世界上最快的捷径,就是脚踏实地,本文已收录【 架构技术专栏】关注这个喜欢分享的地方。
使用git参与多人之间的合做开发大概有三年的时间,大多数场景下使用的git命令一只手多一点就能数的过来git
理论上来讲,只要能合理管理项目分支,这几个命令已经足以应付全部的平常开发工做。可是若是咱们偶尔看一下本身的git graph,个人天呐,为何会这么乱。vim
鉴于分支管理的混乱(或者根本就没有进行过度支管理),咱们常常遇到一些意想不到的问题,所以须要使用不少面生的git命令来解决咱们的问题,好比说本文讲到的git rebase。架构
Git rebase 的中文名是变基,就是改变一次提交记录的base。在这一环节,咱们不妨带着这样一个假设:git rebase ≈ git merge,并用两种命令实现同一工做流来对比他们之间的异同。fetch
回想咱们平常的工做流,假设a和b两人合做开发,三个分支:develop, develop_a, develop_b。两我的分别在develop_a和develop_b分支上进行平常开发,阶段性地合入到develop。ui
那么从a的角度来看,可能的工做流是这样的:spa
(1)我的在develop_a分支上开发本身的功能code
(2)在这期间其余人可能不断向develop合入新特性blog
(3)我的功能开发完毕后经过merge 的方式合入别人开发的功能开发
<img src="https://imgkr2.cn-bj.ufileos.com/8cc6cb08-2204-41f3-81fd-7ed6fdfe93c4.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=m4aOEBDAYY81ui7sIjaOojyXJro%253D&Expires=1604394415" alt="img" style="zoom:50%;" />rem
上图为平常merge 工做流,对应的git操做命令以下:
git checkout develop_a // 本地功能开发... git pull origin develop = git fetch origin develop + git merge develop复制代码
一样走完这样一个工做流若是咱们使用git rebase来实现,结果以下:
git rebase 以前,如图:
<img src="https://imgkr2.cn-bj.ufileos.com/b91971db-ef92-42b1-98d9-c06bd36bc3c6.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=JwrW9r03NwUSfrGx1COB7atRCqI%253D&Expires=1604394434" alt="img" style="zoom:50%;" />
git rebase 之中,如图:
<img src="https://imgkr2.cn-bj.ufileos.com/cb7eb279-95f0-4218-8e15-0ece04b1613f.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=nQx3CttQG6lmgb6qDWdNfRslDxc%253D&Expires=1604394450" alt="img" style="zoom:50%;" />
git rebase 以后,如图:
<img src="https://imgkr2.cn-bj.ufileos.com/59051a0d-342d-4822-bac3-47ebb2e68705.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=w1hLSzuKVFjY71xauONfva%252F4qDg%253D&Expires=1604394465" alt="img" style="zoom:50%;" />
git rebase 操做对应命令以下:
git checkout develop_a // 本地功能开发... git fetch origin develop git rebase develop git checkout develop git merge develop_a git br -d develop_a 复制代码
因而可知,git rebase 和git merge的异同之处以下:
(1)二者均可以用于本地代码合并
(2)git merge 保留真实的用户提交记录,且在merge时会生成一个新的提交
(3)git rebase 会改写历史提交记录,这里的改写不只限于树的结构,树上的节点的commit id也会别改写,所以图3和图4用e'表明图2的e',收益是能够保证提交记录很是清爽
git rebase -i,中文名叫交互式变基。意思就是在变基的过程当中是能够掺入用户交互的,经过交互过程咱们能够主动改写历史提交记录,包括修改、合并和删除等。咱们以上面使用rebase后获得的提交记录为例,来进行历史提交记录的修改,在修改以前,提交记录是这个样子的。
使用git rebase -i 修改历史提交的过程主要包含三步:
(1)列出一个提交记录的范围,并指出你在这个范围内须要对哪些记录进行什么样的修改
(2)以次执行上述的修改,若是遇到冲突须要解决
(3)完成rebase 操做
以上面截图中的提交记录为例,来对历史提交的commit msg进行修改,操做步骤以下:
// 查看最近6次提交记录,选择对哪一条记录进行修改 git rebase -i HEAD~6复制代码
执行完上述命令后,会以vim的方式打开一个文件,文件中显示了最近6次的提交信息,从上到下,由远到近。
从下面的注释能够看到,咱们分别把每一行前面的pick修改为r, s, d的方式就能够实现对历史记录的修改,合并和删除。
首先咱们尝试修改提交信息,把第二行前面的pick改为r,保存退出。当前页面关闭的同时会打开一个新的页面,让你对选中的提交信息进行编辑。
编辑完信息以后保存退出,就完成了对历史提交记录的修改。经过观察下图能够发现,develop_a的提交记录中的commit msg 仍然是feat_c,可是develop 分支中对应的提交记录,commit msg 已经变成了feat: c-update.。
这里须要留意到的一个现象是develop 和develop_a 分支上相同提交的commit id 已经发生了变化,这个在后面会再次提到。
除了修改提交的commit msg 以外,咱们也能够经过把pick 改成e,结合git reset --soft HEAD^ 的方式对档次提交的改动内容进行修改。
合并与删除历史提交的操做步骤与编辑相似,只须要把pick分别改成s 和d 便可,各位看官能够自行尝试。若是在rebase的过程当中遇到了冲突,须要手工解决,而后使用git rebase --continue 完成rebase 操做。
git rebase 的提示仍是很是友好的,它会告诉你须要进行哪些操做解决当前的问题。
从修改历史提交记录这个功能来看,交互式变基是一个很是强大的功能。可是使用这个功能必需要遵循一个铁则:不要对线上分支的提交记录进行变基!
引用git 官方指导文档的话来讲大概是这样:
若是你遵循这条金科玉律,就不会出差错。 不然,人民群众会仇恨你,你的朋友和家人也会嘲笑你,唾弃你。
在说为何不能对线上提交执行交互式变基以前,先说一下若是要对线上功能执行这个操做要怎么作。
首先,你须要在本身本地变基成功,而后使用git push -f 强行push 并覆盖远程对应分支,之因此须要执行覆盖式push 是由于若是你不覆盖,当前变基事后产生的新提交会与远程合并,致使你在本地的变基行为失去意义。
由于咱们上面提到过,从变基那个节点开始日后的全部节点的commit id 都会发生变化。
一样的缘由,即便你使用git push -f 使远程分支发生了变基,若是你的同事的开发分支中还存在你执行变基操做(不管是修改、合并仍是删除)时针对的那些分支,那么当你的同事merge 你的提交以后,你全部想使用变基改变的东西都回来了!
此处咱们尝试经过要点描述的方式,说明线上提交执行变基会致使什么结果以及如何避免这个结果:
(1)你在本地对部分线上提交进行了变基,这部分提交咱们称之为a,a在变基以后commit id 发生了变化
(2)你在本地改变的这些提交有可能存在于你的同事的开发分支中,咱们称之为b,他们与a的内容相同,commit id 不一样
(3)若是你把变基结果强行push 到远程仓库后,你的同事在本地执行git pull 的时候会致使a 和b 发生融合,且都出如今了历史提交中,致使你的变基行为无效
(4)咱们想要的是你的同事拉取线上代码时跳过对a 和b 的合并,只是把他本地分支上新增的修改合并进来
讲了这么多,最终的结论就是,使用变基解决变基带来的问题。即你的同事使用git rebase 的方式把他本地的修改rebase 到远程你执行过rebase 的分支上。
简言之,就是你的同事使用git pull --rebase 而不是git pull 来拉取远程分支。在这个操做的过程当中,git 会对咱们上面提到几个要点的信息进行检查并把真正属于同事本地的修改合入远程分支的最后。
文字描述可能有些乏力,更多详细信息能够参考这里:git-scm.com/book/zh/v2/…
鉴于上面描述的git rebase 可能带来的问题,最后要回答的一个问题是咱们应该如何在平常工做中使用git rebase,一样借用git 官方文档中的一句话:
总的原则是,只对还没有推送或分享给别人的本地修改执行变基操做清理历史, 从不对已推送至别处的提交执行变基操做,这样,你才能享受到两种方式(rebase 和merge)带来的便利。
原文地址:https://www.mdeditor.tw/pl/pMHD
做者:DevUI 华为团队