我在我的存储库中使用了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,现在我只需要找到摆脱旧提交的方法,我该如何实现呢?
答案 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报告说,一旦执行08e7463
,git 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