zoukankan      html  css  js  c++  java
  • git merge 与 rebase

    1. git merge
    2. git rebase
    3. merge V.S. rebase
    4. 参考材料

    写在开始:

    对merge和rebase的用法总有疑惑,好像两个都能完成“获取别的branch的commits到我的branch上”,那二者的区别又是什么。通过一些文章和实验,整理如下,参考资料附后。


    1.git merge

    来看两种场景中merge的不同方式。

    • 场景一:切出特性分支后,develop分支上没有新的提交。

     

    fast-forward,若无分歧,会直接移动文件指针。看不出特性分支的起始点。

    no-fast-forward(--no-ff),保留提交链的完整性。

    squash,压缩不必要的commit;无法看出feature分支合到develop;feature,develop保持相对独立。

    •  场景二:切出特性分支后,develop分支上提交了C6,C7。

                      

    develop分支上提交了C6,C7,无法fast forward。

    three way merge,

      1. 找到develop分支的最新节点C7;
      2. 找到feature分支的最新节点C5;
      3. 找到develop分支和feature分支的共同祖先节点C3;
      4. 对C3,C5,C7进行三方合并,生成最新的C8。

     2.git rebase

    变基/衍合,从旧的base变基到新的base,在新base的基础上重现另一个分支的修改过程,版本树像两个链条串在一起变成一个链条,以达到线性的效果。

    rebase,对指定的base本身并没有什么影响;只是重写base之后的commit历史。

    来看几个场景:

    • 在继续开发的过程中和主分支develop同步

    从develop上拉出分支做一些开发工作,在这个过程中develop分支可能继续往前走了,那我们需要经常和develop保持下同步(可能是别人提交了公用的模块,或者修复了对大家都有影响的bug)。之前我会通过pull操作来达到这一目的,但pull往往内置了merge(pull的效果看起来就像fetch+merge,想想提到过的“merge应该反映业务层面的合并,而非技术行为”,并且此时merge会产生一些杂乱的历史记录)。

    这就相当于我们本地的开发工作(一系列的commits)是在旧的base上展开的,应该使用rebase操作,将本地的开发工作变基到develop的最新节点上。 

    git pull --rebase

    • 重新拾起搁置的工作

    很久之前可能启动一个并行工作(开发不着急上线的新特性或者优化一些功能),但一直没有时间处理所以就搁置了,现在又有时间重新拾起,然后就发现当时基于的base实在是太太太老了。现在肯定是希望基于最新的base展开工作,这样就可以从已解决的bugfix或已完成的新特性中中受益。

    • 在push之前整理我的本地历史
    git rebase -i <myBaseCommit>

    这是一个使用更频繁的场景:并不是为了变基,而是清理本地的commit。很多情况我们都需要commit:

      • 可能需要多个连续的commit才能完成一次bugfix;
      • 切换分支需要保存本地修改(当然按理说这个时候应该使用stash或者idea提供的shelve了);
      • 某些历史commit写错了msg(最近一次commit的msg可以通过 commit --amend 修改);

    通过-i(--interactive,交互式的),我们可以干预rebase将要执行的脚本化过程,从而达到清理本地commit历史的目的。

    关于git rebase -i 的博文:聊下 git rebase -i

    熟练使用rebase,可以轻松的进行commit,只需要在最终push之前做一次清理,不必担心影响到公共仓库。

    git fetch origin develop
    git rebase origin/develop
    ... do sth ...
    git push
    • rebase的场景和用法还有待探索,慢慢更新了。

    记住这个:

    只能rebase私有分支,一旦发布到公共仓库,不要再rebase了。


    3.merge V.S. rebase

    什么时候用merge;基于上述不同的merge行为(fast-forward,--no-ff,squash),什么场景下用哪种merge:

    merge执行一个合并,这个合并应该反应业务层面的合并,而非技术行为。我们希望在当前分支上往前走,这样它就包含了其他分支的工作。

    所以问题的关键是:这个“其他分支”是什么样的分支?这个“其他分支”需要在历史图谱中展示么?

    • 本地的、临时的分支,使用它仅仅是为了使master保持clean。

    1.若拉出本地分支后,master往前走了,此时在本地分支:

    git rebase -i master
    

     将本地分支变基到最新的master节点(重新梳理本地历史提交信息比如合并成一个commit),好似本地分支就是在最新的master节点上做的开发工作,以保证合并到master后呈现线性增长。

    2.在master上:

    git merge (fast-forward)

     最终以一个或几个commit展现在master上。

    • 知名分支,团队明确定义的,可能是用来追踪bug/feature。

    永远不要用rebase,而是用

    git merge --no-ff

     以保留清晰完整的历史图谱。


     4.参考材料

    GETTING SOLID AT GIT REBASE VS. MERGE

    git rebase vs git merge详解

    Git team workflows: merge or rebase?

    git随笔集

    git merge的几种形式

    A successful Git branching model

    聊下 git rebase -i

    git protocol

     

  • 相关阅读:
    centos上安装禅道
    BootStrap-Table主子表
    开源项目学习
    javascript字面量
    linux下vi的一些简单的操作
    vuejs 开发中踩到的坑
    leetcode 220. Contains Duplicate III 求一个数组中有没有要求的元素 ---------- java
    leetcode 219. Contains Duplicate II 求一个数组中有没有重复元素 ---------- java
    leetcode 1
    leetcode 217. Contains Duplicate 求一个数组中有没有重复元素 ---------- java
  • 原文地址:https://www.cnblogs.com/xhz-dalalala/p/9000994.html
Copyright © 2011-2022 走看看