我正在使用Python和Git-Python编写一个git post-receive钩子(Hook),该钩子(Hook)收集有关推送中包含的提交的信息,然后用摘要更新我们的错误跟踪器和IM。我在推送创建分支的情况下遇到麻烦(即要接收的fromrev参数全为零)并且还跨越了该分支上的多个提交。我正在从torev提交向后移动 parent 列表,但我不知道如何确定哪个提交是分支中的第一个提交,即何时停止查找。

在命令行上我可以做

git rev-list this-branch ^not-that-branch ^master

这将确切地给我this-branch中的提交列表,没有其他人。我尝试使用Commit.iter_parents方法复制此方法,该方法记录为采用与git-rev-list相同的参数,但据我所知,它不喜欢位置参数,而且我找不到一组关键字有效的参数。

我阅读了Dulwich的doco,但尚不清楚它是否会做与Git-Python截然不同的事情。

我的(简化)代码如下所示。推送开始新分支时,当前仅查看第一次提交,然后停止:
import git
repo = git.Repo('.')
for line in input:
    (fromrev, torev, refname) = line.rstrip().split(' ')
    commit = repo.commit(torev)
    maxdepth = 25    # just so we don't go too far back in the tree
    if fromrev == ('0' * 40):
        maxdepth = 1
    depth = 0
    while depth < maxdepth:
        if commit.hexsha == fromrev:
            # Reached the start of the push
            break
        print '{sha} by {name}: {msg}'.format(
            sha = commit.hexsha[:7], user = commit.author.name, commit.summary)
        commit = commit.parents[0]
        depth += 1

最佳答案

使用纯Git-Python,它也可以完成。我还没有找到一种方法来识别一组一次性使用的kwarg。但是可以简单地构造一组master分支的shas,然后在要检查的分支上使用iter_commits来查找第一个未出现在父分支中的分支:

from git import *

repo_path = '.'
repo = Repo(repo_path)
parent_branch = repo.branches.master
examine_branch = repo.branches.test_feature_branch

other_shas = set()
for parent_commit in repo.iter_commits(rev=parent_branch):
    other_shas.add(parent_commit.hexsha)
for commit in repo.iter_commits(rev=examine_branch):
    if commit.hexsha not in other_shas:
        first_commit = commit

print '%s by %s: %s' % (first_commit.hexsha[:7],
        first_commit.author.name, first_commit.summary)

而且,如果您确实要确保排除所有其他分支上的所有提交,则可以将第一个for循环包装在repo.branches上的另一个for循环中:
other_shas = set()
for branch in repo.branches:
    if branch != examine_branch:
        for commit in repo.iter_commits(rev=branch):
            other_shas.add(commit.hexsha)
  • 警告1:第二种方法显示未出现在任何其他分支上的第一个提交,这不一定是该分支上的第一个提交。如果feat_b从来自master的feat_a分支出来,那么这将在feat_b分支之后显示feat_a上的第一个提交:feat_a的其余提交已经在feat_b上。
  • 警告2:git rev-list和这两个解决方案仅在分支尚未 merge 回master时才起作用。您实际上是在要求它列出该分支上的所有提交,而不列出另一个。
  • 备注:第二种方法过于矫kill,需要花费更多时间才能完成。更好的方法是将其他分支限制为已知 merge 分支的列表,前提是您不仅仅拥有master。
  • 10-07 19:11
    查看更多