git rebase 让你的提交记载愈加明晰可读

git rebase 的运用

rebase 翻译为变基,它的效果和 merge 很相似,用于把一个分支的修正兼并到别的一个分支上。

如下图所示,下图介绍了经过 rebase 前后提交前史的改变状况。

git merge 和 git rebase的区别

现在咱们来用一个比如来解释一下上面的进程。

假定咱们现在有2条分支,一个为 master\color{#2196F3}{master} ,一个为 feature/1\color{#2196F3}{feature/1},他们都根据初始的一个提交 addreadme\color{#2196F3}{add \ readme} 进行检出分支,之后,master 分支增加了 3.js\color{red}{3.js},和 4.js\color{red}{4.js} 的文件,分别进行了2次提交,feature/1\color{#2196F3}{feature/1} 也增加了 1.js\color{red}{1.js}2.js\color{red}{2.js} 的文件,分别对应以下2条提交记载。

master\color{#2196F3}{master} 分支如下图:

git merge 和 git rebase的区别

feature/1\color{#2196F3}{feature/1} 分支如下图:

git merge 和 git rebase的区别

结合起来看是这样的:

git merge 和 git rebase的区别

此刻,切换到feature/1 分支下,履行git rebase master,成功之后,经过 log 检查记载。

如下图所示:可以看到先是逐个应用了 master 分支的更改,然后以master\color{#2196F3}{master} 分支最终的提交作为基点,再逐个应用feature/1\color{#2196F3}{feature/1} 的每个更改。

git merge 和 git rebase的区别

所以,咱们的提交记载就会非常明晰,没有分叉,上面演示的是比较顺利的状况,但是大部分状况下,rebase 的进程中会产生抵触的,此刻,就需求手动处理抵触,然后运用 git addgit rebase --continue 的方式来处理抵触,完结 rebase,假如不想要某次 rebase 的结果,那么需求运用 git rebase --skip 来越过这次 rebase

git merge 和 git rebase 的区别

不同于git rebase的是,git merge在不是fast-forward(快速兼并)的状况下,会产生一条额外的兼并记载,相似 Merge branch 'xxx' into 'xxx' 的一条提交信息。

git merge 和 git rebase的区别

别的,在处理抵触的时分,用merge只需求处理一次抵触即可,简略粗暴,而用rebase的时分 ,需求一次又一次的处理抵触。

git rebase 交互模式

在开发中,常会遇到在一个分支上产生了许多的无效的提交,这种状况下运用rebase的交互式模式可以把现已发生的多次提交压缩成一次提交,得到了一个干净的提交前史,例如某个分支的提交前史状况如下:

git merge 和 git rebase的区别

进入交互式模式的方法是履行:

git rebase -i <base-commit>

参数 base-commit 就是指明操作的基点提交目标,根据这个基点进行 rebase 的操作,关于上述提交前史的比如,咱们要把最终的一个提交目标 (ac18084\color{#F19E38}{ac18084}) 之前的提交压缩成一次提交,咱们需求履行的指令格局是

git rebase -i ac18084

此刻会进入一个vim的交互式页面,修正器列出的信息像下列这样。

git merge 和 git rebase的区别

想要兼并这一堆更改,咱们要运用squash策略进行兼并,即把当时的commit和它的上一个commit内容进行兼并, 大概可以表明为下面这样。

pick  ... ...
s     ... ... 
s     ... ... 
s     ... ... 

修正文件后 按下 : 然后 wq 保存退出,此刻又会弹出一个修正页面,这个页面是用来修正提交的信息,修正为 feat: 更正,最终保存一下,接着运用 git branch 检查提交的 commit 信息,rebase 后的提交记载如下图所示,是不是清新了许多? rebase 操作可以让咱们的提交前史变得愈加明晰。

git merge 和 git rebase的区别

特别注意,只能在自己运用的 feature 分支上进行 rebase 操作,不允许在集成分支上进行 rebase,由于这种操作会修正集成分支的前史记载。

rebase 的危险

patch:【假定本地分支为 dev1,c1 和 c2 是本地往 dev1 分支上做的两次提交】把 dev1 分支上的c1和 c2 “拆”下来,并临时保存成 c1′ 和 c2’。git 里将其称为 patch

rebase\color{red}{rebase} 会将当时分支的新提交拆下来,保存成 patch\color{red}{patch},然后兼并进其他分支新的 commit\color{red}{commit},最终将 patch\color{red}{patch} 接进当时分支。这是 rebase\color{red}{rebase} 对多条分支的操作。关于单条分支,rebase\color{red}{rebase} 还可以兼并多个 commit\color{red}{commit} 单号,将多个提交兼并成一个提交。

git rebase -i [commit id]指令可以兼并(整改) commit id 之前的一切 commit\color{red}{commit} 单。加上-i选项可以提供一个交互界面,分阶段修正commit信息并 rebase\color{red}{rebase}

但这儿就会呈现一个问题:假如你兼并多个单号时,一不小心兼并多了,将别人的提交也兼并了,此刻你本地的 commithistory\color{red}{commit \ history} 和长途库房的 commithistory\color{red}{commit \ history} 不一样了,不管你如何 push\color{red}{push},都无法推送你的代码了。假如你并不记住 rebase\color{red}{rebase} 之前的 HEAD\color{red}{HEAD} 指向的 commit\color{red}{commit}commitID\color{red}{commit \ ID} 的话,gitreflog\color{red}{git \ reflog} 都救不了你。

tips: 你可以 push\color{red}{push} 时带上 −f\color{red}{-f} 参数,强制掩盖长途 commithistory\color{red}{commit \ history},你这样做估计会被打,由于掩盖之后,团队的其他人的本地 commithistory\color{red}{commit \ history} 就与长途的不一样了,都无法推送了。

因而,请确保仅仅对自己私有的提交单进行 rebase\color{red}{rebase} 操作,关于现已兼并进长途库房的前史提交单,不要运用 rebase\color{red}{rebase} 操作兼并 commit\color{red}{commit} 单。