代码之家  ›  专栏  ›  技术社区  ›  polygenelubricants

Git反复合并挤压

  •  25
  • polygenelubricants  · 技术社区  · 16 年前

    我尝试在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 回复  |  直到 7 年前
        1
  •  24
  •   pvillela    14 年前

    从开始

          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
    
        2
  •  7
  •   Paul T. Rawkeen Bartosz Zasada    8 年前

    这地方不适合用 merge --squash . 使用它的一个好地方是在一个废弃的主题分支中,这个分支将合并到您的主分支中,然后去掉。主题分支中完成的所有开发都显示为主分支中的一个提交。在您的情况下,您应该正常地从开发分支合并,然后使用 git-rebase --interactive 去粉碎你想要的承诺。

    是否可以在不生成与两个父级的“合并提交”的情况下以某种方式记录合并?

    如果我正确理解这个问题,不。 绝对不是 .

    是否可以告诉Git只合并某些“范围”的修订,比如在SVN中?

    对。 git merge [commit hash]

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

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

    或者,我应该为相关文件提供一个自定义合并驱动程序,只需将“它们的”版本重命名为“我们的”,从而解决冲突?我仍然害怕——壁球总是试图将整个历史融合到共同的父母身上,只解决了我一半的问题。

    不! 只是不要使用 git merge --squash .这不是使用它的正确地方!

        3
  •  4
  •   knittl    7 年前

    你可以使用 git rebase -i (交互模式)要对所有更改进行sqash,只需将行更改为 m meld (更新:对于较新的git版本类型 s squash )

    您将拥有一个可以合并的提交。如果你想保留你的每一步,你必须在你的黑客分支上创建另一个分支,然后再进行重新平衡,这可以用 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
    
        4
  •  1
  •   Community CDub    8 年前

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

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

    在提交之前,可以查看阶段文件。如果要在应用diff之后中止进程,只需使用基本命令从索引和工作目录中删除更改。

    $ git reset --hard
    

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

    请注意,这里也有适用于其他答案的假设: 除了来自开发部门的承诺外,稳定部门没有其他承诺。 . 如果同一行在两个分支中被独立地更改,与常规合并不同,这种方法不会给您带来冲突。相反,它只会用正在开发的分支覆盖稳定分支中的更改。

    如果您关心这个问题,那么每次在稳定状态下提交时,都可以将合并的开发提交哈希范围放在提交消息中。这样,你就有了一些记录,如果你需要回溯的话。

        5
  •  -1
  •   Glenn Moss    14 年前

    我对Git不熟悉,但看起来——壁球是你想要的,你只需要以不同的方式处理分支。

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

    这实际上会截断开发分支的历史,下一次合并将只是您想要的。看着手册页,好像 git branch -f development 可以执行与删除和重新创建分支相同的操作。

    正如我所说,我对Git还很陌生,所以我希望能得到一些关于这个想法的反馈。