【问题标题】:What is the difference between merge --squash and rebase?合并 --squash 和 rebase 有什么区别?
【发布时间】:2011-01-26 12:02:02
【问题描述】:

我是 git 新手,我正在尝试了解 squash 和 rebase 之间的区别。据我了解,您在进行变基时会执行壁球。

【问题讨论】:

    标签: git merge rebase git-rebase squash


    【解决方案1】:

    Merge squash 将一棵树(一系列提交)合并为一个提交。也就是说,它压缩n 次提交中所做的所有更改到单个提交中。

    变基就是变基,即为树选择一个新的基(父提交)。也许这方面的反复无常的术语更清楚:他们称之为移植,因为它就是:为一棵树选择一个新的基础(父提交,根)。

    在进行交互式变基时,您可以选择压缩、选择、编辑或跳过要变基的提交。

    希望这很清楚!

    【讨论】:

    【解决方案2】:

    git merge --squashgit rebase --interactive 都可以产生“压缩”提交。但它们的用途不同。

    将在目标分支上生成一个压缩提交,而不标记任何合并关系。 (注意:它不会立即产生提交:您需要额外的git commit -m "squash branch"

    如果您想完全放弃源分支,这很有用,从(从SO question 获取的模式):

    git checkout stable
    
              X               stable
             /
    a---b---c---d---e---f---g tmp
    

    到:

    git merge --squash tmp
    git commit -m "squash tmp"
    
    
    # In the following graph, G is c--d--e--f--g squashed together
    
              X-------------G stable
             /
    a---b---c---d---e---f---g tmp
    

    然后删除tmp 分支。


    注意:git merge has a --commit option,但不能与--squash 一起使用。 从来没有可以同时使用--commit--squash。 自 Git 2.22.1(2019 年第三季度)以来,这种不兼容性已经明确:

    请参阅commit 1d14d0c(2019 年 5 月 24 日)Vishal Verma (reloadbrain)(2019 年 7 月 25 日在 commit 33f2790 中由 Junio C Hamano -- gitster -- 合并)

    merge:拒绝--commit--squash

    以前,当--squash 被提供时,'option_commit' 是静默的 掉了。这对于试图覆盖的用户来说可能是令人惊讶的 明确使用--commit 的壁球的无提交行为。

    git/git builtin/merge.c#cmd_merge() 现在包括:

    if (option_commit > 0)
        die(_("You cannot combine --squash with --commit."));
    

    在一个新的基础上重放您的部分或全部提交,允许您压缩(或最近“修复”,请参阅SO question),直接转到:

    git checkout tmp
    git rebase -i stable
    
       stable
          X----------------G tmp
         /
    a---b
    

    如果您选择压缩所有tmp 的提交(但是,与merge --squash 不同,您可以选择重放一些,并压缩其他的)。

    所以区别是:

    • squash 不会触及您的源分支(此处为tmp)并在您想要的位置创建单个提交。
    • rebase 允许您继续使用同一源分支(仍然是 tmp):
      • 新基地
      • 更清晰的历史

    【讨论】:

    • Gc--d--e--f--g 挤在一起了吗?
    • @Wayne:是的,这些例子中的 G 代表 tmp 的提交被挤压在一起。
    • @Th4wn:由于 Git 使用所有项目的快照的原因,G 不会代表与 g 相同的内容,因为 X 引入了更改。
    • @VonC:不确定最后的评论。如果你有一个git merge --no-ff temp 而不是git merge --squash temp,那么你会得到一个更混乱的历史,但你也可以更容易地做git revert e 之类的事情。这是一段混乱但诚实务实的历史,主要分支仍然相当干净。
    • @naught101 我同意。正如stackoverflow.com/a/7425751/6309 中所解释的那样,当使用太频繁时(如git pull --no-ffstackoverflow.com/questions/12798767/…),它也是关于不破坏git bisectgit blame。反正没有一种方法,这就是为什么本文描述了三种方法 (stackoverflow.com/questions/9107861/…)
    【解决方案3】:

    合并提交:保留分支中的所有提交并将它们与基分支上的提交交错

    Merge Squash:保留更改但忽略历史中的单个提交

    Rebase:这会将整个功能分支移动到 master 分支的顶端,有效地将所有新提交合并到 master 中

    更多关于here


    前两张图来自About pull request merges on the GitHub Docs

    【讨论】:

    • 我发现这比接受的答案更清楚。谢谢!
    • 这是迄今为止几乎任何地方关于该主题的最佳答案。谢谢。
    • 真的比公认的答案好。谢谢
    • 你先生应该获得奖牌
    • 第一张图在我看来完全错误。不知何故,提交 D 最终没有父节点。
    【解决方案4】:

    让我们从下面的例子开始:

    现在我们有 3 个选项可以将 feature 分支 的更改合并到 ma​​ster 分支

    1. 合并提交
      将保留 feature 分支 的所有提交历史并将它们移动到 ma​​ster 分支
      将添加额外的虚拟提交。

    2. 变基和合并
      feature 分支 的所有提交历史记录附加到 ma​​ster 分支
      的前面 不会添加额外的虚拟提交。

    3. 压缩和合并
      将所有功能分支提交分组到一个提交,然后将其附加到主分支的前面
      将添加额外的虚拟提交。

    您可以在下面找到 ma​​ster 分支 将如何处理它们中的每一个。

    在所有情况下:
    我们可以安全地删除功能分支

    【讨论】:

    • 你能解释一下第二张图片中的虚拟提交是什么吗?我是 git 的初学者。
    • @Yusuf,它只是一个包含两个分支更新的额外提交,它的默认提交消息 =“Megre 分支 XYZ 到 master”
    • 对于“压缩和合并”:有一个包含所有分组提交加上一个“额外虚拟提交”的提交?
    • @leticia 所有分组提交的提交 = “额外的虚拟提交”本身,如上图
    • 那么我认为“压缩和合并”不会添加额外的虚拟提交,而只会在主分支前面“重新设置”/追加提交。您在上面描述的上下文中的虚拟提交与 1. 和 3. 中的虚拟提交不同,因为 1 中的虚拟提交是“将分支 XYZ 合并到生成此提交的 master 中”,而 3 中的虚拟提交是“压缩提交到这个提交不是由合并产生的额外提交'
    猜你喜欢
    • 1970-01-01
    • 2012-08-12
    • 2012-03-24
    • 2015-03-21
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    相关资源
    最近更新 更多