我正在使用JGit进行涉及git的广泛使用的项目。
我的目标是使用RevWalk
能够按时间顺序迭代存储库中的提交,从特定的提交开始。我已经成功地实现了这两个目标:
RevSort.REVERSE
RevWalk.markStart(RevCommit c)
我的问题是,当我尝试将两者结合起来时,似乎RevSort会覆盖markStart,并且RevWalk总是从我已经指定的提交的提交开始处开始。< / p>
这段代码展示了我的所作所为:
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.我希望能够使用markStart
和sort
以下列方式实现这一目标:
@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());
这与我试图获得的相反。 这是一种有意的行为,如果是这样,我可以用其他方式解决问题吗?
答案 0 :(得分:1)
在Git中,提交只有父母的链接。 commitB
不知道其后继者commitC
和commitD
。
因此,历史记录只能遍历向后,从给定的提交到其父级,宏大的事务等等。没有信息可以在相反的方向上遍历。
在您的示例中,RevWalk
将从commitB
走到commitÀ
。 REVERSE
排序只会影响迭代器的行为方式但不能前进。
如果您确实想要查找commitB
和HEAD
之间的提交,则需要从HEAD
开始。或者,更一般地说,您需要从所有已知的分支提示开始,以找到可能导致commitB
的多个路径。
答案 1 :(得分:0)
JGit API没有提供组合sort和markStart的禁忌症。 JGit源代码也没有显示表面问题。在我看来,直接修复它需要源级调试。您需要JGit源代码并需要在调试器中运行您的示例。
或者,您可以使用Spliterator对RevWalk进行流式处理,而无需按照RevCommit:getCommitTime()对排序输出进行比较,如下所示:
StreamSupport.stream(walk.spliterator())
.sorted(RevCommit::getCommitTime())
.toList();