从 git 中永久删除目录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1216733/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Remove a directory permanently from git
提问by adk
In my personal git repo, I have a directory that contains thousands of small images that are no longer needed. Is there a way to delete them from the entire git history? I have tried
在我的个人 git repo 中,我有一个包含数千个不再需要的小图像的目录。有没有办法从整个 git 历史记录中删除它们?我试过了
git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch imgs" HEAD
and
和
git filter-branch --tree-filter 'rm -fr imgs' HEAD
but the size of the git repo remains unchanged. Any ideas?
但是 git repo 的大小保持不变。有任何想法吗?
Thanks
谢谢
采纳答案by Antony Stubbs
Actually none of these techniques workedfor me. I found the most reliable was was to simply pull locally into another repo:
实际上,这些技术都不适合我。我发现最可靠的是简单地在本地拉入另一个仓库:
git pull file://$(pwd)/myGitRepo
It also saves you the hassle of deletig old tags.
它还可以为您省去删除旧标签的麻烦。
see the story on my blog: http://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
在我的博客上看到这个故事:http: //stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
回答by VonC
The ProGit book has an interesting section on Removing Object.
ProGit 书有一个有趣的部分关于删除对象。
It does end with this:
它确实以这样的方式结束:
Your history no longer contains a reference to that file.
However, yourreflog
and a new set of refs that Git added when you did thefilter-branch
under.git/refs/original
still do, so you have to remove them and then repack the database. You need to get rid of anything that has a pointer to those old commits before you repack:
您的历史记录不再包含对该文件的引用。
但是,您reflog
和 Git 在您执行filter-branch
under时添加的一组新引用.git/refs/original
仍然有效,因此您必须删除它们,然后重新打包数据库。在重新打包之前,您需要删除任何指向那些旧提交的指针:
$ rm -Rf .git/refs/original
$ rm -Rf .git/logs/
$ git gc
$ git prune --expire
(git prune --expire
is not mandatory but can remove the directory content from the loose objects)
Backup everything before doing those commands, just in case ;)
(git prune --expire
不是强制性的,但可以从松散对象中删除目录内容)
在执行这些命令之前备份所有内容,以防万一;)
回答by Jakub Nar?bski
git-filter-branch by default saves old refs in refs/original/*
namespace.
git-filter-branch 默认将旧的 refs 保存在refs/original/*
命名空间中。
You need to delete them, and thendo git gc --prune=now
您需要删除它们,然后执行git gc --prune=now
回答by Michael
Brandon Thomsonasked in a comment to Rainer Blome's solution if this just fixed the gitk view or if the refs will be really gone. A good way to check this is to remember one of the sha1 hashes (or a unique prefix of it) of the old commits and try
Brandon Thomson在对Rainer Blome的解决方案的评论中询问这是否只是修复了 gitk 视图,或者 refs 是否真的会消失。检查这一点的一个好方法是记住旧提交的 sha1 哈希之一(或它的唯一前缀)并尝试
$ git ls-tree hash-value
This should show you the content of the repos main folder as it was in this commit. After
这应该向您显示 repos 主文件夹的内容,就像在这次提交中一样。后
$ rm -Rf .git/refs/original
$ rm -Rf .git/logs/
as shown by VonCand removing the refs/original/…
lines from .git/info/refs
and .git/packed-refs
as shown by Rainer Blome, a final
如图VonC并除去refs/original/…
从线.git/info/refs
和.git/packed-refs
如由所示莱纳BLOME,最终
$ git gc --prune=now
made not only the refs, but also the old objects (commits, trees, and blobs) go away. The above shown git ls-tree hash-value
proves this.
Another nice command to check this is git count-objects -v
(run it before the filter-brach and after the pruning and compare the size).
不仅使 refs,而且使旧对象(提交、树和 blob)消失。上图git ls-tree hash-value
证明了这一点。另一个很好的检查命令是git count-objects -v
(在 filter-brach 之前和修剪之后运行它并比较大小)。
Note:As I'm not allowed yet to comment on the other answers, I had to write a new one although it mainly combines previous given answers.
注意:由于我还不能对其他答案发表评论,所以我不得不写一个新的,尽管它主要结合了以前给出的答案。
回答by Michael
If you want to go the manual cleanup route, there are some more files that may also contain a ref to the position of your original branch before the git-filter-branch. For example, I filtered my "home" branch:
如果您想走手动清理路线,还有一些文件可能还包含对 git-filter-branch 之前原始分支位置的引用。例如,我过滤了我的“home”分支:
.git/info/refs:
.git/信息/参考:
179ad3e725816234a7182476825862e28752746d refs/original/refs/heads/home
179ad3e725816234a7182476825862e28752746d refs/original/refs/heads/home
.git/packed-refs:
.git/packed-refs:
179ad3e725816234a7182476825862e28752746d refs/original/refs/heads/home
179ad3e725816234a7182476825862e28752746d refs/original/refs/heads/home
After I removed those lines, gitk did not show the old commits any more.
删除这些行后,gitk 不再显示旧的提交。
回答by Zantier
As this is an old question, perhaps some of this wasn't possible back then. This also assumes you're using bash or cygwin.
由于这是一个古老的问题,也许在当时,其中一些是不可能的。这也假设您使用的是 bash 或 cygwin。
Warning:The second and third lines will permanently delete all commits unreachable from your branches/tags.
警告:第二行和第三行将永久删除所有无法从您的分支/标签访问的提交。
After running filter-branch
, do
运行后filter-branch
,做
for ref in $(git for-each-ref --format='%(refname)' refs/original); do git update-ref -d $ref; done
git reflog expire --expire=now --all
git gc --prune=now
git for-each-ref --format='%(refname)'
gets the reference names, and git update-ref -d
deletes the reference. It is generally better not to modify the .git
folder directly, and in particular this command handles the case when the refs are in packed-refs
.
git for-each-ref --format='%(refname)'
获取引用名称,并git update-ref -d
删除引用。通常最好不要.git
直接修改文件夹,特别是这个命令处理 refs 在packed-refs
.
The second and third lines are taken directly from How to clean up unused side-branches in your commit trees?.
第二行和第三行直接取自如何清理提交树中未使用的侧分支?.