git log -all命令显示使用filter-branch命令删除的提交记录

5
为了删除我的代码库中除了“my_dir/”之外的所有内容,我使用了以下命令:
git filter-branch --prune-empty --subdirectory-filter my_dir/  --prune-empty --tag-name-filter cat -- --all
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d;
git reflog expire --expire=now --all;
git gc --prune=now;

现在,使用:

git log

一切看起来都很好:日志中只显示了包含在“my_dir”目录中的文件的提交记录。

但是:

git log --all

仍然显示所有内容。实际上,执行另一个filter-branch(以删除my_dir中的某些其他.pyc文件)将找到(并删除)旧目录中的所有.pyc文件。

看起来--subdirectory-filter并没有真正删除提交...它们仍然存在。

我漏掉了什么?

编辑:

subdirectory-filter“只查看涉及给定子目录的历史记录”。所以也许它不会删除所有其他提交,而只是重写那个目录的提交,并留下其他提交的“孤立分支”???


关于您的编辑:--subdirectory-filter 仅为触及该目录的提交添加重写提交;但是,如果一个引用在其历史记录中有任何此类提交,则该引用将被重写。因此,如果您有无法到达曾经触及子目录的任何提交的引用(可以是分支或标签),那么这可能是问题所在。 - Mark Adelsberger
@MarkAdelsberger在这里的评论可能是真正正确的答案。请注意,--all表示“refs/中的所有引用以及HEAD本身”。 - torek
1个回答

2
filter-branch命令会创建新的引用,指向“旧”的提交记录,以便需要撤消时使用。 git log --all 显示了所有引用的历史记录,包括filter-branch创建的特殊引用。
更一般地说,我所知道的唯一一个Git命令可以删除提交对象是gc。要使gc删除提交记录,则该记录不能从任何引用或reflog中访问。因此,如果您想真正删除这些提交记录:
1)删除original / *引用
2)清除reflog
3)使用prune=now运行积极的gc

正如您从我的问题中所看到的,我执行了 reflog expire + gc --prune=now 命令,但提交记录仍然存在... - Leo
从我的回答中可以看出,在您删除filter-branch创建的“backup”引用之前,它是行不通的。 - Mark Adelsberger
你可能需要再次过期reflog(在确保所有原始引用都已删除后),或者只需rm .git/logs;但如果这样做不起作用,下一步将是git for-each-ref --contains <sha1>,其中<sha1>是应该被删除的提交之一的提交ID。这将列出仍然持有提交以防止其被删除的任何引用,并且您可以处理它们。 - Mark Adelsberger
还要注意,您可能需要在gc命令中添加--aggressive - Mark Adelsberger
1
一旦运行了 git gcrefs/original/ 引用就会被“打包”,必须使用 git update-ref -d 删除它们,或者(更容易但有点作弊)通过编辑 .git/packed-refs。另一方面,原始的 git for-each-ref 在这个时候应该已经完成了这个操作。 - torek
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接