JGit:如何获取一个分支的所有提交记录?(不更改工作目录...)

14

如何使用JGit获取分支的所有提交记录,而不更改工作目录?

不幸的是,JGit文档并不是很好...

在Ruby中使用grit非常容易:

repo = Grit::Repo.new(pathToRepo)

repo.commits(branchName, false).each do |commit|
    doSomethingWithTheCommit
end

再见,hurik

6个回答

16

我先尝试了这个:https://dev59.com/o2PVa4cB1Zd3GeqP5mwn#13925765

但它并不总是有效,所以我找到了这个:http://www.eclipse.org/forums/index.php/t/280339/

这是我的解决方案,虽然不太好看,但是它能工作...

public static void main(String[] args) throws IOException, GitAPIException {
    Repository repo = new FileRepository("pathToRepo/.git");
    Git git = new Git(repo);
    RevWalk walk = new RevWalk(repo);

    List<Ref> branches = git.branchList().call();

    for (Ref branch : branches) {
        String branchName = branch.getName();

        System.out.println("Commits of branch: " + branch.getName());
        System.out.println("-------------------------------------");

        Iterable<RevCommit> commits = git.log().all().call();

        for (RevCommit commit : commits) {
            boolean foundInThisBranch = false;

            RevCommit targetCommit = walk.parseCommit(repo.resolve(
                    commit.getName()));
            for (Map.Entry<String, Ref> e : repo.getAllRefs().entrySet()) {
                if (e.getKey().startsWith(Constants.R_HEADS)) {
                    if (walk.isMergedInto(targetCommit, walk.parseCommit(
                            e.getValue().getObjectId()))) {
                        String foundInBranch = e.getValue().getName();
                        if (branchName.equals(foundInBranch)) {
                            foundInThisBranch = true;
                            break;
                        }
                    }
                }
            }

            if (foundInThisBranch) {
                System.out.println(commit.getName());
                System.out.println(commit.getAuthorIdent().getName());
                System.out.println(new Date(commit.getCommitTime() * 1000L));
                System.out.println(commit.getFullMessage());
            }
        }
    }
}

1
我对这个解决方案有问题,因为在我的相当大的代码库上需要约五分钟才能完成。 - user3495816
请尝试一些其他在此发布的解决方案。 - hurik

16

使用以下代码,您可以获取分支或标记的所有提交

Repository repository = new FileRepository("/path/to/repository/.git");
String treeName = "refs/heads/master"; // tag or branch
for (RevCommit commit : git.log().add(repository.resolve(treeName)).call()) {
    System.out.println(commit.getName());
}

变量treeName将定义标签或分支。这个treeName是分支或标签的完整名称,例如refs/heads/master表示master分支,refs/tags/v1.0表示名为v1.0的标签。

或者,您可以使用gitective API。以下代码与上面的代码相同:

Repository repository = new FileRepository("/path/to/repository/.git");

AndCommitFilter filters = new AndCommitFilter();
CommitListFilter revCommits = new CommitListFilter();
filters.add(revCommits);

CommitFinder finder = new CommitFinder(repository);
finder.setFilter(filters);
String treeName = "refs/heads/master"; // tag or branch
finder.findFrom(treeName);

for (RevCommit commit : revCommits) {
    System.out.println(commit.getName());
}

需要一些try/catch语句,我将它们隐藏起来以便缩短代码。 祝好运。


如果该分支合并了来自多个其他分支/提交的合并,这是否有效? - tgkprog
1
很高兴我的解决方案对你有用,@tgkprog。如果你需要一些jgit的示例代码来帮助你,我建议你看一下这个存储库https://github.com/centic9/jgit-cookbook。 - Felipe Gomes

4
我正在寻找一种列出每个分支下所有提交记录的方法,然后我找到了这个帖子。最终,我做了一些与此处某些答案有所不同的工作。
public static void main(String[] args) throws IOException, GitAPIException {
    Repository repo = new FileRepository("pathToRepo/.git");
    Git git = new Git(repo);

    List<Ref> branches = git.branchList().call();

    for (Ref branch : branches) {
        String branchName = branch.getName();

        System.out.println("Commits of branch: " + branchName);
        System.out.println("-------------------------------------");

        Iterable<RevCommit> commits = git.log().add(repo.resolve(branchName)).call();

        List<RevCommit> commitsList = Lists.newArrayList(commits.iterator());

        for (RevCommit commit : commitsList) {
            System.out.println(commit.getName());
            System.out.println(commit.getAuthorIdent().getName());
            System.out.println(new Date(commit.getCommitTime() * 1000L));
            System.out.println(commit.getFullMessage());
        }
    }

    git.close();
}

感谢您的帮助。

0

这似乎可行,但我原以为添加(ObjectId branch)提供了一个通往活动分支的门,但我似乎需要一个范围

Git git = ...
ObjectId master = git.repository.resolve("refs/heads/master")
ObjectId branch = git.repository.resolve("refs/heads/mybranch")

git.log().addRange(master,branch).call()

0

你说得对,文档应该更好一些。

你可以使用JGit Log命令或者使用像gitective这样的库,使得迭代提交变得容易。你可以查看源代码来了解更多关于JGit的信息。

其他(更复杂)的方法在this SO-question中有描述。


0
一个更加简短和干净的解决方案可以通过JGit提供的“log”命令实现:
    Repository repository = new FileRepository("pathToRepo/.git");
    logs = new Git(repository).log()
            .add(repository.resolve("remotes/origin/testbranch"))
            .call();
    count = 0;
    for (RevCommit rev : logs) {
        System.out.println("Commit: " + rev /* + ", name: " + rev.getName() + ", id: " + rev.getId().getName() */);
        count++;
    }
    System.out.println("Had " + count + " commits overall on test-branch");

请在jgit-cookbook中查看完整代码片段


当我在我的分支上执行此操作时,我会看到它和主分支上的提交。当我使用主分支时,我只能看到它的提交。我期望 "--stop-on-copy" 的行为,但使用 git.log().add(git.repository.resolve("refs/heads/mybranch")).call() 没有看到这种行为。 - Petra Kahn
好的,那么在答案https://dev59.com/mWUo5IYBdhLWcg3wtRXh#35327138中列出的addRange()选项应该可以工作。 - centic
谢谢。我想我需要获取分支头并返回,直到找到一个RevCommit,在其中所有父级都来自另一个分支。沿途的任何提交都可能有来自其他分支的多个父级,但只有一个来自其他分支的父级的提交必须是分支的开头。 - Petra Kahn
我该如何确定我在哪个分支上,并从哪个分支创建?我可以获取 HEAD 然后查找所有分支,但我不知道如何找到我的分支的来源。 - Petra Kahn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接