author-contributions について
author-contributionsは、特定の作者によるブランチ上のファイル変更を調べるスキルです。ファイルのリネームをたどり、マージ差分に含まれるファイルと貢献状況、行数を表にまとめます。
主な機能
- 01作者のGit IDを確認
- 02作者のコミット対象ファイルを収集
- 03コミットをまたいでリネームを追跡
- 04マージ差分内のファイルに限定
- 05状態と行数を一覧表示
活用シーン
- 01ブランチのマージにおける作者の貢献を確認
- 02作者の変更に由来するリネーム後のファイルを特定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ vscode --skill author-contributionsインストール後、Claude Code で/author-contributionsを入力して読み込まれたか確認します。
詳細
特定のブランチで特定の作者が変更したすべてのファイルを検索するよう依頼された場合(main または別の上流ブランチと比較)、次の手順に従います。目的は、人間と LLM の両方が利用できるシンプルな表を作成することです。
サブエージェントとして実行
このスキルでは git コマンドを順番に多数実行する必要があります。次のようなプロンプトでサブエージェントに委任してください。
ブランチ
<branch>で<upstream>と比較して、作者「Full Name」が変更したすべてのファイルを検索してください。ファイル名の変更をたどって変更内容を追跡してください。列が Status(DIRECT または VIA_RENAME)、File Path、Lines(+/-)のマークダウン表を返してください。最後に要約行を付けてください。
手順
1. 作者の正確な git ID を特定する
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. 表を返す
結果をマークダウン表として整形します。
| 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 で正しく動作しません。一時的な
.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