libgit2 / libgit2/libgit2sharp

Question: Using `RewriteHistory` multiple times on the same commit

未关闭
#2,023 0 条评论 1 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

主要语言
C#
星标
3.5k
派生
925
PR 合并指标
30 天内没有已合并 PR

描述

Hi Folks, This isn't a bug report but a question I have regarding calling the RewriteHistory method on the same commit.

public class Tests
{
    Repository Repository;
    DirectoryInfo RepositoryDirectoryInfo;

    private static void CopyDirectoryContents(string sourcePath, string targetPath)
    {
       // copies repository, containg .git and repository content to a temp path. not important for this.
    }

    private static Repository LoadRepository(string repositoryAbsolutePath)
    {
        return new Repository(repositoryAbsolutePath);
    }

    [SetUp]
    public void Setup()
    {
        // Create a temporary directory
        string temporaryGitRepositoryAbsPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
        RepositoryDirectoryInfo = Directory.CreateDirectory(temporaryGitRepositoryAbsPath);

        // Create a copy of the git Repository fixture as testing will modify the fixture itself
        string fixtureGitRepositoryRelPath = "Fixtures\\SampleGitRepository";
        CopyDirectoryContents(fixtureGitRepositoryRelPath, RepositoryDirectoryInfo.FullName);

        Repository = LoadRepository(RepositoryDirectoryInfo.FullName);
    }

    [Test]
    public void Test1()
    {
        // Get the commits and grab the first one
        List<Commit> firstCommits = Repository.Commits.ToList();
        Commit firstChangeToFirstCommit = firstCommits.First();

        // Rewrite commit. Change commit message.
        GitRewriter.RewriteCommit(
            repository: Repository,
            commit: firstChangeToFirstCommit,
            author: firstChangeToFirstCommit.Author,
            committer: firstChangeToFirstCommit.Committer,
            commitMessage: "first change to commit message"
        );

        // Not sure if required (I dont think it is)
        Repository.Reset(ResetMode.Hard, Repository.Head.Tip);

        // Reload Repository thats changed.
        // a.k.a return new Repository("the abs path of the repository");
        Repository = LoadRepository(RepositoryDirectoryInfo.FullName);

        // Get the commits again, and grab the first one like before
        List<Commit> secondCommits = Repository.Commits.ToList();
        Commit secondChangeToFirstCommit = secondCommits.First();

        // Rewrite a second time
        GitRewriter.RewriteCommit(
            repository: Repository,
            commit: secondChangeToFirstCommit,
            author: secondChangeToFirstCommit.Author,
            committer: secondChangeToFirstCommit.Committer,
            commitMessage: "second change to commit message"
        );
    }
}
public class GitRewriter
{
  public static void RewriteCommits(Repository repository, Commit[] commits, Signature author, Signature committer, string commitMessage)
  {
      RewriteHistoryOptions options = new()
      {
          OnError = (error) => ... ,
          OnSucceeding = () => ... ,
          CommitHeaderRewriter = commit =>
          {
              return CommitRewriteInfo.From(
                  commit: commit,
                  author: author,
                  committer: committer,
                  message: commitMessage
              );
          }
      };
      repository.Refs.RewriteHistory(options, commits);
  }
  public static void RewriteCommit(Repository repository, Commit commit, Signature author, Signature committer, string commitMessage)
  {
      Commit[] singleCommit = new Commit[] { commit };
      RewriteCommits(
          repository: repository,
          commits: singleCommit,
          author: author,
          committer: committer,
          commitMessage: commitMessage
      );
  }
}

If you look at my test case Test1, I'm trying to use RewriteHistory on the same commit, twice.

The first rewrite works fine.

On the second attempt, I get the exception: Can't back up reference 'refs/heads/master' - 'refs/original/heads/master' already exists

Message: 
System.InvalidOperationException : Can't back up reference 'refs/heads/master' - 'refs/original/heads/master' already exists

Stack Trace: 
HistoryRewriter.RewriteReference[TRef,TTarget](TRef oldRef, Func`2 selectTarget, Func`2 rewriteTarget, ReferenceUpdater`2 updateTarget)
HistoryRewriter.RewriteReference(Reference reference)
HistoryRewriter.Execute()
ReferenceCollection.RewriteHistory(RewriteHistoryOptions options, IEnumerable`1 commitsToRewrite)
ReferenceCollection.RewriteHistory(RewriteHistoryOptions options, Commit[] commitsToRewrite)
GitRewriter.RewriteCommit(Repository repository, Commit[] commits, Signature author, Signature committer, String commitMessage) line 29
GitRewriter.RewriteCommit(Repository repository, Commit commit, Signature author, Signature committer, String commitMessage) line 34
Tests.Test1() line 168
RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)

I'm aware that when a commit is changed, a new SHA is allocated to that changed commit, and when after I've changed the commit the first time, the SHA does indeed change, but when I attempt to change it the second time, using the changed SHA, I recieve the error as described above.

I've checked the examples of LibGit2 and I could not find anything specific regarding this use-case of changing the same commit twice.

I've tried 'reloading' the repository by created a new Repository but no dice.

Any help, tips or pointers to documentation would be greatly appreciated. Thank you,

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 ReferenceCollection.RewriteHistory 和 HistoryRewriter.RewriteReference 开始,按照 Test1 序列跟踪到 GitRewriter.RewriteCommit。检查 refs/heads/master 和 refs/original/heads/master 在多次重写之间是如何备份的。完成标准是确定是否支持重复重写,并记录现有备份引用所需的行为或解决方案。

由索引模型根据 Issue 内容生成。

评估

技术栈
csharp, git
领域
devtools
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
需要澄清
新手友好度
25/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。