使用 filter-repo 修改 git 提交记录

前两天发现有个项目的 git 邮箱写错了，趁今天稍微空些准备祭出祖传的脚本进行修改，谁知出现提示: "git-filter-branch has a glut of gotchas generating mangled history rewrites. Hit Ctrl-C before proceeding to abort, then use an alternative filtering tool such as git filter-repo instead."。既然有新的命令 (方式) 自然要尝试一般。

介绍

git-filter-repo 是一个使用 [[Python]] 编写，用于过滤和转换 [[git]] 存储库历史记录的工具。可以对提交记录进行各种操作，如删除、重写提交历史、拆分存储库等。

安装

macOS 可以通过 [[Homebrew|brew]] 安装:

Copy
brew install git-filter-repo

或是使用 [[pip]] 安装:

Copy
pip3 install git-filter-repo

当然也可以直接从仓库下载源文件运行，安装的好处是可以结合到 git 命令中使用。

使用

这里主要是对历史提交的邮箱信息进行修改:

Copy
git filter-repo --email-callback "return email.replace(b'old@email.com', b'new@email.com')"

另一种方式支持同时修改邮箱和姓名 (多个):

Copy
git filter-repo --mailmap mailmap

对应 mailmap 文件内容:

Copy
<new@email.com> <old@email.com>
new_name <new@email.com> old_name <old@email.com>

注:

--mailmap 中 <> 符号是必须的

--email-callback 和 --mailmap 两种方式的邮箱顺序不一样

修改完成后 push 如果出现: "fatal: No configured push destination" 提示，需要先重新设置远程仓库:

Copy
git remote add origin <url>
git push --set-upstream origin master -f

问题

在本机修改并 push 后，在服务器上执行 pull 时提示:

Copy
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint:
hint: git config pull.rebase false # merge (the default strategy)
hint: git config pull.rebase true # rebase
hint: git config pull.ff only # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
fatal: Need to specify how to reconcile divergent branches.

尝试加 -f 和按提示操作之后也没办法解决，索性直接把 .git 目录删除，重新 clone 后拷贝过来后，提交记录总算一致。

信息

环境

Python 3.10.10

GitHub 2.39.2

git-filter-repo 2.38.0

System: macOS 13.4.1

参考

Git - gitmailmap Documentation

git-filter-repo/INSTALL.md

git-filter-repo