git rebase的时候捅娄子了,怎么办?在线等……

摘要:
我的第一次灾难是使用gitrebase造成的。虽然最终解决了,但我还是很害怕。但是在我们重新设置push-f的基础之后,C5节点就不存在了。本质上,当我们重新设置基准时,我们会修改提交记录。不同的人对此有不同的看法。如果使用诸如rebase之类的操作进行篡改,则无法追溯以前的更改和版本。例如,当下游存在其他依赖项时,不能使用rebase。否则,几乎肯定会造成麻烦。

大家在使用git的过程当中有闯过祸吗?

我闯过,我闯的第一个祸就是使用git rebase造成的,虽然后来最终还是解决了,但是还是给我吓得不轻。当时的事情是这样的。

我们来看下这张图:

git rebase的时候捅娄子了,怎么办?在线等……第1张

简单解释一下这张图当中的内容,C1节点是所有分支的最小公共祖先。可以理解成是最早的master版本,之后我们checkout出来了两个分支,分别是bugFix和feature。其中feature是我们新开发的分支,而bugFix是修复bug的分支。

当我们把bugFix了之后就赶紧merge master发布了,当我们发布了之后发现bugFix当中有一点小问题。比如说把不应该提交的文件提交了上来,再加上我们不是用rebase的形式合并的,所以看起来commit记录有一点点乱。于是我决定使用rebase修复一下提交记录,搞完了之后使用git push -f强行更新了远程分支

因为我们之前已经push过了,想要用新的commit记录覆盖掉旧的就必须要使用-f强行推送。这些操作都是常规的操作,但是我无意之间犯了一个大问题,差点导致了后面的悲剧。

我先卖个关子,大家先用几秒钟时间想一下,这里藏着的问题是什么?

rebase的禁忌

这里藏着的问题就是feature分支,我们从图中可以看到feature分支是merge了C5节点的。但是当我们rebase push -f了之后,C5节点其实就不存在了。我们把图画出来给大家看一下就明白了,这个是rebase之前的依赖树:

git rebase的时候捅娄子了,怎么办?在线等……第2张

我们rebase之后依赖树变成了这样:

git rebase的时候捅娄子了,怎么办?在线等……第3张

由于feature之前曾经merge过master并且依赖了C5节点,而master在rebase强行push之后整个链路当中已经没有C5节点了。也就是说feature分支依赖了一个已经不存在的节点,这个时候还不算太遭,因为feature分支还没有更新,如果feature分支pull一下,那么整个分支会变成这样:

git rebase的时候捅娄子了,怎么办?在线等……第4张

也就是说同样的代码在feature分支当中保存了两个版本,并且如果feature合并进master之后,会发现之前push -f强行抛弃的那些提交又被合并了进来,并且整个commit的log会变得非常非常混乱,难以看懂。

如果这些分支都是自己的,那么自己捏了鼻子也就算了,如果这些分支是团队当中其他人的,那么捅个篓子基本上是避免不了的。如果组里有一个Git大佬知道这种情况该怎么解决还好,否则的话,想要完全复原非常困难,很有可能一通操作完全不知道偏差到哪里去了,也不知道如何找回来。

我当时还好,捅娄子的时候已经学过了这种情况应该怎么处理,虽然还是没能避免踩坑,但好在及时从坑里出来了。在我们来看脱坑的方法之前,先来思考一个问题,对于rebase造成混乱的根源究竟是什么,我们应该怎么避免?

解决rebase的只有rebase

为什么我们刚才在C8节点一旦pull就会导致本地的错乱呢?因为我们之前也介绍过,当我们执行pull的时候,其实是执行了git fetch和git merge两个步骤。所以相当于我们把master分支的改动又merge了一次,我们本地依赖了rebase之前的改动,这样一merge自然就把两个版本的改动merge在一起了。

要解决这个问题,我们就不能在C8节点的时候进行pull操作,因为pull操作包含merge,merge会导致错误。要解决这个问题其实也不难,我们可以rebase到master上。当我们执行rebase的时候,git会找出我们当前分支独有而master分支上没有的改动,将这些改动提取出来应用在master上得到一个新的结果。

git rebase的时候捅娄子了,怎么办?在线等……第5张

这样我们的记录当中就不会把C2和C5带进来了。

发散思考

我们贯通思考一下上面的过程,会得到一个什么结论?

其实结论很简单,就是rebase虽然很好用也很方便,但是它也有适用的条件,其中最大的条件就是如果还有其他分支依赖了当前分支,我们这时候不可以使用rebase,否则一定会引起错乱。

那引起错乱的原因又是什么呢?本质上是我们rebase的时候修改了commit的记录,关于这一点不同的人有不同的观点。有一派人认为git的提交记录是不可以篡改的,它存在的意义就是记录repo当中所有发生过的改动。如果使用rebase等操作进行了篡改,那么我们就不能很好地追溯之前的改动和版本了。还有一派人不这么看,他们觉得如果记录的改动非常混乱非常不方便使用者阅读,这时候使用一些方法对它进行修整就是非常有必要的事情。工具发明出来就是为了使用的。

这两派争论不休,不同的人有不同的看法,可以说是一个价值观问题也不为过。在这个问题上我个人更加偏向后者, 既然有这么好用的工具,自然应该使用的。使用不是滥用,我们需要遵守一定的规范,这样才能保证不会捅出篓子来。比如一定不可以在下游还有其他依赖的情况下使用rebase,否则几乎可以肯定是一定会捅娄子的。

今天的文章就到这里,衷心祝愿大家每天都有所收获。如果还喜欢今天的内容的话,请来一个三连支持吧~(点赞、关注、转发

原文链接,求个关注

本文使用 mdnice 排版

git rebase的时候捅娄子了,怎么办?在线等……第6张

免责声明:文章转载自《git rebase的时候捅娄子了,怎么办?在线等……》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇倍福TwinCAT(贝福Beckhoff)基础教程2.2 TwinCAT常见类型使用和转换_函数块音频信号质量的度量标准--MOS得分的由来下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

有相同键值的json合并为一个数组

今天我们分享的是,如何使用javascript来将两个含有相同键值的json合并为一个数组。 已知arr1的长度和arr2相等,arr1和arr2含有相同的键值id,使用js如何得到merge。 如下数据: var merge= [{id: 12,name: 20,title: 500}, {id: 13,name: 30,title: 666}]; 下面...

mac搭建git服务器

http://blog.csdn.net/kesalin/article/details/6943770 XCode 4 默认支持 Git 作为代码仓库,当我们新建一个仓库的时候,可以勾选创建默认仓库,只不过这个仓库是在本地的。本文介绍如何在 mac 机器上创建 Git 服务器,总体思路是:使用gitosis来简化创建过程,在用作服务器的机器上创建一个名为...

git解决代码提交冲突

树冲突文件名修改造成的冲突,称为树冲突。比如,A同事把文件改名为A.C,B同事把同一个文件改名为B.C,那么B同事将这两个commit合并时,会产生冲突。如果最终确定用B同事的文件名,那么解决办法如下:git rm A.Cgit rm origin-name.Cgit add B.Cgit commit如果最终确定用A同事的文件名,那么解决办法如下:git...

Git过滤文件和文夹

第一步:添加".gitignore"文件 往项目根目录添加一个文件".gitignore"。这文件和".git"文件夹同级。 但是在windows下无法创建".gitignore"文件名,必须把文件名改成这样".gitignore.", 在文件名最后加一个英文句号就可以了。 第二步:设置过滤条件 bin/过滤所有bin文件夹 obj/过滤所有obj文件夹...

Intellij IDEA如何配置Git?

01 打开IntelliJ IDEA。02 找到IntelliJ IDEA版本控制中Git, 在File–>Setting–>Version Control–>Git–>Path to Git executable。 03 在Git的安装路径下找到cmd文件夹下的git.exe,到此Git配置已完成。 04 检查Git在Inte...

安装go-admin

安装过程 1.下载源码(https://github.com/golangpkg/go-admin)后编译 执行编译命令 go build -ldflags "-linkmode external -extldflags -static" -o go-admin main.go 出现错误:main.go:5:2: cannot find package "...