应优先用 git rebase -i head~3 修改最近3次提交的 author,或用 git filter-repo 全量重写历史;禁用已弃用的 git filter-branch。

别用 git filter-branch,它从 Git 2.22 开始就被官方标记为 deprecated,容易丢合并提交、破坏 GPG 签名,且调试困难。现在只分两种情况处理:改最近几条(用 git rebase -i),或全量重写(用 git filter-repo)。
改最近 3 次提交的 author:用 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 会继续停到下一个edit提交,重复上一步 - 全部改完后,如果已推送到远程,必须用
git push --force-with-lease origin main(不是--force)
⚠️ 常见坑:--no-edit 必须加,否则会打开编辑器让你改 message;--reset-author 是错的,它会覆盖成当前 git config user.* 的值,不是你指定的值。
全量替换所有历史中的邮箱和名字:用 git filter-repo
适用于换公司、统一署名、清理多个旧邮箱等场景。它比 filter-branch 快 10 倍以上,语义清晰,出错可中断恢复,且默认保留标签和 refs。
- 先安装:
pip install git-filter-repo(macOS 可用brew install git-filter-repo) - 准备一个
.mailmap文件,内容形如:Correct Name <correct> Wrong Name <wrong></wrong></correct>
一行一条映射,支持正则和通配 - 执行:
git filter-repo --mailmap .mailmap - 运行后所有 commit hash 都会变,本地分支指针失效,必须重建:
git checkout -B main - 远程强制推送:
git push --force-with-lease --all && git push --force-with-lease --tags
⚠️ 注意:filter-repo 不接受 --force 参数,也不读取 .git/config 里的配置,它只认 --mailmap 或命令行参数(如 --mailmap "Old <old>" "New <new>"</new></old>)。
为什么改完还会再错?源头没堵住
修历史只是补救,真正该做的是让 Git 记住正确的 identity。
- 检查当前生效的配置:
git config --list | grep user,确认没有项目级.git/config里残留的user.email冲突全局设置 - 全局设对:
git config --global user.name "Your Name"和git config --global user.email "you@company.com" - 如果用 IDE(如 IntelliJ / VS Code),还要关掉「Use credentials from system keychain」之类自动填邮箱的选项,否则它可能绕过 Git 配置直接读系统账户
- Azure DevOps / GitHub Web 编辑也会用自己的 profile 生成提交,那部分不受本地 Git 配置控制,得去对应平台的个人资料页单独改
commit hash 变了、远程要强推、协作分支需同步——这些不是“额外步骤”,而是重写历史的必然代价。别跳过验证:改完立刻 git log -10 --pretty="%h %an %s" 看效果,再决定是否推。











