GitPython:获取尚未应用的远程提交列表

4
我正在编写一个Python脚本,用于获取将要应用的提交列表,这些提交将通过git pull操作应用。优秀的GitPython库是一个很好的起点,但是git的微妙内部工作方式令我困扰。现在,这是我目前拥有的(简化和注释版本):
repo = git.Repo(path)                           # get the local repo
local_commit = repo.commit()                    # latest local commit 
remote = git.remote.Remote(repo, 'origin')      # remote repo
info = remote.fetch()[0]                        # fetch changes
remote_commit = info.commit                     # latest remote commit
if local_commit.hexsha == remote_commit.hexsha: # local is updated; end
  return
                                                # for every remote commit
while remote_commit.hexsha != local_commit.hexsha:
  authors.append(remote_commit.author.email)    # note the author
  remote_commit = remote_commit.parents[0]      # navigate up to the parent

基本上,它获取下一次git pull将应用的所有提交的作者。这个功能很好用,但有以下问题:
  • 当本地提交领先于远程时,我的代码只会打印到第一个提交。
  • 远程提交可以有多个父级,而本地提交可以是第二个父级。这意味着我的代码永远无法在远程存储库中找到本地提交。

我可以处理远程存储库落后于本地存储库的情况:同时向另一个方向(本地到远程)查看,代码会变得混乱但可行。但最后一个问题让我疲惫不堪:现在我需要遍历(可能无限的)树来找到与本地提交匹配的内容。这不仅仅是理论上的问题:我的最新更改是一个存储库合并,它出现了这个问题,所以我的脚本不起作用。

获取远程存储库中提交的有序列表,例如repo.iter_commits()对于本地Repo做的那样,将是一个很大的帮助。但我在文档中没有找到如何做到这一点。我可以为Remote存储库获取一个Repo对象吗?

是否有其他方法可以帮助我达到目标,而我却在用锤子钉螺丝?

2个回答

2
我知道这个问题已经很老了,但我为了一个项目不得不这样做... "Original Answer"翻译成中文是"最初的回答"。
head = repo.head.ref
tracking = head.tracking_branch()
return tracking.commit.iter_items(repo, f'{head.path}..{tracking.path}')

最初的回答是:要知道有多少本地提交等待推送,反过来就行了:head.commit.iter_items(repo, f'{tracking.path}..{head.path}')

1

我意识到提交树总是这样的:一个提交有两个父节点,而且两个父节点有同样的父节点。这意味着第一个提交有两个父节点但只有一个祖父节点。

因此编写一个自定义迭代器以遍历提交,包括分叉树并不太难。代码如下:

def repo_changes(commit):
  "Iterator over repository changes starting with the given commit."
  number = 0
  next_parent = None
  yield commit                           # return the first commit itself
  while len(commit.parents) > 0:         # iterate
    same_parent(commit.parents)          # check only one grandparent
    for parent in commit.parents:        # go over all parents
      yield parent                       # return each parent
      next_parent = parent               # for the next iteration
    commit = next_parent                 # start again

same_parent() 函数在存在两个父级和多个祖先时会发出警报。现在迭代未合并的提交非常简单:

for commit in repo_changes(remote_commit):
  if commit.hexsha == local_commit.hexsha:
    return
  authors.append(remote_commit.author.email)

为了清晰起见,我遗漏了一些细节。我从不返回超过预先设定的提交次数(在我的情况下是20),以避免到达仓库的末尾。我还事先检查本地仓库是否落后于远程仓库。除此之外,这个功能非常好用!现在,我可以通知所有提交者,他们的更改正在被合并。


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