ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

git rebase简介

git rebase简介

git rebase核心作用:把你当前分支上的提交,重新“搬到”另一个分支的最新提交后面。

通俗说就是:
你本地写了几个 commit,但主分支master/main/dev已经被别人更新了。你想让自己的代码基于最新主分支继续开发,就可以用rebase。


1. 先看普通开发场景

假设公司远程分支是:

origin/dev: A --- B --- C

你从B拉出来开发了两个提交:

你的 feature 分支: A --- B --- D --- E

但是别人已经把C合进了dev:

origin/dev: A --- B --- C

现在整体是这样:

D --- E 你的 feature / A --- B --- C origin/dev

你执行:

gitcheckout featuregitfetch origingitrebase origin/dev

rebase 之后变成:

A --- B --- C --- D' --- E'

注意:D、E会变成D'、E',因为它们被“重新应用”了一遍,commit id 会变。


2.rebase和merge的区别

用merge

gitcheckout featuregitmerge origin/dev

结果可能是:

D --- E -------- M / / A --- B --- C ----------

会多一个合并提交M。

用rebase

gitcheckout featuregitrebase origin/dev

结果是:

A --- B --- C --- D' --- E'

历史更直,看起来像你是基于最新dev开发的。

所以很多公司喜欢:

gitpull--rebase

而不是普通:

gitpull

因为普通pull默认可能会产生 merge commit。


3. 最常用命令

场景一:更新自己的开发分支

你在feature_xxx分支开发,想同步最新dev:

gitcheckout feature_xxxgitfetch origingitrebase origin/dev

这就是最常见用法。


场景二:拉代码时直接 rebase

普通拉取:

gitpull

可能会自动 merge。

推荐写法:

gitpull--rebase

等价于:

gitfetchgitrebase origin/当前分支

例如你在dev分支:

gitpull--rebaseorigin dev

4. rebase 遇到冲突怎么办?

执行:

gitrebase origin/dev

如果冲突了,Git 会提示类似:

CONFLICT (content): Merge conflict in main.c

这时候流程是:

第一步:看冲突文件

gitstatus

你会看到哪些文件冲突了。

第二步:打开冲突文件

里面可能是这样:

<<<<<<<HEADintspeed=100;=======intspeed=200;>>>>>>>D

含义:

<<<<<<< HEAD 这是目标分支 origin/dev 上的内容 ======= 这是你自己提交里的内容 >>>>>>> 你的提交

你手动改成最终想要的,比如:

intspeed=200;

然后删除<<<<<<<、=======、>>>>>>>这些标记。

第三步:标记冲突已解决

gitaddmain.c

第四步:继续 rebase

gitrebase--continue

如果还有冲突,继续重复:

改文件gitadd文件gitrebase--continue

5. 想放弃 rebase 怎么办?

如果 rebase 到一半你懵了,不想继续了:

gitrebase--abort

它会回到 rebase 之前的状态。

这个命令很重要,记住:

gitrebase--abort

6. interactive rebase:整理 commit 用的

这个也很常用,尤其是 Gerrit / Code Review 前。

比如你最近提交了 3 个 commit:

gitlog--oneline

看到:

a3c1111 fix typo b2d2222 add uart driver c1e3333 debug print

你想整理最近 3 个提交:

gitrebase-iHEAD~3

会打开一个编辑界面:

pick c1e3333 debug print pick b2d2222 add uart driver pick a3c1111 fix typo

常用操作:

pick 保留这个 commit reword 修改 commit message squash 合并到上一个 commit,并合并 message fixup 合并到上一个 commit,但丢掉当前 message drop 删除这个 commit

比如你想把fix typo合并到add uart driver:

pick c1e3333 debug print pick b2d2222 add uart driver fixup a3c1111 fix typo

保存退出后,Git 会帮你整理提交。


7. 嵌入式项目里最常用的 rebase 流程

假设你在公司开发cat_litter_motor_ctrl分支,主分支是dev:

# 1. 切到自己的开发分支gitcheckout cat_litter_motor_ctrl# 2. 拉取远程最新代码gitfetch origin# 3. 把自己的提交搬到最新 dev 后面gitrebase origin/dev# 4. 如果有冲突,解决冲突gitstatus# 手动改冲突文件gitaddxxx.cgitrebase--continue# 5. rebase 完后看提交历史gitlog--oneline--graph--decorate--all

如果你之前已经推送过这个分支,rebase 后 commit id 变了,普通 push 会失败,需要:

gitpush --force-with-lease

不要随便用:

gitpush-f

更推荐:

gitpush --force-with-lease

它比-f安全一些,防止你把别人新推的代码覆盖掉。


8. 最重要的禁忌

不要随便 rebase 公共分支。

比如这些分支不要乱 rebase:

master main dev release

尤其是多人都在用的远程分支。

适合 rebase 的是你自己的开发分支:

feature_xxx bugfix_xxx my_uart_debug

一句话:

自己的分支可以 rebase; 大家共用的分支不要乱 rebase。

9. 你实际最常用记这几个就够了

# 更新远程信息gitfetch origin# 把当前分支变基到最新 devgitrebase origin/dev# 解决冲突后继续gitadd.gitrebase--continue# 放弃 rebasegitrebase--abort# 拉代码时使用 rebasegitpull--rebase# 整理最近 3 个提交gitrebase-iHEAD~3

10. 跟 Gerrit 的关系

你之前用过 Gerrit / repo,这里 rebase 很常见。

比如你提交 review 前,远程tws-dev更新了,你本地 patch 落后了,通常流程是:

gitfetch origingitrebase origin/tws-devgitpush origin HEAD:refs/for/tws-dev

如果 Gerrit 提示冲突,基本就是让你先在本地 rebase 到最新目标分支,再重新推 review。


可以把rebase理解成一句话:

我写的代码不变,但我想假装自己是在最新代码基础上写的。

所以它会把你的 commit 一个一个摘下来,然后重新放到最新分支后面。

返回列表