GitHubのコミット履歴にはメールアドレスが埋め込まれており、誰でも確認できる。スパム対策として、過去のコミット履歴を書き換えつつ、今後のコミットにはno-replyアドレスを使うようにした。 GitHub Settings → Emails に表示されている以下の形式のアドレスを使う。 今後のコミットに使うよう設定: systemレベルも変えておく(管理者権限が必要):
基本systemレベルでは設定しないため消しておく 通常ないと思うがメールアドレスを使い分けている場合にあり得る Mac/Linux/WSL: Windows: ※Git Bashでやってもいいが、遅いのでPowerShellを推奨。PowerShellは便利なんだけど、記述が長すぎて嫌いだけれども(エイリアスを使うのは非推奨みたいだし)。 ※Pythonが入っている必要があります。 リポジトリ一覧の取得に使う。 Mac: Windows: Linux/WSL: インストール後に認証: 公開リポジトリだけに制限しています。 以下のは書き換えた後force pushまで行います。 以下 を書きかえてください。
なお PowerShellのスクリプト実行ポリシーをセッション限りで緩和しておく(管理者権限不要): スクリプト本体:
背景
ちなみに2014年くらい前からGitHubでno-replyのアドレスが設定できるようになった。やりたいこと
--name-callbackで条件書けばできる)。
方針
git-filter-repo で一括書き換え
no-replyアドレスの確認
12345678+username@users.noreply.github.com
git config --global user.email "12345678+username@users.noreply.github.com"
git config --system --unset user.email
確認
git config --global user.email # 新しいものに変わっていればOK
git config --system user.email # 何も出ない
プロジェクト単位でe-mail設定しているものがあるか探すシェル
find ~ -path "*/.git/config" -exec grep -H "email" {} \;
Get-ChildItem -Path $HOME -Recurse -Force -Filter "config" -ErrorAction SilentlyContinue |
Where-Object { $_.DirectoryName -like "*\.git" } |
Select-String "email" |
Select-Object Path, Line
git-filter-repo のインストール
pip install git-filter-repo
GitHub CLI のインストール
brew install gh
winget install GitHub.cli
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update && sudo apt install gh
gh auth login
一括書き換えスクリプト
注意事項:テストしてから実行してください。責任は負えません。
自分の場合、完全に自分のリポジトリだけだと思ったら、
忘れているのがあって、callbackで条件文を入れず、フォークリポジトリで他の人のユーザ名をかきかえてしまい…
reflogから戻しました。gh repo list $GH_USER --visibility=public --json name --jq '.[].name'
OLD_EMAIL="12345678@example.com"
OLD_USER="username"
NEW_EMAIL="12345678+username@users.noreply.github.com"
GH_USER="username"
HTTPSでリモートのURLを書き換えているのでSSHの場合は適宜書き換えてください。
名前を変えてない限りはOLD_USERはGH_USERと一緒でいいです。Bash版(Mac/WSL/Linux)
#!/bin/bash
OLD_EMAIL="12345678@example.com"
OLD_USER="username"
NEW_EMAIL="12345678+username@users.noreply.github.com"
GH_USER="username"
REPOS=($(gh repo list $GH_USER --visibility=public --json name --jq '.[].name'))
for REPO in "${REPOS[@]}"; do
echo "Processing $REPO..."
git clone "https://github.com/$GH_USER/$REPO.git" "tmp-$REPO"
cd "tmp-$REPO"
git filter-repo --name-callback "return b'$GH_USER' if name == b'$OLD_NAME' else name" --email-callback "return b'$NEW_EMAIL' if email == b'$OLD_EMAIL' else email"
if [ $? -ne 0 ]; then
echo "SKIP: $REPO のfilter-repoに失敗しました"
cd ..
rm -rf "tmp-$REPO"
continue
fi
git remote add origin "https://github.com/$GH_USER/$REPO.git"
git push --force --all
if [ $? -ne 0 ]; then
echo "SKIP: $REPO のpushに失敗しました(protected branch?)"
cd ..
rm -rf "tmp-$REPO"
continue
fi
git push --force --tags
cd ..
rm -rf "tmp-$REPO"
done
PowerShell版(Windows)
Set-ExecutionPolicy -Scope Process RemoteSigned
$OLD_EMAIL="12345678@example.com"
$OLD_USER="username"
$NEW_EMAIL = "12345678+username@users.noreply.github.com"
$GH_USER = "username"
$REPOS = gh repo list $GH_USER --visibility=public --json name --jq '.[].name'
foreach ($REPO in $REPOS) {
Write-Host "Processing $REPO..."
git clone "https://github.com/$GH_USER/$REPO.git" "tmp-$REPO"
Set-Location "tmp-$REPO"
git filter-repo --name-callback "return b'$GH_USER' if name == b'$OLD_NAME' else name" --email-callback "return b'$NEW_EMAIL' if email == b'$OLD_EMAIL' else email"
if ($LASTEXITCODE -ne 0) {
Write-Host "SKIP: $REPO のfilter-repoに失敗しました"
Set-Location ..
Remove-Item -Recurse -Force "tmp-$REPO"
continue
}
git remote add origin "https://github.com/$GH_USER/$REPO.git"
git push --force --all
if ($LASTEXITCODE -ne 0) {
Write-Host "SKIP: $REPO のpushに失敗しました(protected branch?)"
Set-Location ..
Remove-Item -Recurse -Force "tmp-$REPO"
continue
}
git push --force --tags
Set-Location ..
Remove-Item -Recurse -Force "tmp-$REPO"
}
注意点
git filter-repo はclone時のoriginを意図的に削除する(誤push防止のため)。そのため git remote add origin が必要git pull できなくなるため、再cloneが必要git cloneし直すのが良いかと思います。
GitHubのコミット履歴から個人のメールアドレスを消す
スポンサードリンク