Remove folder and its contents from git/GitHub's history
我在我的Github帐户上开发一个存储库,这是我偶然发现的一个问题。
- 安装了几个NPM包的文件夹的node.js项目
- 包裹在
node_modules 文件夹中。 - 将该文件夹添加到Git存储库并将代码推送到GitHub(当时没有考虑NPM部分)
- 意识到你并不真正需要这个文件夹作为代码的一部分
- 删除了那个文件夹,推了它
在这种情况下,总Git回购的大小约为6MB,其中实际代码(除文件夹外的所有代码)仅为300KB左右。
现在,我最后要寻找的是一种从Git的历史记录中删除包文件夹细节的方法,这样,如果有人克隆了它,他们就不必下载价值6MB的历史记录,从上一次提交开始,他们将获得的实际文件只有300KB。
我查找了可能的解决方案,并尝试了这两种方法
- 从Git存储库中删除文件(历史记录)
- http://help.github.com/remove-sensitive-data/
- https://gist.github.com/1588371
gist看起来像是在运行脚本之后的什么地方工作的,它显示它已经摆脱了那个文件夹,之后它显示修改了50个不同的提交。但它并没有让我推那个代码。当我试图推动它时,它说
现在,即使它显示它已经摆脱了那个文件夹的历史记录,当我在本地主机上检查这个repo的大小时,它仍然在6MB左右。(我也删除了
我要澄清的是,如果有一种方法可以消除提交历史(这是我认为唯一发生的事情),而且Git保留的那些文件假设要回滚。
假设为此提供了一个解决方案,并应用于我的本地主机,但无法复制到Github repo,是否可以克隆该repo,回滚到第一次提交执行该技巧并将其推送(或者这是否意味着Git仍将具有所有这些提交的历史记录?-又名。6MB)。
我在这里的最终目标是找到从Git中删除文件夹内容的最佳方法,这样用户就不必下载价值6MB的内容,而且还可能有其他从未接触过Git历史上的模块文件夹(几乎全部)的提交。
我该怎么做?
如果您要复制粘贴代码:
这是一个从历史中删除
1 2 3 4 5 6 7 | git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d echo node_modules/ >> .gitignore git add .gitignore git commit -m 'Removing node_modules from git history' git gc git push origin master --force |
我发现在其他答案中使用的
下面是我使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # Make a fresh clone of YOUR_REPO git clone YOUR_REPO cd YOUR_REPO # Create tracking branches of all branches for remote in `git branch -r | grep -v /HEAD`; do git checkout --track $remote ; done # Remove DIRECTORY_NAME from all commits, then remove the refs to the old commits # (repeat these two commands for as many directories that you want to remove) git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch DIRECTORY_NAME/' --prune-empty --tag-name-filter cat -- --all git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d # Ensure all old refs are fully removed rm -Rf .git/logs .git/refs/original # Perform a garbage collection to remove commits with no refs git gc --prune=all --aggressive # Force push all branches to overwrite their history # (use with caution!) git push origin --all --force git push origin --tags --force |
您可以在
1 | git count-objects -vH |
。
除了上面流行的答案,我还想为Windows系统添加一些注释。命令
1 | git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD |
工作完美,无需任何修改!因此,您不能使用
Remove-Item 、del 或其他任何东西来代替rm -rf 。如果需要指定文件或目录的路径,请使用像
./path/to/node_modules 这样的斜杠。
我找到的最佳和最准确的方法是下载bfg.jar文件:https://rtyley.github.io/bfg-repo-cleaner/
然后运行命令:
1 2 3 4 5 | git clone --bare https://project/repository project-repository cd project-repository java -jar bfg.jar --delete-folders DIRECTORY_NAME # i.e. 'node_modules' in other examples git reflog expire --expire=now --all && git gc --prune=now --aggressive git push --mirror https://project/new-repository |
。
如果要删除文件,请改用"删除文件"选项:
1 | java -jar bfg.jar --delete-files *.pyc |
。
完成复制粘贴配方,只需在测试后将命令添加到注释中(对于复制粘贴解决方案):
1 2 3 4 5 6 | git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD echo node_modules/ >> .gitignore git add .gitignore git commit -m 'Removing node_modules from git history' git gc git push origin master --force |
号
在此之后,可以从.gitignore中删除行"node_modules/"。
对于windows用户,请注意使用
1 2 3 4 5 6 7 | git filter-branch -f --tree-filter"rm -rf FOLDERNAME" --prune-empty HEAD git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d echo FOLDERNAME/ >> .gitignore git add .gitignore git commit -m"Removing FOLDERNAME from git history" git gc git push origin master --force |
。
我在Windows上使用Git从旧的C项目中删除了bin和obj文件夹。小心
1 | git filter-branch --tree-filter"rm -rf bin" --prune-empty HEAD |
它通过删除git安装文件夹中的usr/bin文件夹来破坏git安装的完整性。