如何在filter-branch之后删除旧的提交?

时间:2010-07-11 12:35:27

标签: git

我在我的存储库中使用了filter-branch到fix an incorrect email address但是所有的分支现在都是MIA(master除外)。

这是git graph之前filter-branch显示的内容:

*   d93c7ee (HEAD, master) Merge branch 'f1'
|\  
| * 08e7463 (f1) adding b
|/  
* 7c7bd91 adding a

我发出了这个filter-branch命令:

git filter-branch --env-filter 'export GIT_AUTHOR_EMAIL="fixed-email";
                                GIT_AUTHOR_NAME="fixed-author"'

得到了这个:

*   770262a (HEAD, master) Merge branch 'f1'
|\  
| * 0f58ab5 adding b
|/  
* fb012a9 adding a
*   d93c7ee (refs/original/refs/heads/master) Merge branch 'f1'
|\  
| * 08e7463 (f1) adding b
|/  
* 7c7bd91 adding a

困扰我的一些事情:

1)f1分支未移至0f58ab5 2)fb012a9之前的所有提交似乎与我无关,我可以摆脱它们吗?

我在另一个问题中看到有人建议:

rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --aggressive --prune=now

但它没有太大帮助,这是我后来得到的:

*   770262a (HEAD, master) Merge branch 'f1'
|\  
| * 0f58ab5 adding b
|/  
* fb012a9 adding a
* 08e7463 (f1) adding b
* 7c7bd91 adding a

编辑:按照VonC的建议做出这个图表:

*   211632d (HEAD, master) Merge branch 'f1'
|\  
| * bda7577 (f1) adding b
|/  
* 70c7b34 adding a
*   3182b33 (refs/original/refs/heads/master) Merge branch 'f1'
|\  
| * 8b81c21 (refs/original/refs/heads/f1) adding b
|/  
* 4c07dc9 adding a

哪个解决了问题#1,现在我只需要找到摆脱旧提交的方法,我该如何实现呢?

3 个答案:

答案 0 :(得分:6)

你可以再次尝试使用'-- --all'的git过滤器分支,例如:

git filter-branch --env-filter 'export GIT_AUTHOR_EMAIL="fixed-email";
                                       GIT_AUTHOR_NAME="fixed-author"' -- --all

注意:

  • 将过滤器分支选项与修订选项分开的--
  • --all重写所有分支和标记

也就是说,在您目前的情况下,git gc ... prune ...的任何数量都不会删除仍由分支标记引用的提交,例如仍然指向f1的{​​{1}}。
所以你所看到的是正常的设计。


OP报告说,一旦执行08e7463git filter-branch ... -- --all就会处理旧的提交。

同样,这并不奇怪:没有标签或分支再引用它们,这次,它们是从Git仓库中永久删除的候选者。

答案 1 :(得分:4)

我有同样的问题,我忘记在我的过滤器分支上-- --all,正如VonC建议的那样。

git filter-branch --env-filter 'export GIT_AUTHOR_EMAIL="fixed-email";
                                       GIT_AUTHOR_NAME="fixed-author"' -- --all

但我还要把它推到一个远程github回购..

您可能需要以相同的方式修复GIT_COMMITTER_NAME和GIT_COMMITTER_EMAIL ..一旦repo包含多个作者,您就需要对名称进行过滤。我的未配置名称是“未知”。

git filter-branch -f --env-filter '
if [ "$GIT_COMMITTER_NAME" = "unknown" ]
then
 export GIT_COMMITTER_EMAIL="fixed-email"
 export GIT_COMMITTER_NAME="fixed-author"
 export GIT_AUTHOR_EMAIL="fixed-email"
 export GIT_AUTHOR_NAME="fixed-author"
fi
' -- --all

但是因为我在修复之前将它推送到了repo,然后将它推后,我在我的git代码的历史中有一个奇怪的双头结构,除了不完全孤立的refs分支:

--E--\                   --E--\
---A--B----\             ---A--B----\
    \----C--D--- master      \----C--D--- refs/original/refs/heads/master
--E-----/                --E-----/

在我到达之前,A是回购,E是我本地提交的更改,我试图合并并推送到回购。

B和C都有A和E作为父母而D是新头。 B是我用E名字/地址写错的第一个工作,C是过滤器分支修复E中所有变化的结果,是正确的名称。

我使用git reflog显示我的本地克隆中的序列,然后git reset --hard A将所有内容放回A,丢弃B / C / D中的所有更改和文件。哪个很好,它是相同的文件,只是与不同的作者。

然后我从E和上面的git filter-branch重新合并了合并,这次包括改变了我的本地回购的-- --all

--E--\
---A--C-- master    (plus the refs branch is still there)

所以现在git shortlog -se只显示来自A和E的作者(已更正),而不显示来自B的“未知”作者。

然后我使用rm -r .git/refs/original修剪孤立的分支。 git branch现在显示正确的事情。

当我进行git推送时,它抱怨丢失提交并拒绝。这是真的,因为上面的提交B正是我想要摆脱的。

git push -f完成了这个伎俩。但请确保您在回购中拥有所需的一切,因为它具有破坏性。但最后,远程github repo匹配我的本地结构而不是突变体。

哦,为了奖励乐趣,如果你用msys Git for windows做这个,你可能需要更新,我不能使用1.52的filter-branch,但是在更新到1.74后它工作正常。

答案 2 :(得分:0)

如果要修改所有分支,请记住使用--all

git filter-branch $options -- --all

并删除旧的引用:

rm -rf .git/refs/original