世界上最快的捷径,就是好高鹜远,本文已收录【架构技术专栏】关注这个喜爱分享的中央。
引言
应用git参加多人之间的合作开发大略有三年的工夫,大多数场景下应用的git命令一只手多一点就能数的过去
- git add
- git commit
- git push
- git merge
- git pull
- git log
实践上来说,只有能正当治理我的项目分支,这几个命令曾经足以应酬所有的日常开发工作。然而如果咱们偶然看一下本人的git graph,我的天呐,为什么会这么乱。
鉴于分支治理的凌乱(或者基本就没有进行过分支治理),咱们常常遇到一些意想不到的问题,因而须要应用很多面生的git命令来解决咱们的问题,比如说本文讲到的git rebase。
git rebase 和 git merge 区别
Git rebase 的中文名是变基,就是扭转一次提交记录的base。在这一环节,咱们无妨带着这样一个假如:git rebase ≈ git merge,并用两种命令实现同一工作流来比照他们之间的异同。
回忆咱们日常的工作流,假如a和b两人合作开发,三个分支:develop, develop_a, develop_b。两个人别离在develop_a和develop_b分支上进行日常开发,阶段性地合入到develop。
那么从a的角度来看,可能的工作流是这样的:
(1)集体在develop_a分支上开发本人的性能
(2)在这期间其他人可能一直向develop合入新个性
(3)集体性能开发结束后通过merge 的形式合入他人开发的性能
git 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%;" />
上图为日常merge 工作流,对应的git操作命令如下:
git checkout develop_a// 本地性能开发...git pull origin develop = git fetch origin develop + git merge develop复制代码
git rebase
同样走完这样一个工作流如果咱们应用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 developgit rebase developgit checkout developgit merge develop_agit 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 批改历史提交记录
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 rebase -i 必须遵循的规定是什么?
从批改历史提交记录这个性能来看,交互式变基是一个十分弱小的性能。然而应用这个性能必须要遵循一个铁则:不要对线上分支的提交记录进行变基!
援用git 官网领导文档的话来说大略是这样:
如果你遵循这条清规戒律,就不会出差错。 否则,人民大众会怨恨你,你的敌人和家人也会讥笑你,鄙弃你。
在说为什么不能对线上提交执行交互式变基之前,先说一下如果要对线上性能执行这个操作要怎么做。
首先,你须要在本人本地变基胜利,而后应用git push -f 强行push 并笼罩近程对应分支,之所以须要执行笼罩式push 是因为如果你不笼罩,以后变基过后产生的新提交会与近程合并,导致你在本地的变基行为失去意义。
因为咱们下面提到过,从变基那个节点开始往后的所有节点的commit id 都会发生变化。
同样的起因,即便你应用git push -f 使近程分支产生了变基,如果你的共事的开发分支中还存在你执行变基操作(不论是批改、合并还是删除)时针对的那些分支,那么当你的共事merge 你的提交之后,你所有想应用变基扭转的货色都回来了!
如果突破了git rebase -i 的应用规定应该如何补救
此处咱们尝试通过要点形容的形式,阐明线上提交执行变基会导致什么后果以及如何防止这个后果:
(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,同样借用git 官网文档中的一句话:
总的准则是,只对尚未推送或分享给他人的本地批改执行变基操作清理历史, 从不对已推送至别处的提交执行变基操作,这样,你能力享受到两种形式(rebase 和merge)带来的便当。
原文地址:https://www.mdeditor.tw/pl/pMHD
作者:DevUI 华为团队