toc
为什么要修改 Git 提交历史
修改 Git 历史,一般有以下两个原因:
- 删除密码、API Key 等敏感数据,因为即使你在最新的提交删除了他们,在历史提交里也存在;
- 删除超大文件。
超大文件问题经常出现在当你从一个 Git 托管网站换到另一个时,常因为后者不支持大文件,导致推送不上去。即使最新版删除了大文件,因为大文件存在在历史中,依然不能推送。
目前我测试几个网站的文件大小限制:
- Github,50M 报警,100M 拒绝,Conditions for large files;
- Gitlab,不限制单文件,max file size ?;
- Gitee,50M - 300M,根据付费版本不同,仓库体积过大,如何减小?
操作步骤
本文演示删除历史中的大文件步骤。
安装 bfg
如果是 MacOS,直接安装即可:
brew install bfg
如果是其他系统,可以下载 1.13.0 版的 jar 包,并将下面命令中的 bfg
替换成 java -jar path/to/bfg-1.13.0.jar
克隆仓库
git clone --mirror git@xxxxxx.com:jitao/project.git
这里使用 --mirror
参数,表示克隆出来的是一个 bare 仓库。
这一步最好备份一下仓库。
改历史
bfg --delete-files home.mp4 project.git
删除 home.mp4
这个文件,注意参数只能是文件名,不包含路径。如果传入一个路径,会报错:
Error: *** Can only match on filename, NOT path *** - remove '/' path segments
正常运行大概输出如下:
Using repo : /Users/jitao/workspace/project.git
Found 527 objects to protect
Found 2 commit-pointing refs : HEAD, refs/heads/master
Protected commits
-----------------
These are your protected commits, and so their contents will NOT be altered:
* commit 9bbd9c4e (protected by 'HEAD')
Cleaning
--------
Found 336 commits
Cleaning commits: 100% (336/336)
Cleaning commits completed in 435 ms.
Updating 1 Ref
--------------
Ref Before After
---------------------------------------
refs/heads/master | 9bbd9c4e | bc0c11c6
Updating references: 100% (1/1)
...Ref update completed in 24 ms.
Commit Tree-Dirt History
------------------------
Earliest Latest
| |
.............................DDDDDmmmmmmmmmmmmmmmmmmmmmmmmmm
D = dirty commits (file tree fixed)
m = modified commits (commit message or parents changed)
. = clean commits (no changes to file tree)
Before After
-------------------------------------------
First modified commit | 4021098d | ce77dc85
Last dirty commit | d73ece33 | e26922da
Deleted files
-------------
Filename Git id
------------------------------
home.mp4 | 8ab9914d (114.1 MB)
In total, 187 object ids were changed. Full details are logged here:
/Users/jitao/workspace/project.git.bfg-report/2020-03-15/15-02-30
BFG run is complete! When ready, run: git reflog expire --expire=now --all && git gc --prune=now --aggressive
信息的最后 bfg 还夹带了点私货:
--
You can rewrite history in Git - don't let Trump do it for real!
Trump's administration has lied consistently, to make people give up on ever
being told the truth. Don't give up: https://www.rescue.org/topic/refugees-america
--
呵呵。
清理仓库
cd project.git
git reflog expire --expire=now --all && git gc --prune=now --aggressive
推送
git push