你根本不懂rebase-使用rebase打造可读的git graph

栏目: 编程工具 · 发布时间: 5年前

内容简介:这里的可读,主要指的是能够通过看git graph了解每一次版本更迭,每一次hotfix的修改记录.反映到分支上面,有两个要求:rebase翻译做讲rebase的文章经常会引用三张图:

这里的可读,主要指的是能够通过看git graph了解每一次版本更迭,每一次hotfix的修改记录.反映到分支上面,有两个要求:

  • 每个分支的历史修改可读(单个分支的层面)
  • 每个分支的分叉合并可读(多个分支的层面)

rebase是什么,它是更优雅的merge吗?

rebase翻译做 变(re)基(base) .

讲rebase的文章经常会引用三张图:

你根本不懂rebase-使用rebase打造可读的git graph

原本的两个分支

你根本不懂rebase-使用rebase打造可读的git graph

通过merge的结果

你根本不懂rebase-使用rebase打造可读的git graph

通过rebase的结果

用来说明git rebase和git merge的区别的时候确实是足够了,但是 git rabase的用途并非是合并分支,它与merge根本不是同样的性质.(注意,这里的说法是 并非是 ,不是 并非只是 ,因为虽然有时rebase替代了merge的工作,但其原理和性质完全不一样.)

rebase还有以下几种用处:

  • git pull —-rebase 处理同一分支上的冲突(如果你能理解其实这是 git fetch&&git rebase 两个操作,并且理解远程分支和本地分支的区分的话,那么其实他跟单纯的rebase用法没什么区别,但是因为其场景不一样,所以单独拆分出来讲)
  • git rebase -i 修改commit记录

实质上:

  • merge是对目前分叉的两条分支的合并
  • rebase是对 当前分支 记录基于任何 commit节点 (不限于当前分支上的节点)的变更.

rebase的 base 不能理解为分叉的基点,而是整个git库中存在的所有commit节点:

  • git pull —-rebase 的时候,这个 当前分支 是本地分支, commit节点 是远程分支的head
  • git rebase master 的时候,这个 当前分支 是feature分支, commit 节点是master分支的head
  • git rebase -i 的时候,这个 当前分支 就是当前工作分支, commit节点 是在 -i后注明的commit

rebase是怎么工作的?

上面我们已经说到了:

rebase 是对 当前分支 记录基于任何 commit节点 (不限于当前分支上的节点)的变更.

怎么做到呢?我没有深入研究它真的是如何实现的,以下步骤一定是不对的,但足够让你理解rebase干了什么.

我们标注出了两个重点, 当前分支commit节点 .

当前分支
commit节点
rebase -i
commit节点

rebase很危险对吗?

对,很危险.

不过就像小马过河一样,光听别人说是没用的,我们需要明白为什么有人说危险,有人说不危险.我看到很多文章说rebase有问题,但他们的说法其实并不让人信服,很多时候只是他们不会用.

很多人听说过一个golden rule,在文末有链接,但是很少有人会明白真正的原因.让我们一层层地剖析:

冲突扩散到了其他人身上
把别人fetch回去的改掉
-f

实际上不止rebase这样,任何修改远程分支历史的操作都会造成冲突,并且这个冲突需要所有人都解决一遍.

但是分析还是太长了,记不住怎么办?

只需要记住 -f ,只要你不使用 -f ,那么就是安全的.

不过仅是安全,并不能保证优雅,如果要使git graph可读,那你还得多想想:

  • 怎么让自己的commit历史清晰(每个commit反应了一个单位的工作,前后顺序合理)
  • 怎么让每次hotfix和feature所做的工作和顺序清晰

rebase如何让git graph可读?

我们还是说回之前提到的三个用法:

git rebase master

在把分支合并回master的时候,用 git rebase master 代替 git merge master .(注意,只在合并之前使用,否则多人协作会遇到冲突)

这样的好处有两个:

  • log里不会出现一个 Merge branch 'master' into hotfix/xxx 的节点
  • master分支上在这次merge之前已经被提交的 上一次工作 和这一次工作的顺序更清晰,因为rebase会让这次feature的分叉节点改到上一次工作后.对于master分支来说,我们并不关心checkout新的feature的顺序,我们 更关心merge新的feature的顺序 .
你根本不懂rebase-使用rebase打造可读的git graph

比如这里,使用merge master导致的紫色的分叉在提交之前与master多了一次连接,而且主线上在紫色分叉合并之前还经历了一次合并,这个时间顺序并不清晰.

那么在master分支上合并也用rebase吗?不是.因为我们需要master上的分叉让我们更明白master上的改变(所以使用-no-ff).实际上,不管你采用任何git flow模型,我都建议你对不太重要的分支合并采用rebase,对重要的分支合并采用merge.这样会让主干的更改更清晰,而分支不会扩散地太远.

git pull —-rebase

多人在同一分支上工作的时候(包含master分支和多人合作的feature等分支),在git pull的时候会遇到冲突,git pull的默认行为是 git fetch&git merge ,merge的对象是远程分支和本地分支.

它的好处基本上与上一条无异,还多了一条:

  • 使用merge行为的pull会将其他人的工作作为外来的分叉,从而在graph上产生一个新的分叉, 并且其他人这一段时间所做的所有的工作都会在graph上被抬升出去,如果这段时间其他人做的工作很多,graph的主线会变得丧失了主线的意义(因为它太单薄了,很多工作根本没反应上来).
你根本不懂rebase-使用rebase打造可读的git graph

比如这里,本来左数第二条玫红色的才是主线,因为不规范地在master上直接提交了一次commit并且采用merge方式的pull做了合并导致主线被抬升到了外层.而这次不规范的commit却成了主线.

git rebase -i

使用这条命令可以修改分支的记录,比如觉得之前的commit修改内容不够单元化,像是 修改了文案1为文案2 , 修改了文案2为文案3 ,这种记录对于master分支来说是没必要关注的信息,最好通过 git commit --amend 或者rebase的方式修改掉.

不过并不推荐在提交之前手动做一次整个分支的squash,如果是rebase方式合并的话,也许更有意义.工蜂(腾讯内部的code平台)提供了merge request的标题和内容功能,所以没必要做squash,完全可以不必太聚合,以便反应真实的信息.

为了不影响别人,只用它修改未push的commit,或者如果一条分支只有一个人,你也可以修改已经push的commit.

对于这条命令的更多功能,可以再去查阅其他文章.

可读的graph应该长什么样?

先说一个原则,看graph要先看主线,主线要清晰,再看分叉上信息,这与我们的工作流程是一致的.

你根本不懂rebase-使用rebase打造可读的git 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应该反应的是如下信息:

  • 1月10号修补bug
  • 2月1号上线需求1
  • 2月3号修补bug
  • 2月10号上线需求2

rebase的缺点是什么?

(这里并不讨论rebase可能带来的冲突问题,有很多文章都会讲,上面也已经提到了rebase的危险性,这里只讨论rebase对于git graph的缺点.实际上,冲突只是rebase不恰当使用导致的问题,而非rebase本身的问题.)

当然也有人会说,工作的开始时间也很重要呀,因为它反映了当时工作开展的基础条件.对,这是rebase master的弊端.他让记录清晰,也让记录丢失了一些信息.记录的加工让可读性变得更好,也让信息量变少了.

git rebase 让git graph发生了变化, 每次分叉的检出和并入之间不会再有任何节点 .(因为合并到master采取的是merge行为.否则根本没有分叉)

你根本不懂rebase-使用rebase打造可读的git graph

也就是这种情况不会再出现.因为每次总是 rebase master ,把自己的起点抬了上去. git rebase实际上让检出信息没有意义,换取了主分支分叉的清晰.

如果rebase没有缺点,那么也就没有争议.是否使用rebase也要看真实的需求是什么.


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Understanding Computation

Understanding Computation

Tom Stuart / O'Reilly Media / 2013-6-3 / USD 39.99

Finally, you can learn computation theory and programming language design in an engaging, practical way. Understanding Computation explains theoretical computer science in a context you'll recognize, ......一起来看看 《Understanding Computation》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器