2010-04-22 161 views
4

我知道this问题,但不确定如何将其映射到我目前的情况。 (再次基于是可怕的,撤销重订为双吓人!)从多个git rebases恢复“旧提交”

我开始了我的主人的几个不同的特性分支:

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转换到Feature B的情况?

+0

实际上,我感到困惑,为什么你重建基础可言。您应该已经创建了一个与master或featureC关联的新分支(称为featuresABC),然后将它们合并到其中,从而使功能分支完好无损。保留各种功能分支的独立历史是很好的。 – Cascabel 2010-04-22 15:47:20

+1

@Jefromi,因为我还在学习...... – Benjol 2010-04-22 18:55:59

+0

@Jefromi,如果你想检查(甚至自己声称) – Benjol 2010-04-23 06:37:45

回答

4

这就是我的答案是什么的认识,基于评论:

当你做一个底垫中,你目前的提交分支'是'撤消',然后'重新申请',但实际上,他们没有撤消,他们被'记住'*,并重新申请新的ID,例如,如果我看看git reflog show FeatureB,我得到这样的事情:

7832f89 [email protected]{0} rebase finished: refs/heads/FeatureB onto f4df3 
efd3fed [email protected]{1} commit: B 
f3f3d43 [email protected]{2} commit: A 
2f32fed [email protected]{3} branch: Created from HEAD 

正如@Jefromi所说,原件仍然存在(A和B在reflog中提交的SHA与在git log中提交的不一样,对应于A'和B')。

同样,git reflog show FeatureC看起来像这样

32873ef [email protected]{0} commit: W 
17dafb3 [email protected]{1} rebase finished: refs/heads/FeatureC onto 89289fe 
893eb78 [email protected]{2} commit: Z 
a78b873 [email protected]{3} commit: Y 
e78b873 [email protected]{4} commit: X 
378cbe3 [email protected]{5} branch: Created from HEAD 

同样,原来Z,Y和X提交仍然存在

所以,解决我的问题是创建一个新的分支FeaturesBC关闭主的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 

最后,请注意,如果您喜欢,您可以使用reflog中提供的其他表示法 - 例如,[email protected]{2}而不是893eb78。这意味着“FeatureC的第二个以前的位置”。不过,请注意在查看reflog后立即使用它,因为只要再次更新分支(移动它,提交给它...),[email protected]{2}将代替17dafb3。

由于@Jefromi评论我的问题:

你或许应该已经创建了一个新的分支关老爷或featureC(称为featuresABC,说),以及合并每个进去,留下功能分支完好。保留各种功能分支的独立历史是很好的。

*确切地说,旧的提交对象只留在版本库中。他们最终会被修剪,因为你不希望回购充满旧的悬挂承诺;这将在第一次运行git gc时发生并且提交至少两周(由gc.pruneExpire配置)。

0

如果一切都失败了,你可以重新启动master和git cherry-pick所有的B或C都承诺重新创建这些分支。我希望别人已经写了一个脚本,如果这是唯一的解决办法...

+0

嗯,说实话,我在开始之前备份了我的整个资源库,所以我并没有完全搞砸,但我想避免再次重做整个rebase的事情...... – Benjol 2010-04-22 13:18:07

+0

我的理解(从这里http: //Backoverflow.com/questions/2689634/do-i-need-to-perform-a-commit-after-a-rebase)是B和C的提交已被rebase修改,所以这是行不通的,或者我错过了什么? – Benjol 2010-04-22 13:19:36

+0

@ Benjol:你是部分正确的:重新提交的提交确实是原始版本的修改版本(具体来说,它们有不同的父母,可能有些不同的补丁),但原始文件仍然存在。找到它们的最简单方法可能是'git reflog show FeatureA' - 这比通过HEAD'的reflog拾取并确定哪些线属于哪个分支要容易一些。 – Cascabel 2010-04-22 15:44:05

0

您可以使用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的引用日志和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

+0

这当然是所有的工作,但只要旧的非基础提交是仍然在储存库中,不需要重新分配。 (给出错误的机会更多,不必要地刷新提交日期。) – Cascabel 2010-04-23 20:29:37