这里的可读,主要指的是可以经过看git graph了解每一次版本更迭,每一次hotfix的修改记录.反映到分支上面,有两个要求:git
rebase翻译作变(re)基(base)
.安全
讲rebase的文章常常会引用三张图:数据结构
用来讲明git rebase和git merge的区别的时候确实是足够了,可是 git rabase的用途并不是是合并分支,它与merge根本不是一样的性质.(注意,这里的说法是并不是是
,不是并不是只是
,由于虽然有时rebase替代了merge的工做,但其原理和性质彻底不同.)fetch
rebase还有如下几种用处:翻译
git pull —-rebase
处理同一分支上的冲突(若是你能理解其实这是git fetch&&git rebase
两个操做,而且理解远程分支和本地分支的区分的话,那么其实他跟单纯的rebase用法没什么区别,可是由于其场景不同,因此单独拆分出来说)git rebase -i
修改commit记录实质上:code
当前分支
记录基于任何commit节点
(不限于当前分支上的节点)的变动.rebase的base
不能理解为分叉的基点,而是整个git库中存在的全部commit节点:cdn
git pull —-rebase
的时候,这个当前分支
是本地分支,commit节点
是远程分支的headgit rebase master
的时候,这个当前分支
是feature分支,commit
节点是master分支的headgit rebase -i
的时候,这个当前分支
就是当前工做分支,commit节点
是在 -i后注明的commit上面咱们已经说到了:对象
rebase
是对当前分支
记录基于任何commit节点
(不限于当前分支上的节点)的变动.blog
怎么作到呢?我没有深刻研究它真的是如何实现的,如下步骤必定是不对的,但足够让你理解rebase干了什么.工作流
咱们标注出了两个重点,当前分支
和commit节点
.
当前分支
branch-A从头至尾列出来,从数据结构的角度来讲这是一个链表commit节点
所在的分支branch-B从头至尾列出来,一样是一个链表rebase -i
来讲,还能够一次取多个节点或者按照不一样顺序取,你有更大的处理自由commit节点
以后 你能够把以前咱们说到的三种rebase用处套在以上步骤看看,是否可以理解.对,很危险.
不过就像小马过河同样,光听别人说是没用的,咱们须要明白为何有人说危险,有人说不危险.我看到不少文章说rebase有问题,但他们的说法其实并不让人信服,不少时候只是他们不会用.
不少人据说过一个golden rule,在文末有连接,可是不多有人会明白真正的缘由.让咱们一层层地剖析:
冲突扩散到了其余人身上
把别人fetch回去的改掉
,由于他们的工做就是基于fetch回去的分支开展的(往前推动是必须的,其实也修改了远程分支,因此才会merge产生冲突,可是这个冲突是没法避免的)-f
能够强推实际上不止rebase这样,任何修改远程分支历史的操做都会形成冲突,而且这个冲突须要全部人都解决一遍.
可是分析仍是太长了,记不住怎么办?
只须要记住-f
,只要你不使用-f
,那么就是安全的.
不过仅是安全,并不能保证优雅,若是要使git graph可读,那你还得多想一想:
咱们仍是说回以前提到的三个用法:
在把分支合并回master的时候,用git rebase master
代替git merge master
.(注意,只在合并以前使用,不然多人协做会遇到冲突)
这样的好处有两个:
Merge branch 'master' into hotfix/xxx
的节点上一次工做
和这一次工做的顺序更清晰,由于rebase会让此次feature的分叉节点改到上一次工做后.对于master分支来讲,咱们并不关心checkout新的feature的顺序,咱们更关心merge新的feature的顺序
.好比这里,使用merge master致使的紫色的分叉在提交以前与master多了一次链接,并且主线上在紫色分叉合并以前还经历了一次合并,这个时间顺序并不清晰.
那么在master分支上合并也用rebase吗?不是.由于咱们须要master上的分叉让咱们更明白master上的改变(因此使用-no-ff).实际上,无论你采用任何git flow模型,我都建议你对不过重要的分支合并采用rebase,对重要的分支合并采用merge.这样会让主干的更改更清晰,而分支不会扩散地太远.
多人在同一分支上工做的时候(包含master分支和多人合做的feature等分支),在git pull的时候会遇到冲突,git pull的默认行为是git fetch&git merge
,merge的对象是远程分支和本地分支.
它的好处基本上与上一条无异,还多了一条:
好比这里,原本左数第二条玫红色的才是主线,由于不规范地在master上直接提交了一次commit而且采用merge方式的pull作了合并致使主线被抬升到了外层.而此次不规范的commit却成了主线.
使用这条命令能够修改分支的记录,好比以为以前的commit修改内容不够单元化,像是修改了文案1为文案2
,修改了文案2为文案3
,这种记录对于master分支来讲是不必关注的信息,最好经过git commit --amend
或者rebase的方式修改掉.
不过并不推荐在提交以前手动作一次整个分支的squash,若是是rebase方式合并的话,也许更有意义.工蜂(腾讯内部的code平台)提供了merge request的标题和内容功能,因此不必作squash,彻底能够没必要太聚合,以便反应真实的信息.
为了避免影响别人,只用它修改未push的commit,或者若是一条分支只有一我的,你也能够修改已经push的commit.
对于这条命令的更多功能,能够再去查阅其余文章.
先说一个原则,看graph要先看主线,主线要清晰,再看分叉上信息,这与咱们的工做流程是一致的.
绿色的hotfix或者feature分支每次不是只容许提交一次commit,只是这一段都是一些小更改.
这看起来有点好笑,一点都不高级.说了这么多作了这么多难道只是为了获得这么简单的图?
没错,为了让东西变简单,原本就要付出不少代价
,咱们所作的就是要让东西变简单,好比努力工做是为了让赚钱变简单,努力提高是为了让工做变简单.让事情变复杂只会让事情不可控.
固然具体如何仍是要取决于你采用的git flow,可是原则很简单:
每一个分叉的子分叉尽可能是一个串联一个,内部尽可能不要再有本身的提交.
为何我认为这样的git graph可读性好,由于它把咱们的工做也拍平了,不在意每一个工做的开始时间和持续时间,只关心这个工做的完成时间.
假如一个项目需求1是1月1号启动,2月1号上线,需求2是1月20号启动,2月10号上线.1月10号修了一个bug,2月3号修了一个bug. 听起来是否是很绕?
若是你的git graph显示的也是这样的信息,可读性必定很差,因此咱们要作的git graph应该反应的是以下信息:
(这里并不讨论rebase可能带来的冲突问题,有不少文章都会讲,上面也已经提到了rebase的危险性,这里只讨论rebase对于git graph的缺点.实际上,冲突只是rebase不恰当使用致使的问题,而非rebase自己的问题.)
固然也有人会说,工做的开始时间也很重要呀,由于它反映了当时工做开展的基础条件.对,这是rebase master的弊端.他让记录清晰,也让记录丢失了一些信息.记录的加工让可读性变得更好,也让信息量变少了.
git rebase 让git graph发生了变化,每次分叉的检出和并入之间不会再有任何节点
.(由于合并到master采起的是merge行为.不然根本没有分叉)
也就是这种状况不会再出现.由于每次老是rebase master
,把本身的起点抬了上去.git rebase实际上让检出信息没有意义,换取了主分支分叉的清晰.
若是rebase没有缺点,那么也就没有争议.是否使用rebase也要看真实的需求是什么.
经过rebase让git graph更可读.目的和原则咱们都已经说过了,不必再从新说一遍.
多有谬误之处,还望不吝赐教!