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
相关推荐
自动花钱机1 小时前
Cherry-pick冲突与Git回滚
git
苏元7 小时前
☠️ 写错 commit = 绩效自爆,别说我没提醒你!
git
程序设计实验室7 小时前
模型文件硬塞进 Git,GitHub 直接打回原形:使用Git-LFS管理大文件
git
Dontla1 天前
脚本:git push直到成功(windows powershell命令)(Github连不上、Github断开)
git·github
CAE虚拟与现实1 天前
GitHub Desktop 和 Git 命令行工具(CLI)各有优势
git·github·github desktop
RePeaT1 天前
代码双仓库备份指南:三种简单高效的方法
git·github
coderklaus1 天前
Git GC
git
xiezhr1 天前
Git提交错了,别慌!还有后悔药
git·gitlab·github
GGGGGGGGGGGGGG.1 天前
CI/CD 全链路实践:从 Git 基础到 Jenkins + GitLab 企业级部署
运维·git·ci/cd·云原生·gitlab·jenkins