1

我们正在尝试获取 Gitlab 存储库中每个文件的提交。我们正在使用 Python Gitlab 模块。我们可以获取存储库的提交,但无法获取存储库中单个文件的提交。有人可以帮助我们吗?

4

1 回答 1

3

单个文件的提交历史不会直接通过 GitLab API 公开。因此,python-gitlabgitlab模块中没有直接的功能。

但是,您可以通过使用可用的 API 有效地获取相同的信息。具体来说,您可以使用存储库提交 API和差异 API 或文件责备 API

使用提交 API

例如,使用提交 API,您可以列出所有提交及其差异,然后为每个提交关联文件更改。

import gitlab
from collections import defaultdict
TOKEN = 'Your API Token'
gl = gitlab.Gitlab('https://gitlab.example.com', private_token=TOKEN)

project = gl.projects.get(1234)
commits = project.commits.list(all=True)

# file paths and a list of commits which create/modify/delete the file
file_map = defaultdict(list)

for c in commits:
    diff = c.diff()
    files_changed = set()
    for change in diff:
        files_changed.add(change['old_path'])
        files_changed.add(change['new_path'])
    for path in files_changed:
        file_map[path].append(c)

#  show list of commits which modified README.md
print(file_map['README.md'])

使用责备 API

使用提交 API 需要获取每个提交的差异,这在大型存储库上可能需要很长时间。

如果您只对更改单个文件的提交感兴趣,那么遍历责备树可能会更有效。但是,请注意,您也可能会错过使用此方法的提交(例如,其他分支或分支树中的提交)。

def search_blame(project, filename, base_ref=None):
    if base_ref is None:
        base_ref = project.default_branch
    commits = set()
    refs_to_check = [base_ref,]
    seen = set()
    while refs_to_check:
        ref = refs_to_check.pop()
        if ref in seen:
            continue
        seen.add(ref)
        blame = project.files.blame(filename, ref)
        for change in blame:
            commit_id = change['commit']['id']
            if commit_id not in seen:
                refs_to_check.append(commit_id)
                refs_to_check.extend(change['commit']['parent_ids'])
                for c in change['commit']['parent_ids']:
                    commits.add(c)
            commits.add(commit_id)
    return commits

# show commits in blame tree for README.md
# only includes commits in the default branch
print(search_blame(project, 'README.md'))
于 2022-01-19T19:45:10.250 回答