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

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

  • 通过应用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());
            }
        }
    
    }
    

    这应该从指定的提交开始以相反的顺序打印存储库的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();
    }
    

    现在,从我所看到的结果来看,这是行不通的,因为markStart总是在sort之前执行,因此实际行为满足以下测试:
    assertEquals(commitA, revWalk.next());
    assertEquals(commitB, revWalk.next());
    assertNull(revWalk.next());
    

    那与我试图获得的相反。
    这是否是故意的行为,如果是,我还可以通过其他什么方式解决问题?

    最佳答案

    在Git中,提交仅具有指向其父级的链接。 commitB不知道其后续版本commitCcommitD

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

    在您的示例中,RevWalk将从commitB移到commitÀREVERSE排序只会影响迭代器的行为,但不能向前移动。

    如果您实际上想查找commitBHEAD之间的提交,则需要从HEAD开始。或者,更一般地说,您需要从所有已知的分支技巧开始,以找到可能导致commitB的多个路径。

    10-05 20:23