前言
笔者最近在主导一个项目的架构迁移作业,因为迁移项目的前史包袱较重,人员合作较多,在迁移过程中免不了进行多分支、屡次commit的状况,时刻一长,git的提交记载便紊乱不胜,随便截一个图形化的git提交前史给咱们感受一下。
各种分支张狂打架宛如后宫争宠的妃子们,之所以会呈现这种状况,首要仍是因为乱用git merge指令并且不考虑后续的了解本钱导致的。如今在大厂作业的程序员们,频频接受改变的需求,一旦一开始考虑不周到,就必定会呈现了大量无含义的commit log,加上“敏捷”理念的推行,产品的快速迭代上线变成了核心指标,这些无含义的commit log便被“下次再处理”,久而久之就紊乱不胜了。
而咱们在看一些开源库房时,会发现他们的commit记载非常整齐,其实这并不是社区的程序员才干更强,而是因为他们没有KPI大棒的鞭挞,在提交代码前会花时刻收拾自己的commit log。而这便是本文的主角了——“Git Rebase”。
git rebase和git merge
git rebase,中文翻译为“变基”,一般用于分支兼并。已然提到了分支兼并,那就必定离不开git merge
这个指令。
相信每个新手程序员刚进入职场的时分,都会听到“xxx你把这个分支merge一下”这样的话。那么问题来了,假如你有6个程序员一起作业, 你就会有6个程序员的分支, 假如你运用merge, 你的代码前史树就会有六个branch跟这个主的branch交错在一起。
上图是 git merge
操作的流程示意图,Merge指令会保存一切commit的前史时刻。每个人对代码的提交是林林总总的。虽然这些时刻关于程序本身并没有任何含义。可是merge的指令初衷便是为了保存这些时刻不被修正。于是也就构成了以merge时刻为基准的网状前史结构。每个分支上都会继续保存各自的代码记载,主分支上只保存merge的前史记载。子分支随时都有可能被删去。子分子删去以后,你能够看到的记载也便是,merge某branch到某branch上了。这个前史记载描绘基本上是没有含义的。
而 git rebase
中文翻译为“变基”,变得这个基指的是基准。怎么了解这个基准呢?咱们看一下下图。
咱们能够看到经过变基后的feature分支的基准分支发生了变化,变成了最新的master。这便是所谓的“变基”。
经过上面的两张图能够很明显的发现,这两种兼并分支的方法最大的区别在于,merge后的分支,会保存两个分支的操作记载,这在git commit log 树中会以穿插的方式保存。而rebase后的分支会根据最新的master分支,从而不会构成分叉,自始至终都是一条干净的直线。
关于
git rebase
和git merge
的具体用法不在本文的介绍范围内,概况能够参考互联网上的其他材料。
在变基过程中,咱们一般需求进行commit的修正,而这也为咱们收拾git记载提供了一个可选计划。
坚持最近的几条记载整齐
假定咱们有一个库房,我在这个库房里履行了4次提交,经过 git reflog
指令检查提交记载如下。
假如咱们想将Commit-3、Commit-2和Commit-1的提交兼并成一次提交(假定某次提交至改了一些pom文件),咱们能够直接履行下面的指令
git rebase -i HEAD~3
-i
指的是 --interactive
,HEAD~3
指的是最近三次commit。
当然咱们也能够直接指定最新的一个想保存的 Commit的ID,在上面的比如中便是Commit-0的ID,因而咱们也能够写成
git rebase -i d2b9b78
履行该指令后,咱们会进入到这么如下一个界面:
这个界面是一个Vim界面,咱们能够在这个界面中检查、修正改变记载。有关Vim的操作,能够看我之前写的文章和录制的视频《和Vim的初次见面》
在看前三行之前,咱们先来看一下第5行的指令加深一下咱们对git rebase
的认识。
翻译过来便是,将d2b9b78..0e65e22
这几个分支变基到d2b9b78
这个分支,也便是将Commit-3/2/1/0
这几次改变兼并到Commit-0
上。
回到前面三行,这三行表示的是咱们需求操作的三个 Commit,每行最前面的是对该 Commit 操作的 Command。而每个指令指的是什么,指令行里都现已具体的告知咱们了。
-
pick
:运用该commit -
squash
:运用该 Commit,但会被兼并到前一个 Commit 当中 -
fixup
:就像squash
那样,但会扔掉这个 Commit 的 Commit message
因而咱们能够直接改成下面这样
这儿运用fixup,而不是squash的首要原因是squash会让你再输入一遍commit的log,图省劲的话,能够无脑选择fixup形式。
然后履行:wq
退出vim修正器,咱们能够看到控制台现已输出Successful了。
这个时分咱们再来看下log 记载,履行git log --oneline
于是最近三次的提交记载就被兼并成一条提交记载了。
坚持中心某些记载整齐
那假如不是最终的几个commit兼并,而是中心连续的几个Commit记载,能够用上述方法收拾兼并吗?答案是能够的,只不过需求留意一下。
咱们从头创立一个新的库房
假如这次咱们想将”third commit”和”second commit”兼并为一个提交,其实和上面的方法相同,咱们只需履行git rebase -i HEAD~3
,然后将中心的提交改成fixup/squash
形式即可,如下图所示:
之所以是HEAD~3,是因为咱们要做的改变是根据first commit做的,因而咱们也能够写成
git rebase -i a1f3929
咱们来看下更改完的commit log,如下图所示:
是不是就干掉了third commit了。
三行代码让git提交记载坚持整齐
上面咱们都是在本地的git库房中进行的commit记载收拾,可是在实践的开发过程中,咱们基本上都是写完就直接push到长途库房了,那应该怎么让长途的开发分支也坚持记载的整齐呢?
第一种做法是在push代码前就做在本地收拾好自己的代码,可是这种做法并不适用于那种本地无法布置,需求布置到长途环境才干调试的场景。
这时咱们只需求履行git push -f
指令,将自己的修正同步到长途分支即可。
-f
是force强制的意思,之所以要强制推送是因为本地分支的改变和长途分支呈现了分歧,需求用本地的改变覆盖长途的。
而长途分支更新后,假如其他人也在这条分支上更改的话,还需求履行一个git pull
指令来同步长途分支。
这儿咱们来总结下让git提交记载坚持整齐的三行代码。
git rebase -i xxx
git push -f
git pull
❗️❗️❗️Tips:因为rebase和push -f是有些风险的操作,因而只建议在自己的分支上履行哦。