共计 4246 个字符,预计需要花费 11 分钟才能阅读完成。
世界上最快的捷径,就是好高鹜远,本文已收录【架构技术专栏】关注这个喜爱分享的中央。
引言
应用 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 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 批改历史提交记录
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 华为团队