Git反复合并壁球

时间:2009-09-23 08:12:41

标签: git version-control merge

我正在尝试在git中使用二进制文件的两个分支 - 一个“开发”和一个“稳定”。在我想将它们“释放”到稳定分支之前,开发分支可以对这些文件进行多处更改(并且如果相关,则稳定分支会重命名这些文件)。

我可以进行正常的合并,这样可以正常工作,但保留了太多的历史记录 - 当拉动“稳定”分支时,所有来自“开发”分支的中间提交也被拉出(因为它们是父提交)。但是我们讨论的是没有任何合理的合并策略的二进制文件(除了他们/我们的),因此开发分支上的文件的实际历史是无用的。当我拉出“稳定”分支时,我得到了这个:

          X-------------------G stable
         /                   /
    a---b---c---d---e---f---g development

因为G在开发分支中有父项,所以我在我的存储库中获取了开发分支的全部历史记录(c,d,e,f和g的数据对象),我对此不感兴趣(X是与b相同,应用了一些文件重命名。)

所以我尝试从开发分支到稳定分支的git merge --squash更改。第一个这样的合并和提交就行了,结果如预期的那样(提交消息中的改变日志很好,与开发分支无关):

          X-------------------G stable
         /                   
    a---b---c---d---e---f---g development

在我拉出这个压扁的稳定分支后,我在我的存储库中得到了这个,这就是我想要的:

a---b---X---G

但是第二次合并失败了(因为git无法知道我已经合并了多少并且感到困惑)。

  • 是否有可能以某种方式记录合并,而不会与两个父母产生“合并提交”?
  • 或者,是否可以告诉git只合并某个“范围”的修订版,比如在SVN中?
  • 或者,是否可以进行正常合并而不必在拉动时从其他分支下载所有引用?
  • 或者我应该为相关文件提供自定义合并驱动程序,只需将“他们的”版本重命名为“我们的”,从而解决冲突?我仍然担心--squash会一直试图将整个历史合并到共同的父母,只解决我问题的一半。

更新:重新定位

如果我理解正确的变形,我最终会得到这个:

                              X stable
                             /
    a---b---c---d---e---f---g development

这让我得到了我不感兴趣的所有数据(c,d,e,f),作为奖励,我将丢失b在分支中是稳定版本的信息。

每个开发版本都会增加大约5MB的存储库大小(并且重新打包整个repo只会缩小大约10%),“稳定”分支几乎是免费的(数据已经存在)。我想从稳定分支中拉出一个新版本,只拉动新的5MB,而是从X更新到G下载25MB,因为我不知道我不知道我不关心c,d的内容,e和f。

5 个答案:

答案 0 :(得分:24)

开始
      X stable
     /                   
a---b---c---d---e---f---g development

您可以使用以下步骤将最后一次提交从开发分支复制到稳定分支:

git checkout development@{0}  # get working tree from "development", detach HEAD
git reset --soft stable  # reposition detached HEAD on "stable"
git commit  # enter the appropriate commit message
git branch temp  # create a temporary branch "temp" at HEAD
git checkout temp  # get on the new temporary branch
git branch -M stable  # rename "temp" to "stable"

所以你最终得到:

      X-------------------G stable
     /                   
a---b---c---d---e---f---g development

如果您继续开发“开发”,例如,

      X-------------------G stable
     /                   
a---b---c---d---e---f---g---h---i---j development

您可以重复上述相同的git命令,最终会得到:

      X-------------------G-----------J stable
     /                   
a---b---c---d---e---f---g---h---i---j development

答案 1 :(得分:7)

这不是使用merge --squash的正确位置。使用它的一个好地方是在一个一次性的主题分支,你将要合并到你的主分支然后摆脱。在主题分支中完成的所有开发都显示为主分支中的一个提交。在您的情况下,您应该正常从开发分支合并,然后使用git-rebase --interactive来压缩您想要的提交。

  
    

是否有可能以某种方式记录合并,而不会与两个父母产生“合并提交”?

  

如果我理解正确的话,不。 绝对不是

  
    

是否有可能告诉git只合并某个“范围”的修订版,比如在SVN中?

  

是。的 git merge [commit hash]

  
    

或者,是否可以进行正常合并而不必在拉动时从其他分支下载所有引用?

  

请参阅上一个问题的答案。

  
    

或者我应该为相关文件提供自定义合并驱动程序,只需将“他们的”版本重命名为“我们的”,从而解决冲突?我仍然害怕--squash会一直尝试将整个历史合并到普通父母,只解决我问题的一半。

  

没有! 只是不要使用git merge --squash 。这不适合使用它!

答案 2 :(得分:4)

您可以使用git rebase -i(交互模式)对所有更改进行sqash,只需将行更改为mmeld(更新:对于较新的Git版本类型ssquash

您将拥有一个可以合并的提交。如果你想保留你的每一步,你必须在进行rebase之前在你的黑客分支上创建另一个分支,这可以通过git branch small-dirty-changes-i-don’t-want-anybody-to-see

来完成

所有这一切都必须在尝试合并之前完成;一步一步:

# on branch "hacking": hack commit hack commit hack commit

# create a reference to your history
$ git branch dirty-history

# sqash your commits by setting all lines to "meld"
$ git rebase -i

# checkout master or the branch you want to merge to
$ git checkout master

# merge your squashed commit
$ git merge hacking
# or: $ git pull hacking

答案 3 :(得分:1)

top voted answer有效地区分了stable和development分支,并将stable中缺少的所有更改应用为一次提交。还有另一种方法可以做到这一点:

$ git checkout stable 
$ git diff stable development | git apply --index -   
$ git commit

在提交之前,您可以查看暂存的文件。如果要在应用diff后中止该过程,可以使用基本命令从索引和工作目录中删除更改。

$ git reset --hard

您可以多次重复此过程,因为每次需要合并时,您实际上只是在区分两个分支的提示。

请注意,此处的假设也适用于另一个答案:除了来自开发分支的之外,稳定分支中没有提交。如果同一行在两个分支中独立更改,与常规合并不同,此方法不会给您带来冲突。相反,它只会覆盖稳定分支中的变化与开发中的变化。

如果您担心这一点,那么每次提交stable时,都可以将合并的开发提交哈希范围放在提交消息中。这样,如果你需要回溯,你就会有一些记录。

答案 4 :(得分:-1)

我是git的新手,但似乎--squash就是你想要的,你只需要以不同的方式处理分支。

$ git merge --squash development
$ git branch -d development
$ git checkout -b development
# continue work on development branch

这实际上会截断开发分支的历史记录,下一次合并只会是你想要的。查看手册页似乎git branch -f development可能与删除和重新创建分支相同。

正如我所说,我对git很新,所以我喜欢这个想法的一些反馈。