关于 author-contributions
author-contributions 是面向代码审查与分支分析的技能,用于识别指定作者在分支合并差异中的文件贡献。它追踪跨多次重命名的文件,并以表格汇总状态和行数变化。
主要功能
- 01核对作者的 Git 身份
- 02汇总作者提交涉及的文件
- 03跨提交追踪文件重命名
- 04仅筛选合并差异中的文件
- 05输出文件状态及行数统计
适用场景
- 01审查分支合并时某位作者的贡献
- 02追踪作者修改后经重命名的文件
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ microsoft/ vscode --skill author-contributions安装后在 Claude Code 中输入/author-contributions确认已加载。
详细介绍
当被要求查找某位作者在某个分支上(与 main 或其他上游分支相比)参与过的所有文件时,请按以下流程操作。目标是生成一个简单的表格,便于人类和大模型读取。
作为子 Agent 运行
此技能需要依次运行许多 git 命令。请将其委派给子 Agent,并使用类似以下提示词:
找出作者“Full Name”在分支
<branch>上相较于<upstream>参与过的每个文件。追踪文件重命名前的贡献。返回一个 Markdown 表格,列包括:状态(DIRECT 或 VIA_RENAME)、文件路径和行数(+/-)。最后附上一行摘要。
流程
1. 确定作者准确的 git 身份
git log --format="%an <%ae>" <upstream>..<branch> | sort -u
将请求中的人员与其准确的 --author= 字符串匹配。不要猜测——简短的用户名可能无法匹配完整的显示名称(请通过 git log 或 GitHub MCP get_me 工具进行确认)。
2. 收集作者直接提交过的所有文件
git log --author="<Exact Name>" --format="%H" <upstream>..<branch>
对于每个提交哈希,提取涉及的文件:
git diff-tree --no-commit-id --name-only -r <hash>
将所有结果合并为一个集合(author_files)。
3. 构建整个分支的重命名映射
对分支上的每个提交(不只是作者的提交)提取重命名:
git diff-tree --no-commit-id -r -M <hash>
解析状态为 R 的行,构建映射:new_path → {old_paths}。
4. 获取合并差异中的文件列表
git diff --name-only <upstream>..<branch>
这些文件将在分支合并时实际进入上游。
5. 对合并差异中的每个文件进行分类
对于步骤 4 中的每个文件:
- 如果它在
author_files中 → DIRECT - 否则,沿重命名映射进行传递追踪(沿链追踪:当前路径 → 旧路径 → 更早的路径),检查是否有任何祖先路径在
author_files中 → VIA_RENAME - 否则,该文件不属于此作者的贡献
6. 获取差异统计信息
git diff --stat <upstream>..<branch> -- <file1> <file2> ...
7. 返回表格
将结果格式化为 Markdown 表格:
| Status | File | +/- |
|--------|------|-----|
| DIRECT | src/vs/foo/bar.ts | +120/-5 |
| VIA_RENAME | src/vs/baz/qux.ts | +300 |
| ... | ... | ... |
**Total: N files, +X/-Y lines**
重要说明
- 使用 Python 处理繁重工作。 在 zsh 中,带内联注释的 Shell 循环会出错。请编写临时
.py脚本,运行后再删除。 - 作者匹配必须精确。 始终先运行步骤 1。
--author会进行子字符串匹配,但必须确认匹配的是正确的人(例如,查找“Josh S.”时不要匹配到“Joshua Smith”)。请使用 GitHub MCPget_me工具或git log输出确认正确的全名。 - 重命名可能经过多次转换。 文件可能从
contrib/chat/移动到agentSessions/,再移动到sessions/。必须沿重命名映射进行传递追踪。 - 只报告合并差异中的文件(步骤 4)。作者参与过但之后被彻底删除的文件不应出现——它们不会进入上游。
- 重命名映射必须包含所有作者的提交,不能只包含目标作者的提交。其他人经常负责重命名提交(例如批量重构或移动文件)。
Python 脚本示例
import subprocess, os
os.chdir('<repo_root>')
UPSTREAM = 'main'
AUTHOR = '<Author Name>' # Resolve via `git log` or GitHub MCP `get_me`
# Step 2: author's files
commits = subprocess.check_output(
['git', 'log', f'--author={AUTHOR}', '--format=%H', f'{UPSTREAM}..HEAD'],
text=True).strip().split('\n')
author_files = set()
for h in (c for c in commits if c):
files = subprocess.check_output(
['git', 'diff-tree', '--no-commit-id', '--name-only', '-r', h],
text=True).strip().split('\n')
author_files.update(f for f in files if f)
# Step 3: rename map from ALL commits
all_commits = subprocess.check_output(
['git', 'log', '--format=%H', f'{UPSTREAM}..HEAD'],
text=True).strip().split('\n')
rename_map = {} # new_name -> set(old_names)
for h in (c for c in all_commits if c):
out = subprocess.check_output(
['git', 'diff-tree', '--no-commit-id', '-r', '-M', h],
text=True, timeout=5).strip()
for line in out.split('\n'):
if not line:
continue
parts = line.split('\t')
if len(parts) >= 3 and 'R' in parts[0]:
rename_map.setdefault(parts[2], set()).add(parts[1])
# Step 4: merge diff
diff_files = subprocess.check_output(
['git', 'diff', '--name-only', f'{UPSTREAM}..HEAD'],
text=True).strip().split('\n')
# Step 5: classify
results = []
for f in (x for x in diff_files if x):
if f in author_files:
results.append(('DIRECT', f))
else:
# walk rename chain
chain, to_check = set(), [f]
while to_check:
cur = to_check.pop()
if cur in chain:
continue
chain.add(cur)
to_check.extend(rename_map.get(cur, []))
chain.discard(f)
if chain & author_files:
results.append(('VIA_RENAME', f))
# Step 6: stats
if results:
stat = subprocess.check_output(
['git', 'diff', '--stat', f'{UPSTREAM}..HEAD', '--'] +
[f for _, f in results], text=True)
print(stat)
# Step 7: table
for kind, f in sorted(results, key=lambda x: x[1]):
print(f'| {kind:12s} | {f} |')
print(f'\nTotal: {len(results)} files')
替代脚本
完成上述流程后,运行此脚本,对照分支差异交叉检查作者参与过的文件。可以同时检查包含和不包含 src/vs/sessions 的情况。
AUTHOR=""
# 1. Find commits by author on this branch (not on main)
git log main...HEAD --author="$AUTHOR" --format="%H"
# 2. Get unique files touched across all those commits, excluding src/vs/sessions/
git log main...HEAD --author="$AUTHOR" --format="%H" \
| xargs -I{} git diff-tree --no-commit-id -r --name-only {} \
| sort -u \
| grep -v '^src/vs/sessions/'
# 3. Cross-reference with branch diff to keep only files still changed vs main
git log main...HEAD --author="$AUTHOR" --format="%H" \
| xargs -I{} git diff-tree --no-commit-id -r --name-only {} \
| sort -u \
| grep -v '^src/vs/sessions/' \
| while read f; do git diff main...HEAD --name-only -- "$f" 2>/dev/null; done \
| sort -u
评论
支持 Markdown