JGit:RevWalk 顺序覆盖起点

viv*_*nig 5 java jgit

我正在将 JGit 用于我的一个涉及 git 深入使用的项目。

我的目标是使用 aRevWalk能够按时间顺序迭代存储库中的提交,从特定提交开始。我设法分别实现了这两个目标:

  • 通过应用时间顺序 RevSort.REVERSE
  • 通过调用开始 RevWalk.markStart(RevCommit c)

我的问题是,当我尝试将两者结合起来时,似乎 RevSort 覆盖了 markStart,而 RevWalk 总是在我指定的提交的提交开始处开始。

这个片段显示了我所拥有的:

import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;

import java.io.IOException;
import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.MissingObjectException;

public class Main {

    public static void main(String[] args) throws IOException, AmbiguousObjectException, MissingObjectException {
        final String repositoryPath = args[0];
        final String commitID = args[1];
        final Repository repository = new FileRepository(repositoryPath + "/.git");
        final RevWalk walk = new RevWalk(repository);
        walk.sort(RevSort.REVERSE);
        walk.markStart(walk.parseCommit(repository.resolve(commitID)));
        for (final RevCommit revCommit : walk) {
            System.err.println(revCommit.getId());
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

这应该从指定的提交开始以相反的顺序打印存储库的 ID,但它只是忽略第二个设置并从初始提交开始。

更新:

我已经调查更多的问题,事实证明,在申请时的两个选项(按任意顺序),则markStart变成了markStop。我认为这是由于始终首先执行 markStart 并限制提交的范围(使用过滤器),然后通过RevSort. 基本上,这RevWalk是对我感兴趣的补充提交集进行迭代。

我应该假设我尝试做的事情无法通过这种方式获得吗?如果不遍历整个存储库直到我的起点,我想不出另一种方法来获取它,但这听起来效率极低。

更新 2:在这里给出一个正确的例子是我期望实现的。假设我们有一个包含 4 个提交的存储库:A、B、C 和 D。我只对按时间顺序从 B 到当前修订版(不包括 A)的评论感兴趣。我希望能够通过以下方式使用markStartsort实现这一目标:

@Test
public void testReverse2() throws Exception {
    final RevCommit commitA = this.git.commit().setMessage("Commit A").call();
    final RevCommit commitB = this.git.commit().setMessage("Commit B").call();
    final RevCommit commitC = this.git.commit().setMessage("Commit C").call();
    final RevCommit commitD = this.git.commit().setMessage("Commit D").call();

    final RevWalk revWalk = new RevWalk(this.git.getRepository());
    revWalk.markStart(revWalk.parseCommit(commitB));
    revWalk.sort(RevSort.REVERSE);

    assertEquals(commitB, revWalk.next());
    assertEquals(commitC, revWalk.next());
    assertEquals(commitD, revWalk.next());
    assertNull(revWalk.next());
    revWalk.close();
}
Run Code Online (Sandbox Code Playgroud)

现在,从我所见,这不起作用,因为markStart总是在 之前执行sort,因此实际行为满足以下测试:

assertEquals(commitA, revWalk.next());
assertEquals(commitB, revWalk.next());
assertNull(revWalk.next());
Run Code Online (Sandbox Code Playgroud)

这与我试图获得的相反。这是一种有意的行为,如果是,我还能以什么其他方式来解决这个问题?

Rüd*_*ann 2

在 Git 中,提交仅具有指向其父级的链接。commitB不知道它的继任者commitCcommitD

\n\n

因此,历史只能向后遍历,从给定的提交到其父项、祖父母等。没有信息可以沿相反方向遍历。

\n\n

在您的示例中,RevWalk将从 步行commitBcommit\xc3\x80。排序REVERSE只会影响迭代器的行为,但不能向前移动。

\n\n

commitB如果您确实想查找和之间的提交HEAD,则需要从 开始HEAD。或者,更一般地说,您需要从所有已知的分支提示开始,找到通向 的可能的多个路径commitB

\n