清空Github仓库的commits历史记录

git是当前最常见的版本控制工具,但出现以下情况时,往往需要清空commits历史记录:

  • commits记录占用空间过大甚至远远超过版本控制文件本身大小,进行云端代码管理时会受制于空间限制,无法继续更新
  • 历史记录中存在敏感信息,需要清理

清理commits历史记录的核心思想是,直接删除本地的.git目录,重新建立git仓库并与远程仓库建立链接,采用强制提交的方式覆盖远程仓库的commits记录。下面是一段示例脚本。

参数说明:

  • $REPO_DIR 表示需要处理的Git仓库本地目录
  • git@github.com:xxxx/$REPO_DIR.git 表示远程仓库地址

则可以按照如下步骤处理:

进入本地仓库,删除.git目录

cd $REPO_DIR
rm -rf .git

重新git初始化并添加commit

git init
git add . # 重新添加所有的文件
git commit -m "restart git commit"

添加远程仓库链接

在添加远程仓库时,需要设置远程仓库的代号,本教程记为origin.

git remote add origin git@github.com:xxxx/$REPO_DIR.git

此时,可以用git remote -v检查远程仓库的设置。

强制提交,覆盖远程仓库的commits历史记录

假设提交到远程仓库的master分支,则强制提交脚本如下:

git push -f origin master # 或者 git push --force origin master

强制提交之后,再看远程仓库master分支的commits记录就变成1了。

如果需要与上游保持同步检测,可以使用指令--set-upstream origin/master,即

git push origin master --set-upstream origin/master # 如果指向其他分支,可以修改为 origin/${指定分支名}

至此,大功告成~

后续讨论

细心的朋友可能会发现,上述操作之后,如果你还记得历史记录中某个commit的链接,你仍然可以通过链接访问到该commit下的文件,甚至可以基于这个commit重新创建新分支。为什么会出现这种情况呢?这其实和Git本身的设计机制有关,主要是为了提高容错率,防止你因为一些误操作弄丢了某些commits进而造成无法挽回的结果。

实际上,这些commits并没有马上被清理掉,仅仅是你的所有分支或标签无法访问到它们,这些commits被称为unreachable commits. 它们通常会被缓存一段时间,这个周期默认是30天,你也可以通过git命令行手动修改缓存周期或者手动清理。由于Github也是建立在Git这个版本管理工具上的网站,所以它也有这个机制。虽然它们在缓存期内仍然可以被访问到,但你clone到本地并不会包含它们,也就是说,你并不能在本地删除Github上已经存在的unreachable commits,因为本地根本访问不到它们(存在于 GitHub 上但不存在于本地克隆中的提交)。如果不着急的话,你可以等30天之后再试试看是否还能访问这些unreachable commits的链接;但如果你很着急,你可以联系Github Support帮你清理这些你不想保留的commits。

所以,如果你只是维护个人的文件仓库的话,不需要担心这个问题,你在新机器上clone下来的仍然是缩减大小之后的仓库,而Github上的unreachable commit会在缓存期后被清理掉。如果是与他人协作的仓库,还是谨慎使用git push --force这种危险的操作吧,确实遇到需要这个操作的场景时,考虑用更安全的git push --force-with-lease. 如果你强制提交之后发现后悔了,找到想恢复的commit的链接并创建新分支就可以找回那个commit所在历史分支之前的内容啦。

感谢@绿静風 发现了这个问题,促使我进一步查阅资料去完善这篇博文,在此表示感谢!

后续讨论的主要参考内容如下:

如果只是想删除历史记录中曾经存在(但现在并不需要)的大文件,可以参考这个Issue中的讨论:Consider cleaning up the .git folder to reduce the large repo size

posted @ 2018-11-06 22:18  云游四海的修补匠  阅读(2552)  评论(4编辑  收藏  举报