git rebase

rebase ⇒ 将一系列节点移动到目标分支的最后 ⇒ 也叫变基

rebase vs cherry-pick

rebasecherry-pick 的操作角度是不一样的

  • cherry-pick 是把别的分支提交合并到当前分支
  • rebase 是把自己提交合并到目标分支

基本原理

初始分支结构为

此时在dev 分支执行 git rebase main

  1. 复制 c2c3 生成内容完全一致,但sha-1不一致的节点
  2. dev 分支移动到了复制后的c3'
  3. c2c3 没有使用,被称之为 悬挂提交,再下次 git 自动执行 git gc 时会被自动移除

此时看起来就像是 dev分支是基于 main分支的最新提交来开发的

这样的好处是

  1. 整个开发分支线变成线性的了,相对简单
  2. main 分支执行 git merge dev 的时候就变成了 快进合并

这也是rebasemerge 的最大区别

  1. merge 如果不是快进会产生新的提交节点
  2. rebase 是让节点尽可能的线性,使merge 可以快进合并

其中 c3' 是和c3 节点内容完全一致的节点,之所以不复用之前的节点是因为,节点的parent 发生了改变,即改变了历史

在变基的过程中,是需要变基节点依次进行变基操作

  1. c2 执行变基,将c2 相对于c1 的变动作用于c5 ,并依次为基础生成c2'
  2. c3 执行变基,将c3 相对于c2 的变动作用于c2' ,并依次为基础生成c3'
  3. 如果有其余节点指向类似操作

所以其本质也是依次执行三路合并

  1. 第一次 ⇒ 三路为 c1c2c5
  2. 第二次 ⇒ 三路为 c3c2c2'
  3. 依次类推

既然是三路合并,就可能会产生冲突,解决方法如下

  1. 解决冲突:用编辑器(比如 vi)修改冲突文件,保留需要的改动,然后用以下命令继续:

    shell 复制代码
    git add .
    git rebase --continue
  2. 忽略冲突::

    shell 复制代码
    git rebase --skip

    意思是冲突了,就将当前提交视为空提交,直接跳过,不合并 ⇒ 不推荐

  3. 终止变基:不想继续变基,恢复到变基前的状态:

    shell 复制代码
    git rebase --abort

    此时会和数据库的事务一样,依次回滚,将之前的变基操作都还原

rebase vs merge

并列分支

单人维护分支推荐使用rebase ,假设分支结构如下

shell 复制代码
A---B---C---D (main)
     \   \
      \   H---I (fix/log)
       \
        E---F---G (fix/login)

此时在 fix/login 分支执行 git rebase main ,再切到 main 执行git merge fix/login

shell 复制代码
A---B---C---D---E'---F'---G' (main)
         \
          H---I (fix/log)

此时别的分支不会受到任何影响,使用rebase 还可以让分支合并是线性的,而merge 合并后会生成新节点

例如在 main 分支直接执行 git merge fix/login ,此时将会生成一个新合并节点 M

shell 复制代码
A---B---C---D----------M  (main)
     \   \           /
      \   E---F---G-/   (fix/login)
       \
        H---I          (fix/log)

分支上的分支(依赖分支)

shell 复制代码
A---B---C---D (main)
     \
      E---F---G 
          \
           X---Y 

此时就需要团队协商确认,大家统一使用merge 还是 rebase

假设初始分支如下

shell 复制代码
A---B---C---D (main)
     \
      E

张三从 E 开始继续开发,生成FG

shell 复制代码
A---B---C---D (main)
     \
      E---F---G (fix/zs)

但此时李四,从E 开了一个新分支进行开发, 结构变成了

shell 复制代码
A---B---C---D (main)
     \
      E---F---G (fix/zs)
          \
           X---Y (fix/ls)

此时如果在 fix/zs 执行 git rebase main

对于张三而言,分支就变成了

shell 复制代码
A---B---C---D---E'---F'---G' (main)

此时张三进行了更新推荐,李四执行了git pull 此时对于李四而言,她的分支变成了

shell 复制代码
A---B---C---D---E'---F'---G' (main)
     \
      E---F---G 
          \
           X---Y (fix/ls)

原分支不变,E'F'G' 会新增提交

如果此时在 fix/ls 执行 git rebase main

  • 因为 EFGE'F'G' 内容一致

    所以 EFG 会被抛弃,直接使用 E'F'G'

    所以 EFG 也被称之为 空提交

最终分支结构如下

shell 复制代码
A---B---C---D---E'---F'---G' (main)
											\
						           X---Y (fix/ls)

此时并不会有很大的问题

但如果此时 李四在main执行的git merge fix/ls , 分支结构就变成了

shell 复制代码
A---B---C---D---E'---F'---G'---M  (main)
     \                   \     /
      E---F---G           \   /
          \                X---Y (fix/ls)
           \                    /
            --------------------

此时很明显 存在很多重复的 parent 节点

所以一般情况下,推荐分支的开发模式是 git flow模型 + git rebase

  1. rebase 单人维护开发的分支

  2. 如果一个分支是多人一起维护的,就不能随意使用rebase

    • 此时要么都用merge ,要么都用rebase
    • 不应该混用mergerebase
相关推荐
louis.D.11 小时前
git 删除标签完整步骤总结
git
晴天1612 小时前
Git 图形界面工具现状-Day28
git
AD_youyu15 小时前
Git 安装教程
git
hj28625116 小时前
Git 与 DevOps/CI/CD 核心知识整理
git
中科三方16 小时前
DNS解析中的“委派“是什么意思?如何正确配置NS记录?
git·github·dns解析
OPEN-F17 小时前
Python进阶教程:Git版本控制与团队协作
git·python·elasticsearch
深念Y19 小时前
Fork 仓库瘦身指南:从 90MB 到 11MB
git·github·仓库·历史·瘦身·fork·上游
叫我少年19 小时前
Git SSH 配置:从生成密钥到远程连接
git·后端
阿火~1 天前
Git 项目配置与推送完整指南
git
j7~1 天前
【Git】《Git 系列指南(二):Git基本操作与 reset 三种模式》
运维·git·git安装·git基本操作·git配置·创建git仓库·git reset三种模式