从 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 06:49:27  来源:igfitidea点击:

Remove a directory permanently from git

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, your reflogand a new set of refs that Git added when you did the filter-branchunder .git/refs/originalstill 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-branchunder时添加的一组新引用.git/refs/original仍然有效,因此您必须删除它们,然后重新打包数据库。在重新打包之前,您需要删除任何指向那些旧提交的指针:

$ rm -Rf .git/refs/original
$ rm -Rf .git/logs/
$ git gc
$ git prune --expire 

(git prune --expireis 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/refsand .git/packed-refsas 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-valueproves 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 -ddeletes the reference. It is generally better not to modify the .gitfolder 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?.

第二行和第三行直接取自如何清理提交树中未使用的侧分支?.