JGit检测工作副本中的重命名

时间:2013-06-25 11:38:41

标签: java git jgit

Contex的

我正在尝试在工作副本中检测上次提交后发生的可能的文件重命名。 在我的例子中,我有一个干净的工作副本,我这样做:

git mv old.txt new.txt

正在运行$ git status会显示预期结果:

# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       renamed:    old.txt -> new.txt

我试过

使用StatusCommand,我可以在已删除的列表中看到 old.txt ,并在添加的列表中看到 new.txt 。 但我找不到将它们联系在一起的方法。

我知道RenameDetector的存在,但它使用DiffEntry,我不知道如何在 HEAD 工作副本。

2 个答案:

答案 0 :(得分:7)

没关系,找到了答案。 JGit的API非常复杂..

TreeWalk tw = new TreeWalk(repository);
tw.setRecursive(true);
tw.addTree(CommitUtils.getHead(repository).getTree());
tw.addTree(new FileTreeIterator(repository));

RenameDetector rd = new RenameDetector(repository);
rd.addAll(DiffEntry.scan(tw));

List<DiffEntry> lde = rd.compute(tw.getObjectReader(), null);
for (DiffEntry de : lde) {
    if (de.getScore() >= rd.getRenameScore()) {
        System.out.println("file: " + de.getOldPath() + " copied/moved to: " + de.getNewPath());
    }
}

(此代码段也使用Gitective库)

答案 1 :(得分:0)

如果有人想在获取DiffEntry时使用路径过滤器,则应提供新旧路径。

 List<DiffEntry> diffs = git.diff()
            .setOldTree(prepareTreeParser(repository, oldCommit))
            .setNewTree(prepareTreeParser(repository, newCommit))
            .setPathFilter(PathFilterGroup.createFromStrings(new String[]{"new/b.txt","b.txt"}))
            .call();
 RenameDetector rd = new RenameDetector(repository);
 rd.addAll(diffs);
 diffs = rd.compute();

如果你想要树解析器方法的代码:

 private static AbstractTreeIterator prepareTreeParser(Repository repository, String objectId) throws IOException {
    try (RevWalk walk = new RevWalk(repository)) {
      RevCommit commit = walk.parseCommit(repository.resolve(objectId));
      RevTree tree = walk.parseTree(commit.getTree().getId());
      CanonicalTreeParser treeParser = new CanonicalTreeParser();
      try (ObjectReader reader = repository.newObjectReader()) {
           treeParser.reset(reader, tree.getId());
      }
      walk.dispose();
      return treeParser;
    }
}