恢复“旧提交”来自多个 git rebase
我知道这个问题,但不确定如何将其映射到我当前的情况。 (Rebase 很可怕,撤销 rebase 更可怕!)
我从我的 master 的几个不同的功能分支开始:
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
我的问题是我的同事告诉我我们还没有为功能 A 做好准备。
有什么方法可以让我保留所有工作,同时又恢复到可以将功能 C 重新设置为功能 B 的情况吗?
I am aware of this question, but not to sure how to map it to my current situation. (Rebase is scary, undoing rebase is double scary!)
I started out with several different feature branches of my master:
master x-x-x-x-x-x-x-x-x-x
\ \ \
FeatureA 1-2-3 \ \
FeatureB A-B \
FeatureC X-Y-Z
I wanted to merge them all together and check they worked before merging back onto the top of master, so I did a:
git checkout FeatureB
git rebase FeatureA
git mergetool //etc
git rebase --continue
Then
git checkout FeatureC
git rebase FeatureB
git mergetool //hack hack
git rebase --continue
Which leaves me with
master x-x-x-x-x-x-x-x-x-x
\
FeatureA 1-2-3
\
FeatureB A'-B'
\
FeatureC X'-Y'-Z'
Then I corrected some bits that didn't compile properly, and got the whole feature set to an acceptable state:
master x-x-x-x-x-x-x-x-x-x
\
FeatureA 1-2-3
\
FeatureB A'-B'
\
FeatureC X'-Y'-Z'-W
My problem is that my colleagues tell me that we're not ready for FeatureA.
Is there any way for me to keep all my work, but also revert to a situation where I can just rebase FeatureC on to Feature B?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是我根据评论对答案的理解:
当您进行变基时,当前分支上的提交将被“撤消”,然后“重新应用”,但实际上,它们并没有被撤消,而是被“记住”* ,并重新应用新的 ID,因此,例如,如果我查看 git reflog show FeatureB,我会得到如下内容:
因此,正如 @Jefromi 所说,原始 ID 仍然存在(A 的 SHA) reflog 中的 和 B 提交与 git log 中的提交不同,对应于 A' 和 B')。
同样, git reflog show FeatureC 看起来像这样
再次,原始的 Z、Y 和 X 提交仍然存在
所以,我的问题的解决方案是创建一个新分支FeaturesBC离开master的HEAD(例如),然后挑选提交FeatureB {2 & 1},然后是FeatureC{4,3,2},和(可能)W:(
它似乎有效,我不得不重新进行一些相同的合并,但这还不错)
编辑,来自Jefromi:
择优挑选可能没有必要。您还可以简单地重新创建分支之前的分支:
或者,如果您想丢弃FeatureB和FeatureC的重新基位置,回到它们之前的位置:
最后,请注意,如果您愿意,您可以使用另一个引用日志中提供的符号 - 例如,
FeatureC@{2}
而不是893eb78
。这意味着“FeatureC 的第二个先前位置”。不过,请注意,仅在查看引用日志后立即使用此选项,因为一旦您再次更新分支(移动它、提交它...),FeatureC@{2}
将引用17dafb3 代替。正如 @Jefromi 对我的问题的评论:
<子>
* 准确地说,旧的提交对象只是留在存储库中。它们最终会被修剪,因为你不想要一个充满旧悬空提交的存储库;这将在第一次运行 git gc 且提交至少两周前发生(由 gc.pruneExpire 配置)。
This is my understanding of what the answer is, based on comments:
When you do a rebase, the commits on your current branch are 'undone', then 'reapplied', but actually, they are not undone, they are 'remembered'*, and reapplied with new IDs, so for example, if I look in
git reflog show FeatureB
, I get something like this:So as @Jefromi said, the originals are still there (the SHAs of the A and B commits in the reflog are not the same as the ones in git log, which correspond to A' and B').
Similarly,
git reflog show FeatureC
looks like thisAgain, the original Z, Y and X commits are still there
So, the solution to my problem is to create a new branch
FeaturesBC
off the HEAD of master (for example), then cherry-pick the commits FeatureB{2 & 1}, and then FeatureC{4, 3, 2}, and (possibly) W:(It seems to have worked, I had to re-do some of the same merges, but it wasn't too bad)
Edit, from Jefromi:
Cherry-picking may not have been necessary. You can also simply recreate branches where the branches were before the rebase:
Or, if you want to throw away the rebased position of FeatureB and FeatureC, going back to where they were before:
Finally, note that if you like you can use the other notation provided in the reflogs - for example,
FeatureC@{2}
instead of893eb78
. This means "the second previous position of FeatureC". Be careful to only use this immediately after viewing the reflog, though, because as soon as you update the branch again (move it, commit to it...),FeatureC@{2}
will refer to 17dafb3 instead.As @Jefromi commented on my question:
* To be precise, the old commit objects are simply left in the repository. They will eventually be pruned, since you don't want a repo full of old dangling commits; this will happen the first time
git gc
is run and the commits are at least two weeks old (configured bygc.pruneExpire
).如果所有其他方法都失败,您可以从 master 重新启动并 gitcherry-pick 所有 B 或 C 提交来重新创建这些分支。如果这是唯一的解决方案,我希望其他人已经写了一个脚本......
If all else fails you can restart from master and
git cherry-pick
all of B's or C's commits to recreate those branches. I hope someone else already wrote a script if this is the only solution...你可以使用 git rebase --ontoA C 将从 C 到 A 的所有内容重新设置为 master 上的某个点。它会给你留下:
要找到你想要变基的点,你可以使用 git 的 reflog 和 git merge-base 的组合 - 但你也可以变基到 A 的合并基础,具有类似于以下内容的历史记录:(
git rebase --onto $(git merge-base A master) A C
)you can use
git rebase --onto <old-merge-base from B> A C
to rebase everything from C up to A onto a point on master. it will leave you with:to find the point where you want to rebase onto, you can use a combination of git's reflog and
git merge-base
– but you can also rebase onto the merge base of A, to have history similar to the following:(
git rebase --onto $(git merge-base A master) A C
)