从git / GitHub的历史logging中删除文件夹及其内容

我在我的GitHub帐户上工作了一个存储库,这是我偶然发现的一个问题。

  • Node.js项目与安装了几个npm软件包的文件夹
  • 这些包在node_modules文件夹中
  • 将该文件夹添加到git存储库,并将代码推送到github(当时没有考虑npm部分)
  • 意识到你并不需要这个文件夹成为代码的一部分
  • 删除该文件夹,推送它

在这种情况下,总的git回购的大小大约是6MB ,实际的代码(除了那个文件夹之外)只有大约300KB

现在我最终要找的是从git的历史中删除这个包文件夹的细节,所以如果有人克隆它,他们不必下载6mb的历史logging,只有他们将获得的实际文件截至上次提交将是300KB。

我查找了可能的解决scheme,并尝试了这两种方法

  • 从git存储库中删除文件(历史logging)
  • http://help.github.com/remove-sensitive-data/
  • https://gist.github.com/1588371

Gist看起来好像是在脚本运行后的地方,它显示它已经删除了那个文件夹,然后显示出50个不同的提交被修改了。 但是它不让我推这个代码。 当我试图推动它时,它说Branch up to date但是显示50个提交在git status被修改。 其他两种方法也没有帮助。

现在,即使它显示它摆脱了该文件夹的历史logging,当我检查我的本地主机上的回购大小,它仍然是6MB左右。 (我也删除了refs/original文件夹,但没有看到回购的大小的变化)。

我要澄清的是,如果有办法摆脱不仅提交历史(这是我认为发生的唯一的事情),而且还有那些git保持假设想要回滚的文件。

可以说一个解决scheme是为此提出的,并应用在我的本地主机,但不能被转载到该GitHub回购,是否有可能克隆回购,回滚到第一次提交执行的技巧和推它(或这是否意味着git会还有所有这些提交的历史? – 也就是6MB)。

我的最终目标是基本上find摆脱git的文件夹内容的最佳方式,以便用户不必下载6MB的东西,仍然可能有其他提交从未触摸模块文件夹(这很漂亮很多都是)git的历史。

我怎样才能做到这一点?

如果您在这里复制粘贴代码:

这是一个从历史中删除node_modules的例子

 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 

我发现其他答案中使用的--tree-filter选项可能会非常慢,特别是在大量提交大型库时。

这里是我使用的方法 – 使用--index-filter选项从git历史logging中彻底删除一个目录,该选项运行速度更快:

 # 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 

您可以使用以下命令检查gc之前和之后的存储库大小:

 git count-objects -vH 

除了上面的stream行答案之外,我还想为Windows系统添加一些注释。 命令

 git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD 
  • 完美的作品没有任何修改! 因此, 您不能使用Remove-Itemdel或其他任何内容而不是rm -rf

  • 如果您需要指定文件或目录的path,请使用./path/to/node_modules类的./path/to/node_modules

我find的最好和最准确的方法是下载bfg.jar文件: https ://rtyley.github.io/bfg-repo-cleaner/

然后运行命令:

 git clone --bare https://project/repository project-repository cd project-repository java -jar bfg.jar --delete-folders node_modules git reflog expire --expire=now --all && git gc --prune=now --aggressive git push --mirror https://project/new-repository 

如果要删除文件,请使用delete-files选项:

 java -jar bfg.jar --delete-files *.pyc 

完成复制和粘贴配方,只需在注释中添加命令(对于复制粘贴解决scheme),在testing之后:

 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 /”行