5

Python と Git-Python を使用して、プッシュに含まれるコミットに関する情報を収集し、バグ トラッカーと IM を要約で更新する git post-receive フックを作成しています。プッシュがブランチを作成し (つまり、fromrevpost-receive へのパラメーターがすべてゼロである)、そのブランチで複数のコミットにまたがる場合に問題が発生します。親のリストをコミットからさかのぼって歩いていますが、torevどのコミットがブランチの最初のコミットであるか、つまりいつ見るのをやめるべきかを判断する方法がわかりません。

コマンドラインでできること

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

これにより、 のコミットのリストが正確に表示されthis-branch、他には表示されません。git-rev-list と同じパラメーターを取るように文書化されている方法を使用してこれを複製しようとしましたCommit.iter_parentsが、私が見る限り位置パラメーターが好きではなく、キーワードパラメーターのセットが見つかりませんその仕事。

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
4

3 に答える 3

2

私はダルウィッチで遊んだだけですが、これを行うにはもっと良い方法があるかもしれません(ビルトインのウォーカーを使って?)。新しいブランチが 1 つだけ (または共通点のない複数の新しいブランチ) あると仮定します。

#!/usr/bin/env python
import sys
from dulwich.repo import Repo
from dulwich.objects import ZERO_SHA


def walk(repo, sha, shas, callback=None, depth=100):
    if not sha in shas and depth > 0:
        shas.add(sha)

        if callback:
            callback(sha)

        for parent in repo.commit(sha).parents:
            walk(repo, parent, shas, callback, depth - 1)


def reachable_from_other_branches(repo, this_branch):
    shas = set()

    for branch in repo.refs.keys():
        if branch.startswith("refs/heads") and branch != this_branch:
            walk(repo, repo.refs[branch], shas)

    return shas


def branch_commits(repo, fromrev, torev, branchname):
    if fromrev == ZERO_SHA:
        ends = reachable_from_other_branches(repo, branchname)
    else:
        ends = set([fromrev])

    def print_callback(sha):
        commit = repo.commit(sha)
        msg = commit.message.split("\n")[0]
        print('{sha} by {author}: {msg}'
              .format(sha=sha[:7], author=commit.author, msg=msg))

    print(branchname)
    walk(repo, torev, ends, print_callback)


repo = Repo(".")
for line in sys.stdin:
    fromrev, torev, refname = line.rstrip().split(' ')
    branch_commits(repo, fromrev, torev, refname)
于 2013-08-29T16:50:26.463 に答える
1

このようなものは最初のコミットを見つけます:

x = Repo('.')
print list(x.get_walker(include=[x.head()]))[-1].commit

(これは大規模なリポジトリに O(n) メモリを使用することに注意してください。それを回避するにはイテレータを使用してください)

于 2013-10-27T08:38:48.353 に答える