在使用 git filter-repo 重写 Git 历史时,很多人会遇到一个隐蔽但常见的逻辑问题:
- 只修改了
author_name或committer_name - 作者(author)和提交人(committer)被设置成了不同的名字
- 只匹配了一个邮箱,导致另一部分提交没有被修改
本文将给出一个正确、可复用的方案:
只要邮箱匹配
xxxxxx@163.com,就把作者和提交人统一改成michah(名字和邮箱都可统一)。
一、问题背景
在 Git 中,一次提交包含两套身份信息:
- Author(作者):实际编写代码的人
- Committer(提交人) :执行
git commit的人
它们分别对应:
author_name/author_emailcommitter_name/committer_email
如果在脚本中只修改其中一个,或者给两者设置了不同的名字,就会导致历史记录混乱。
二、正确目标
✅ 目标非常明确:
- 只要提交中的邮箱是
xxxxxx@163.com - 无论是 author 还是 committer
- 统一修改为:
text
michah <michah@example.com>
(如果你想保留原邮箱,只改名字,也可以做到,后文会说明)
三、修正后的 git-filter-repo 脚本(推荐)
bash
git filter-repo --force --commit-callback '
target_email = b"xxxxxx@163.com"
new_name = b"michah"
new_email = b"michah@example.com" # 可选,也可保持原邮箱
if commit.author_email == target_email:
commit.author_name = new_name
commit.author_email = new_email
if commit.committer_email == target_email:
commit.committer_name = new_name
commit.committer_email = new_email
'
关键点说明
- 只判断邮箱,不判断名字(邮箱才是稳定标识)
- author 和 committer 分别独立判断、分别修改
- 名字和邮箱保持一致,避免历史中出现"一个人多个身份"
四、如果你只想改名字,不改邮箱
把脚本中的这一行:
python
new_email = b"michah@example.com"
改成:
python
new_email = target_email
即可。
五、修改前 vs 修改后对比
| 字段 | 修改前 | 修改后 |
|---|---|---|
| author_name | xingming | michah |
| author_email | xxxxxx@163.com | michah@example.com |
| committer_name | 其他名字 | michah |
| committer_email | xxxxxx@163.com | michah@example.com |
六、修改完成后的校验方式(非常重要)
执行以下命令,确认历史中不再出现旧身份:
bash
git log --format='%an <%ae>' | sort | uniq
bash
git log --format='%cn <%ce>' | sort | uniq
如果输出中只剩下 michah,说明修改是成功的。
七、设置当前仓库的默认提交用户
⚠️ 注意:这一步 不会影响历史提交 ,只作用于未来的提交。
bash
git config user.name "michah"
如果你希望对当前用户下的所有仓库生效:
bash
git config --global user.name "michah"
git config --global user.email "michah@example.com"
八、重要提醒
git filter-repo会重写整个仓库历史- 如果仓库已经推送到远程,需要:
bash
git push --force --all
git push --force --tags
- 协作仓库请提前沟通,避免影响他人
九、总结
✔ 用邮箱作为唯一判断条件
✔ author / committer 必须同时处理
✔ 名字和邮箱保持统一
这是最干净、最不容易出问题的 Git 历史重写方式。