我知道this问题,但不知道如何将其映射到我目前的情况。 (Rebase是可怕的,撤销rebase是双重可怕的!)
我从我的主人的几个不同的功能分支开始:
master x-x-x-x-x-x-x-x-x-x
\ \ \
FeatureA 1-2-3 \ \
FeatureB A-B \
FeatureC X-Y-Z
我想将它们合并在一起并检查它们是否有效,然后再合并到主机顶部,所以我做了一个:
git checkout FeatureB
git rebase FeatureA
git mergetool //etc
git rebase --continue
然后
git checkout FeatureC
git rebase FeatureB
git mergetool //hack hack
git rebase --continue
让我留下了
master x-x-x-x-x-x-x-x-x-x
\
FeatureA 1-2-3
\
FeatureB A'-B'
\
FeatureC X'-Y'-Z'
然后我纠正了一些没有正确编译的位,并将整个功能设置为可接受的状态:
master x-x-x-x-x-x-x-x-x-x
\
FeatureA 1-2-3
\
FeatureB A'-B'
\
FeatureC X'-Y'-Z'-W
我的问题是我的同事告诉我,我们还没有为FeatureA做好准备。
我有什么方法可以保留我的所有工作,但也可以恢复到我可以将FeatureC重新设置为功能B的情况吗?
答案 0 :(得分:5)
根据评论,这是我对答案的理解:
当您执行rebase时,当前分支上的提交被“撤消”,然后“重新应用”,但实际上,它们未被撤消,它们被“记住”*,并重新应用新ID,例如,如果我查看git reflog show FeatureB
,我会得到类似的结果:
7832f89 FeatureB@{0} rebase finished: refs/heads/FeatureB onto f4df3
efd3fed FeatureB@{1} commit: B
f3f3d43 FeatureB@{2} commit: A
2f32fed FeatureB@{3} branch: Created from HEAD
正如@Jefromi所说,原始文件仍然存在(reflog中A和B提交的SHA与git log中的提交不同,它们对应于A'和B')。
同样,git reflog show FeatureC
看起来像这样
32873ef FeatureC@{0} commit: W
17dafb3 FeatureC@{1} rebase finished: refs/heads/FeatureC onto 89289fe
893eb78 FeatureC@{2} commit: Z
a78b873 FeatureC@{3} commit: Y
e78b873 FeatureC@{4} commit: X
378cbe3 FeatureC@{5} branch: Created from HEAD
同样,原始的Z,Y和X提交仍然存在
所以,我的问题的解决方案是从master的HEAD创建一个新的分支FeaturesBC
(例如),然后挑选提交的FeatureB {2& 1},然后是FeatureC {4,3,2}和(可能)W:
git checkout master
git checkout -b FeaturesBC
git cherry-pick f3f3d43
git cherry-pick efd3fed
//etc...
(它似乎有效,我不得不重新做一些相同的合并,但它并不太糟糕)
编辑,来自Jefromi:
可能没有必要采摘樱桃。您还可以简单地重新创建分支在rebase之前的分支:
git branch FeatureB-old efd3fed
git branch FeatureC-old 893eb78
或者,如果你想抛弃FeatureB和FeatureC的重新定位,回到原来的位置:
git branch -f FeatureB efd3fed
git branch -f FeatureC 893eb78
最后,请注意,如果您愿意,可以使用reflog中提供的其他表示法 - 例如,FeatureC@{2}
而不是893eb78
。这意味着“FeatureC的第二个先前位置”。但是,请注意在查看reflog之后立即使用它,因为只要再次更新分支(移动它,提交它...),FeatureC@{2}
将引用17dafb3。
@Jefromi评论了我的问题:
您可能应该从master或featureC创建一个新分支(比如说,名为featuresABC),并将每个分支合并到其中,使功能分支保持不变。保留各个功能分支的独立历史是很好的。
<子>
*确切地说,旧的提交对象只是保留在存储库中。他们最终会被修剪,因为你不想要一个充满旧悬挂的回购;这将在第一次git gc
运行且提交至少两周(由gc.pruneExpire
配置)时发生。
子>
答案 1 :(得分:1)
如果所有其他方法都失败了,您可以从master和git cherry-pick
所有B或C的提交重新启动以重新创建这些分支。我希望其他人已经写过一个脚本,如果这是唯一的解决方案......
答案 2 :(得分:1)
您可以使用git rebase --onto <old-merge-base from B> A C
将从C到A的所有内容重新绑定到主节点上。它将离开你:
master x-x-x-x-x-x-x-x-x-x
\ \
FeatureA 1-2-3 \
\
FeatureB A'-B'
\
FeatureC X'-Y'-Z'-W
要找到要重新绑定的点,可以使用git的reflog和git merge-base
的组合 - 但是你也可以重新绑定到A的合并基础,以获得类似于以下内容的历史记录: / p>
master x-x-x-x-x-x-x-x-x-x
|\
FeatureA | 1-2-3
\
FeatureB A'-B'
\
FeatureC X'-Y'-Z'-W
(git rebase --onto $(git merge-base A master) A C
)