5

我知道这个问题,但不确定如何将其映射到我目前的情况。(变基是可怕的,撤消变基是双重可怕的!)

我从我的主人的几个不同的功能分支开始:

master    x-x-x-x-x-x-x-x-x-x
             \       \    \
FeatureA      1-2-3   \    \
FeatureB               A-B  \
FeatureC                     X-Y-Z

我想将它们合并在一起,并在合并回到 master 顶部之前检查它们是否有效,所以我做了:

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 重新定位到 Feature B 的情况?

4

3 回答 3

5

根据评论,这是我对答案的理解:

当您进行变基时,当前分支上的提交被“撤消”,然后“重新应用”,但实际上,它们并没有被撤消,它们被“记住”*,并使用新的 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 提交仍然存在

因此,我的问题的解决方案是FeaturesBC从 master 的 HEAD 创建一个新分支(例如),然后选择提交 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:

可能没有必要采摘樱桃。您还可以简单地重新创建分支在变基之前的分支:

git branch FeatureB-old efd3fed
git branch FeatureC-old 893eb78

或者,如果您想丢弃 FeatureB 和 FeatureC 的重新定位位置,回到它们之前的位置:

git branch -f FeatureB efd3fed
git branch -f FeatureC 893eb78

最后,请注意,如果您愿意,可以使用 reflogs 中提供的其他符号 - 例如,FeatureC@{2}代替893eb78. 这意味着“FeatureC 的第二个先前位置”。但是,请注意仅在查看 reflog 后立即使用它,因为一旦您再次更新分支(移动它,提交它......),FeatureC@{2}将改为引用 17dafb3。

正如@Jefromi 评论我的问题:

您可能应该从 master 或 featureC 创建一个新分支(例如称为 featuresABC),并将每个分支合并到其中,保持功能分支完好无损。保留各个功能分支的独立历史记录是很好的。

* 准确地说,旧的提交对象只是留在存储库中。它们最终会被修剪,因为你不想要一个充满旧的悬空提交的仓库;这将在第一次git gc运行时发生,并且提交至少存在两周(由 配置gc.pruneExpire)。

于 2010-04-23T06:37:00.943 回答
1

如果一切都失败了,您可以从 master 和git cherry-pick所有 B 或 C 的提交重新启动以重新创建这些分支。如果这是唯一的解决方案,我希望其他人已经写了一个脚本......

于 2010-04-22T13:08:45.573 回答
1

您可以使用git rebase --onto <old-merge-base from B> A C将所有内容从 C 到 A 重新设置为 master 上的一个点。它会给你留下:

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 的合并基础上,以获得类似于以下的历史记录:

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)

于 2010-04-23T10:06:30.090 回答