• Git 之 merge 与 rebase 的区别


    首先看下面举例:

    1. 假定 1-2 是现在的master分支状态;
    2. 这个时候从 master 分支 checkout 出来一个 Dev01 分支;
    3. 然后 master 提交了 3、4,Dev01 提交了5、6、7;
    4. 这个时候 master 分支状态就是 1-2-3-4 ,Dev01 分支状态变成 1-2-5-6-7
    5. 如果在 Dev01 分支上,用 rebase master,Dev01 分支状态就成了 1-2-3-4-5-6-7
    6. 如果在 Dev01 分支上,用 merge:

    1-2-5-6-7-8

    ........ |3-4|

        7.会出来一个 8,这个 8 的提交就是把 3-4 合进来的提交。

    2者区别:

    假设当前从 master 分别切出了两个分支:learn-rebase 和 learn-merge,它俩分别都进行了两次 commit,我们希望把两个分支的内容都合并到 master 上

    clipboard.png

    Merge(合并)

    fast-forward

    使用 merge 可以合并多个历史记录的流程。

    首先我们合并 learn-merge 分支,只看蓝色的部分,learn-merge 分支与 master 分支的最新 commit 在同一条线上,这说明 learn-merge 分支的历史记录包含 master 分支所有的历史记录,那么这个合并是非常简单的。只需要通过把 master 分支的位置移动到 learn-merge 的最新分支上,Git 就会合并。这样的合并被称为 fast-forward(快进)合并。(fast-forward 模式下是不可能出现冲突的)

    操作如下:

    ➜  git branch
      learn-merge
      learn-rebase
    * master
    ➜  git merge learn-merge
    Updating 594a6c9..c2b4ae3
    Fast-forward
     myfile.txt | 2 ++
     1 file changed, 2 insertions(+)

    结果如下:

    clipboard.png

    非 fast-forward

    接下来需要合并 learn-rebase 分支,此时可以看到 master 的最新 commit 已经和 learn-merge 保持一致了,与 learn-rebase 分支不在一条直线上,那此时就不能进行 fast-forward 合并了。

    在这种情况下使用 merge 方法,可以合并两个修改并生成一个新的提交。(此时可能会出现冲突的情况,因为 learn-rebase 分支可能与 learn-merge 分支修改同一个文件)

    操作如下:

    ➜  git merge learn-rebase
    Auto-merging myfile.txt
    CONFLICT (content): Merge conflict in myfile.txt
    Automatic merge failed; fix conflicts and then commit the result.
    ➜  vim myfile.txt # 解决冲突
    ➜  git add myfile.txt
    ➜  git commit -m 'fix conflicts'
    [master 2a6899b] fix conflicts

    结果如下:

    clipboard.png

    设置 non fast-forward

    执行合并时,如果设定了non fast-forward 选项,即使在能够 fast-forward 合并的情况下也会生成新的提交并合并。

    clipboard.png

    设置方法:添加 -no-ff 选项

    rebase(变基)

    与 merge 会保留修改内容的历史记录不同,rebase 是在原有提交的基础上将差异内容反映进去。让我们回到 merge learn-rebase 之前的样子。

    clipboard.png

    rebase 的步骤分为两步,第一步将 learn-rebase 分支的历史记录添加在 master 分支的后面。这个时候可能会有冲突,当出现冲突时,解决冲突后的提交不是使用 commit 命令,而是执行 rebase 命令指定 --continue 选项。若要取消 rebase,指定 --abort 选项。

    clipboard.png

    操作如下:

    ➜  git checkout learn-rebase
    Switched to branch 'learn-rebase'
    ➜  git rebase master
    First, rewinding head to replay your work on top of it...
    Applying: add rebase
    Using index info to reconstruct a base tree...
    M   myfile.txt
    Falling back to patching base and 3-way merge...
    Auto-merging myfile.txt
    CONFLICT (content): Merge conflict in myfile.txt
    error: Failed to merge in the changes.
    Patch failed at 0001 add rebase
    The copy of the patch that failed is found in: .git/rebase-apply/patch
    When you have resolved this problem, run "git rebase --continue".
    If you prefer to skip this patch, run "git rebase --skip" instead.
    To check out the original branch and stop rebasing, run "git rebase --abort".
      1 merge 与 rebase 的差别
    ➜  vim myfile.txt # 解决冲突
    ➜  git add myfile.txt
    ➜  git rebase --continue
    Applying: add a new line

    结果如下:

    clipboard.png

    然后再使用 fast-forward 合并即可

    ➜  git checkout master
    Switched to branch 'master'
    ➜  git merge learn-rebase
    Updating 0b9e66f..1fc71b9
    Fast-forward
     myfile.txt | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)

    对比 merge 和 rebase 最终的历史记录,可以发现 merge 保持了修改内容的历史记录,但是历史记录会很复杂;而 rebase 后的历史记录简单,是在原有提交的基础上将差异内容反映进去。

    clipboard.png

    rebase 黄金定律

    奇妙的变基也并非完美无缺,要用它得遵守一条准则:

    不要对在你的仓库外有副本的分支执行变基。

    变基操作的 实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。 如果你已经将提交推送至某个仓库,而其他人也已经从该仓库拉取提交并进行了后续工作,此时,如果你用 git rebase 命令重新整理了提交并再次推送,你的同伴因此将不得不再次将他们手头的工作与你的提交进行整合,如果接下来你还要拉取并整合他们修改过的提交,事情就会变得一团糟。

    merge vs rebase

    到底该使用 merge 方式开发还是使用 rebase 方法开发是有争议的

    有一种观点认为,仓库的提交历史即是 记录实际发生过什么。 它是针对历史的文档,本身就有价值,不能乱改。 从这个角度看来,改变提交历史是一种亵渎,你使用谎言掩盖了实际发生过的事情。 如果由合并产生的提交历史是一团糟怎么办? 既然事实就是如此,那么这些痕迹就应该被保留下来,让后人能够查阅。

    另一种观点则正好相反,他们认为提交历史是 项目过程中发生的事。 没人会出版一本书的第一版草稿,软件维护手册也是需要反复修订才能方便使用。 持这一观点的人会使用 rebase 及 filter-branch 等工具来编写故事,怎么方便后来的读者就怎么写。

    总的原则是,只对尚未推送或分享给别人的本地修改执行变基操作清理历史,从不对已推送至别处的提交执行变基操作,这样,你才能享受到两种方式带来的便利。

    撤销提交的不同

    如果使用 merge 进行合并,可以使用 revert 命令对 merge 的内容进行撤销操作(参考 revert),而使用 rebase 则不行(已经没有 merge commit 了),而需要使用 rebase -i 对提交进行重新编辑(参考 交互式 rebase)。

    转自:时间被海绵吃了 https://segmentfault.com/a/1190000012897637

    参考

  • 相关阅读:
    2-sat问题,输出方案,几种方法(赵爽的论文染色解法+其完全改进版)浅析 / POJ3683
    hdu 4587 2013南京邀请赛B题/ / 求割点后连通分量数变形。
    最小费用最大流粗解 poj2516
    hdu3078 建层次树+在线LCA算法+排序
    hdu 3594 Cactus /uva 10510 仙人掌图判定
    有向图最小路径覆盖方法浅析、证明 //hdu 3861
    hdu 1827 有向图缩点看度数
    条件转化,2-sat BZOJ 1997
    2-sat基础题 BZOJ 1823
    2-sat 分类讨论 UVALIVE 3713
  • 原文地址:https://www.cnblogs.com/zhangzhang-y/p/13682281.html
Copyright © 2020-2023  润新知