3

操作によって適用されようとしているコミットのリストを取得する 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ます。これはうまく機能していますが、次の問題があります。

  • ローカル コミットがリモート コミットより先にある場合、私のコードはすべてのコミットを最初に出力します。
  • リモート コミットは複数の親を持つことができ、ローカル コミットは 2 番目の親になることができます。これは、私のコードがリモート リポジトリでローカル コミットを見つけられないことを意味します。

ローカルリポジトリの背後にあるリモートリポジトリに対処できます。同時に反対方向(ローカルからリモート)を見ると、コードが乱雑になりますが、機能します。しかし、この最後の問題は私を殺しています: ローカル コミットに一致するものを見つけるために、(潜在的に無制限の) ツリーをナビゲートする必要があります。これは単なる理論的なものではありません。私の最新の変更は、まさにこの問題を引き起こすレポ マージであったため、スクリプトが機能していません。

ローカル リポジトリの場合のように、リモート リポジトリでコミットの順序付きリストを取得するrepo.iter_commits()と、非常に役立ちます。しかし、私はドキュメントでそれを行う方法を見つけていません。リモート リポジトリの Repo オブジェクトを取得できますか?

そこに到達する可能性のある別のアプローチはありますか?ハンマーを使用してネジを釘付けにしていますか?

4

2 に答える 2

1

コミットのツリーは常にこのようなものであることに気付きました: 1 つのコミットには 2 つの親があり、両方の親には同じ親があります。これは、最初のコミットには 2 つの親があり、祖父母は 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()は、2 人の親と複数の祖父母がいる場合にアラートを出します。これで、マージされていないコミットを繰り返すのは簡単なことです。

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

明確にするために、いくつかの詳細を省略しました。リポジトリの最後に行かないようにするために、事前に設定された数 (私の場合は 20) を超えるコミットを返すことはありません。また、ローカル リポジトリがリモート リポジトリよりも進んでいないことも事前に確認します。それ以外は、うまく機能しています!これで、変更がマージされていることをすべてのコミット作成者に警告できます。

于 2011-11-28T14:02:19.473 に答える