2013-07-04 114 views
3

我们正在两个版本,一个小和一个主要的,每个都有自己的git分支。在我们创建主要分支之前,一个功能最初被添加到小分支。之后,该功能从小分支中删除(提交revert),因为我们决定在主要版本中引入该功能。合并git分支时,有一个恢复,其他不想要

所以,现在我们有一种情况,如果我们将小分支的变化合并到主分支中,它将包含回复提交,这在主分支中是没有意义的。

我考虑过的一个选择是在恢复提交后对次分支提交使用cherry-pick,但这有一个缺点,即基于次分支的任何分支都不能与主分支合并。 (我们必须继续使用cherry-pick来处理类似的事情。)虽然它的优点是具有更准确的历史记录,因为不会包含恢复提交。

另一种选择是将所有小分支合并到主分支中,并仅“忽略”还原更改。通过“忽略”,我的意思是在合并时手动还原已恢复的更改。从git的角度来看,这更好地保留了历史记录,但可能意味着在合并过程中会出现一些问题。

通常我们只在主分支中使用合并,而樱桃采摘只是为了在修改最新代码之前将它们合并。所以我的选择是第二种选择,但我想知道这是否是处理这种情况的正确方法,或者是否有我缺少的东西。

编辑:这里是ASCII艺术:-)

* (major) 
| * (minor) 
* | ... 
| * revert feature on minor 
* | major: unrelated commit 
| * minor: unrelated commit 
* | 
|/ 
* common ancestor 
| 
* add feature to main branch 
+1

你的问题是缺少ASCII艺术:)。您是否恢复了仅在小分支上进行的提交或者是在分支或合并到小分支之前在主分支中创建的提交? – Chronial

+0

在将功能添加到次分支之后但在将还原添加到次分支之前,小分支合并到主分支中了吗? –

+0

我不清楚这两个分支上的功能提交是否通用。 –

回答

6

我很好奇你的意思,“在主要分支中没有意义。”您是否担心该功能将在主要分支上恢复?或者,你是否只是觉得在主要分支的历史中会出现名为“恢复功能”的提交,而实际上该功能在那里?

很难说,合并的结果会是什么没有更多的细节,但这里有一些可能性:

如果你的历史看起来是这样的:

* (major) 
| * (minor) 
* | 
| * revert feature on minor 
* | cherry-pick feature onto major 
| * add feature to minor 
* | 
|/ 
* common ancestor 
| 

然后,你可以简单地合并minor进入major没有任何问题。

为什么?想想这样说:当你合并minormajor,你实际上走的是共同的祖先(git merge-base major minor)和minor之间的差异,把它当成一个补丁到major,然后创建一个承诺,恰好拥有二者majorminor作为父母。

公共祖先与minor之间的差异不包含任何已添加的特征提示,然后因两个提交相互抵消而被还原。因此,将引入major的唯一更改将会由于minor上的其他提交而引起更改。

如果你的历史是这样的:

* (major) 
| * (minor) 
* | 
| * revert feature on minor 
* | merge minor into major 
|\| 
* | cherry-pick feature onto major 
| * add feature to minor 
* | 
|/ 
* 
| 

那么你有问题。在这种情况下,majorminor之间的共同祖先是标有“add feature to minor”的提交。如果你看看这个共同的祖先和minor之间的差异,差异将包括该特征的恢复。当您将minor合并到major时,此差异将应用于major,在major上还原该功能。

在这种情况下,有几个简单的方法可以防止丢失在major功能:

  • 合并minormajor,然后恢复的复归。结果图应该是这样的:

    * revert the revert (major) 
    | 
    * merge minor into major 
    |\ 
    * | 
    | * (minor) 
    * | 
    | * revert feature on minor 
    * | merge minor into major 
    |\| 
    * | cherry-pick feature onto major 
    | * add feature to minor 
    * | 
    |/ 
    * 
    | 
    
  • 创建一个新的分支关闭的minor。我们称之为minor-for-merge。在这个分支上,恢复回复。然后将分支合并到major并删除分支。结果图应该是这样的:

    *  merge minor-for-merge into major (major) 
    |\ 
    | * revert the revert 
    * \ 
    | * (minor) 
    * | 
    | * revert feature on minor 
    * | merge minor into major 
    |\_ | 
    * \| cherry-pick feature onto major 
    | * add feature to minor 
    * _/ 
    |/ 
    * 
    | 
    

两种方法都可行。后者有点尴尬—承诺恢复恢复是在无人地带摇晃—,但它可以帮助您避免合并到major时大量的合并冲突。

无论哪种方式,minor的任何分支将合并到major而不会恢复该功能。如果minor之前的分支是在回复之前完成的,则回复将不会被合并到历史记录中。如果在回复之后关闭minor的分支(或者minor在归还之后合并到分支中) ,那么回复仍然不会被合并到历史中,因为该提交已经在major的祖先中。

+0

其实你的第二个场景与我所拥有的相似。我喜欢在合并之前提供恢复提交提交的想法。我会尝试一下,看看它是如何工作的。感谢您的详细解答。 –

+0

所以我在合并之前恢复了恢复提交。它工作完美无瑕。再次感谢。 –

2

我想你可以合并未成年分支和“恢复的恢复”,我的意思是

git merge <minor branch> 
git revert <revert commit> 

还要检查这个“How to Revert Faulty Merge ',这完全与你的问题无关,但你可以对'恢复还原'的效果有所了解。

+0

感谢您的回答。我很感激帮助。 –

+0

@MichaelBest不客气:)我很高兴理查德汉森提出了一个很好的答案,这个答案解释了我的英语不好。 – dyng