【问题标题】:GitPython: get list of remote commits not yet appliedGitPython:获取尚未应用的远程提交列表
【发布时间】:2011-11-28 00:16:03
【问题描述】:

我正在编写一个 Python 脚本来获取即将由 git pull 操作应用的提交列表。优秀的GitPython library 是一个很好的开始,但是 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 合并,它提出了这个问题,所以我的脚本不起作用。

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

是否有另一种方法可以让我到达那里,我正在用锤子钉螺丝?

【问题讨论】:

    标签: python git gitpython


    【解决方案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 个),以避免进入 repo 的末尾。我还事先检查了本地仓库不在远程仓库之前。除此之外,它工作得很好!现在我可以提醒所有提交作者他们的更改正在被合并。

    【讨论】:

      【解决方案2】:

      我知道这已经年龄老了,但我只是为了一个项目而这样做......

      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}')

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-01-25
        • 1970-01-01
        • 2015-11-04
        • 2012-12-29
        • 2020-03-13
        • 1970-01-01
        • 2015-04-05
        相关资源
        最近更新 更多