如何按条件清理Git仓库提交历史,保留开发者提交记录?
完全可行,用Git历史重写工具就能实现
核心思路
通过Git的历史重写工具(推荐用git filter-repo,效率远高于旧的git filter-branch),批量过滤掉所有提交信息为[skip ci] Generate yaml files的自动提交,同时确保最终仓库的工作区内容和原仓库完全一致。
具体步骤
1. 先备份原仓库
历史重写是破坏性操作,务必先克隆原仓库的镜像副本进行操作,避免影响线上仓库:
git clone --mirror <你的仓库地址> repo-mirror cd repo-mirror
2. 记录原仓库的最终内容哈希
确保重写后仓库的文件内容和原仓库完全一致,先记下原仓库HEAD对应的树哈希:
ORIGINAL_TREE=$(git rev-parse HEAD^{tree})
3. 过滤自动提交
使用git filter-repo批量删除所有自动生成的提交,只保留开发者提交:
git filter-repo --message-filter ' if [[ "$GIT_COMMIT_MESSAGE" == "[skip ci] Generate yaml files" ]]; then exit 1 # 跳过该提交(即删除) else cat # 保留开发者提交的信息 fi '
4. 同步最终内容
如果原仓库的最后一次提交是自动提交,上面的过滤会删掉它,导致最后提交的内容和原仓库不一致。此时需要基于最后一个开发者提交,创建一个包含原仓库最终内容的新提交:
# 获取过滤后的最后一个开发者提交哈希 LAST_DEV_COMMIT=$(git rev-parse HEAD) # 创建新提交,继承开发者提交的历史,使用原仓库的最终内容 NEW_COMMIT=$(git commit-tree $ORIGINAL_TREE -p $LAST_DEV_COMMIT -m "Apply final auto-generated yaml files") # 将HEAD指向新提交 git update-ref HEAD $NEW_COMMIT
5. 推送重写后的仓库
确认内容无误后,强制推送到远程仓库(注意:这会覆盖远程仓库的所有历史,需提前通知所有协作者):
git push --force
注意事项
- 重写历史后,所有协作者必须重新克隆仓库,不能再用旧的本地仓库进行拉取/推送操作,否则会引发严重冲突。
- 如果你的Git版本低于2.22.0,需要先安装
git filter-repo(它是官方推荐的历史重写工具,替代老旧的git filter-branch)。
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

