git filter-branch 已被弃用,应改用 git rebase(小范围)或 git filter-repo(全量);前者通过 git rebase -i head~n 配合 git commit --amend --author 修改近期提交,后者需安装并用 --mailmap 统一重写历史。

filter-branch 已被弃用,别再用它改作者信息
Git 官方在 2.22 版本起明确标记 git filter-branch 为“deprecated”,它不仅慢、难调试,还容易损坏引用(比如丢失合并提交、破坏 GPG 签名)。现在标准做法是用 git rebase(小范围)或 git filter-repo(全量历史重写)。
小范围修改:用 git rebase -i 改最近几次提交的 author
只改最近 3 次提交?git rebase -i HEAD~3 最直接。它不会动远古提交,也不影响协作分支结构,适合本地未推送或刚推错邮箱的场景。
- 运行
git rebase -i HEAD~3,把要改的提交前的pick改成edit - 保存退出后,Git 会停在第一个
edit提交,此时执行:git commit --amend --author="Name <email>" --no-edit</email> - 再执行
git rebase --continue,重复到所有目标提交处理完 - 如果已推送到远程,需强制推送:
git push --force-with-lease origin main(注意不是--force)
⚠️ 常见错误:漏掉 --no-edit 导致打开编辑器、误改 commit message;或者用 --reset-author(它会覆盖成当前 config 的 user,不是你想要的)。
全量重写历史:用 git filter-repo 替代 filter-branch
git filter-repo 是官方推荐替代品,速度快、语义清晰、默认保留标签和 refs。它不依赖 shell 脚本,出错时也更容易中断和恢复。
- 先安装:
pip install git-filter-repo(确保 pip 是 Python 3.7+) - 备份当前分支:
git branch backup-before-filter(这步不能跳) - 执行邮箱替换(全局改 author 和 committer):
git filter-repo --mailmap .mailmap,其中.mailmap文件内容形如:Correct Name <correct> Bad Name <bad></bad></correct>
- 如果只是简单统一替换,可用:
git filter-repo --mailmap Old Name <old>")</old>
⚠️ 注意:运行后所有 commit hash 都会变,本地分支指针会失效,必须用 git checkout -B main 重建分支;远程需 git push --force-with-lease --all + --tags 同步。
改完之后,怎么避免下次再错?
历史能修,但源头不堵,下次照样错。关键不是“怎么修”,而是“怎么让 Git 记住正确的 identity”。
- 检查当前配置:
git config --list | grep user,确认没有残留的user.email在~/.gitconfig或项目级.git/config里冲突 - 多账号用户建议:用
includeIf条件加载配置,例如在~/.gitconfig里加:[includeIf "gitdir:~/work/"]<br> path = ~/work/.gitconfig-work<br>[includeIf "gitdir:~/personal/"]<br> path = ~/personal/.gitconfig-personal
- 提交前快速验证:
git log -1 --pretty=format:"%an | %cn ",对比 author(%an/%ae)和 committer(%cn/%ce),两者应一致——除非你真在用GIT_AUTHOR_*环境变量临时覆盖
真正麻烦的从来不是改历史,而是改完发现 CI 流水线里某个脚本硬编码了旧邮箱,或者某条 git blame 引用的 commit 已失效。动手前,先想清楚谁还在依赖这些哈希值。











