idea 实现git rebase操作详解

idea 实现git rebase操作详解

  • 1. git rebase介绍
  • 2. git rebase应用
    • 2.1、 同一分支的rebase操作
    • 2.2、分支跟master之间的rebase操作
    • 2.3、不同分支之间的rebase操作
      • 2.3.1、 同基线不同分支的rebase操作
      • 2.3.2、不同基线不同分支的rebase操作
    • 2.4、总结

本文结合idea工具进行rebase的各种场景的操作,借助工具更能直观地观察到分支之间地操作差异,方便我们理解rebase的各种操作以及场景的使用。

1. git rebase介绍

rebase:翻译成中文是重新设定,在这里可以理解为重新设置基线,也可以这么理解,将当前分支重新设置起始点。
rebase会把你当前分支的 commit 放到最后面,将rebase后的目标分支的commit当作基点放在前面,通俗的说就是将目标分支的提交作为你当前分支的基点,所以叫变基。

2. git rebase应用

先准备好一个主基线:
idea 实现git rebase操作详解_第1张图片

在此基础上创建一个分支:名字为fenzhi_1,创建另一个分支,名字为fenzhi_2
idea 实现git rebase操作详解_第2张图片
idea 实现git rebase操作详解_第3张图片

最开始fenzhi_1和fenzhi_2以及master的基线是同一个。

2.1、 同一分支的rebase操作

当前分支为fenzhi_2,共有三个提交记录:
idea 实现git rebase操作详解_第4张图片

在第一次修改上进行右击鼠标:选择图中的选项,翻译一下就是在此处进行交互式改变基址。
交互式可以理解为可自定义的选择不同rebase行为进行操作。
idea 实现git rebase操作详解_第5张图片

可以看到下面的界面,我们讲解一下:红色部分是操作栏,绿色部分是显示的提交记录,黄色部分是显示选择提交记录的详情信息,黑色部分就是执行rebase操作或者取消
idea 实现git rebase操作详解_第6张图片

着重讲解红色部分:
Rebase的行为可以大致分为三类:
第一类:保留commit,不合并
1、pick: 标记为pick的commit会在rebase操作后会直接保留下来,不做任何改动,也不会合并,最上面的commit最好标记为这一类
2、reword: 这一类commit也会保存下来,不过在保存下来之前会有一次修改commit message的机会
3、edit:这一类的commit也会直接保存下来,不过,当合并到这种类型的commit时,整个合并经常会暂停下来,你可以重新修改这次commit中的变动内容,比如给这个commit继续新增一些代码改动、或者修改commit message,然后git add(不要忘记 git add了), 再继续使用git rebase —continue,来继续rebase操作。
第二类:不保留commit,与上一次commit合并
1、squash:标记为squash的commit在rebase操作完成后不会保留,它会与之相邻的上一次commit进行合并。同时它的commit message也会与上一次commit的message合并。
2、fixup: 这类commit不会保留,会直接与相邻的上一次commit合并,与squash不同之处在于,它的commit message回直接丢弃,即这次commit会被视为对前一次commit的一次小的补充修改(fixup),commit message就以前一次为准
第三类:不保留,直接删除commit
1、drop:标记为skip的commit会直接被删除,就相当于这次commit从来没有发生过。同时,这个commit中涉及的所有代码修改全部会被删除。

值得注意的是:
不能全部选择 drop commit,不然就没有需要改变的了
squash 和 fixup 不能在第一个commit,因为他们需要与前一个commit配合

A、红色的部分就是对提交记录的操作,左边的上下箭头可以改变提交记录的顺序:
操作一下,选中第一次修改记录然后点击下箭头:如图所示可以第一次记录跟第二次记录的顺序发生了变化
idea 实现git rebase操作详解_第7张图片

执行rebase结果看一下:可以看到第一次提交记录已经在第二次修改上面了。(若其中有对同一个文件修改时,会出现冲突并处理完后,将同个文件所有的提交记录折成一个)所以可以看出rebase操作其实也是有风险的,容易把别人的提交记录删除掉,在解决冲突时也就会出现替换别人的改动。
idea 实现git rebase操作详解_第8张图片

B、第三个按钮它显示的提示是pick,其实它是对每个提交记录的所有的操作恢复到最初的配置,记住不是所有提交记录的操作回退,其实最初的操作就是默认pick。
C、第四个是stop to edit,指的是不修改提交信息,点击后:还是在第一次修改记录中点击这个按钮,可以看到左边显示了按钮。但双击鼠标后可以解除此操作;
idea 实现git rebase操作详解_第9张图片

若修改第一次修改记录,再点击这个按钮呢:
idea 实现git rebase操作详解_第10张图片

可以看到记录给恢复原初的信息。
idea 实现git rebase操作详解_第11张图片

D、reword:通俗的说就是修改提交信息
E、Squash和Fixup是一组的,squash的操作会合并俩个提交的信息:如图操作,也可以在选择第二次操作后点上面的按钮也可以的,这里是方便展示进行的操作,点击后我们看下结果:
idea 实现git rebase操作详解_第12张图片

可以看到第二次提交记录合并到了第一次提交记录上
idea 实现git rebase操作详解_第13张图片

执行结果看一下:
idea 实现git rebase操作详解_第14张图片

要是点击Fixup呢:可以看到若第二次合并到第一次后,提交记录沿用第一次的提交记录。
idea 实现git rebase操作详解_第15张图片

执行结果看一下:
Rebase之前:可以看到俩次的提交记录
在这里插入图片描述
在这里插入图片描述

Rebase之后,可以看到提交记录合并到了一起。
在这里插入图片描述

F、drop:可以理解为丢弃,就是将删除当前提交的所有修改。将所有修改恢复到修改之前的样子,并且删除此次提交记录。
idea 实现git rebase操作详解_第16张图片

执行结果看一下:可以看到直接删除了第二次的所有改动记录,也可以理解为回退了第二次的所有操作。
idea 实现git rebase操作详解_第17张图片

G、reset:这个操作就简单了,就是还原对所有commit的操作
rebase操作后,又该如何push呢
比如我们执行的是将第二次提交合并到第一次提交上:
在这里插入图片描述

可以看到有俩个操作提示:更新和推送。从操作来看,若rabase后不推送,执行的是更新就会是远程的最新记录替换本地的改变。但不能这么做,那rebase操作就白整了。我们得需要push
idea 实现git rebase操作详解_第18张图片

可以看到push有俩种选择:若直接选择的push,看下结果:
idea 实现git rebase操作详解_第19张图片

翻译一下:push的时候它认为你本地的变更与远程版本不一致
idea 实现git rebase操作详解_第20张图片

若选择rebase的话,就会发现恢复到rebase操作之前的记录
若选择merge的话,可以看到处理的结果,原先的2条提交信息还在,只是会新生成一个整合后的提交。
idea 实现git rebase操作详解_第21张图片

看下面的记录发现很奇怪。为啥第二次第三次提交成为了一个临时提交,然后第三次提交又成为了第一次提交后的版本,然后第二次提交成为了新的一个提交记录。
我们再次回到操作的时候:查看一下git的命令
idea 实现git rebase操作详解_第22张图片

可以看到第一次和第三次的行为是pick,而第二次的是fixup,所以进行push时选择的是merge时会出现上述的提交记录。
idea 实现git rebase操作详解_第23张图片

如果自己分支的几个提交都是本地的,还没有提交到远程分支fenzhi_2上,那么就可以直接push推到远程,但一般我们总要合自己代码到dev/test,所以必然是已经提交到自己远程分支上了, 此时当你去push你的commit时,会再次与你远程分支的commit合并,之前本地rebase的那些commit又会出现了。
若选择force push呢,翻译过来就是强制推送,看一下操作结果:有个提示,翻译一下就是:强制推送,可能会覆盖远程服务器的提交。
idea 实现git rebase操作详解_第24张图片

点击强制推送
idea 实现git rebase操作详解_第25张图片

可以看到这个结果是想要的,但是这个也有不同的情况:
若这个远程分支只有你一个人在开发:强制推送是可以的,没有人会在你rebase没完成时提代码,可以直接理解为用你本地分支的状态区覆盖掉远端origin分支的状态,也就是执行过后,本地的分支什么样,远端分支就什么样

2.2、分支跟master之间的rebase操作

Rebase的本意是改变基线,意思就是当从master拉取的分支1开发一段时间后,master也提交了几个版本,这就使得分支1的基线与现在的master不是同一个版本。需要将分支1的基线改成最新master。那就需要rebase操作了。看案例效果:
看一下fenzhi_2的基线是在提交id为1639f5db的基础上拉的分支,然后做了俩次变更
idea 实现git rebase操作详解_第26张图片

再看一下master的提交记录:master在 1639f5db上提交了一次变更。
在这里插入图片描述

这就造成了fenzhi_2的基线不是最新的master了,现在要将fenzhi_2的基线改为提交id为f7ec72e7,看下面操作
本地分支改为fenzhi_2:
idea 实现git rebase操作详解_第27张图片

在master上右击鼠标:第二步操作翻译一下就是在master基础上改变fenzhi_2的基线。
idea 实现git rebase操作详解_第28张图片

点击操作:若看到有冲突,手动处理一下即可,
idea 实现git rebase操作详解_第29张图片

可以看到同一个位置都有改动,这就根据实际情况合并代码了,这里我的目的是master的改动和本分支的改动都要保留。
idea 实现git rebase操作详解_第30张图片

解决完后,会自动弹出一个窗口:是提交信息的修改,这个也是根据实际情况定,这里我不改,点击继续rebase。
idea 实现git rebase操作详解_第31张图片

看结果:提交id为f7ec72e7的成为了fenzhi_2的基线。
在这里插入图片描述

我们再看一下上面解决冲突后的代码变更记录:
先看基线的变更是Test.java文件进行了变更
idea 实现git rebase操作详解_第32张图片
idea 实现git rebase操作详解_第33张图片

分支第一次提交id为a6330cc0的也修改了这个Test.java。那我们上面rebase后,本次变更就得在基线的基础上变更,那我们看看是不是
idea 实现git rebase操作详解_第34张图片

结果来看,是我们想要的。这个结果是上面解决冲突的结果。
idea 实现git rebase操作详解_第35张图片

接下来push:可以看到push有俩个操作,一个push一个是force push(强制推送)。
idea 实现git rebase操作详解_第36张图片

若分支是自己使用,那我们就强制推送。本地的分支提交记录覆盖远程的。
看一下远程仓库记录:
idea 实现git rebase操作详解_第37张图片

上面的操作是分支改变基线,那反过来操作呢,在master上rebase呢。
看一下分支fenzhi_3:这个分支做了俩次变更
idea 实现git rebase操作详解_第38张图片

Master也做了俩次变更
idea 实现git rebase操作详解_第39张图片

在master上进行rebase onto fenzhi_3:
idea 实现git rebase操作详解_第40张图片

可以看到有个提示:
idea 实现git rebase操作详解_第41张图片

idea 实现git rebase操作详解_第42张图片

大概意思就是会对master的提交记录进行修改,看下执行结果:
idea 实现git rebase操作详解_第43张图片

发现分支的提交记录在master记录之前,这个与merge操作是相反的。继续操作push
idea 实现git rebase操作详解_第44张图片

可以看到上面提示,若点击合并呢:可以看到分支的提交跟master在一条线上,但最上面又有一条合并记录。
idea 实现git rebase操作详解_第45张图片

若点击的是rebase呢:可以看到是将分支fenzhi_3的提交放在了最前面。这个操作就模拟了代码merge,但提交记录是一条线。这个才是我们的本意。
idea 实现git rebase操作详解_第46张图片

这个时候若继续将fenzhi_3 merge到master时只会产生一个合并记录:
idea 实现git rebase操作详解_第47张图片

2.3、不同分支之间的rebase操作

不同分支之间的rebase操作是一个分支合并另一个分支的变更。这种操作的应用场景是啥呢?看下面案例:
比如有个fenzhi_2和fenzhi_3
idea 实现git rebase操作详解_第48张图片

idea 实现git rebase操作详解_第49张图片

比如fenzhi_2开发的时候需要fenzhi_3的代码,并把fenzhi_3的提交信息合并到fenzhi_2上,后续代码都将在fenzhi_2上继续开发。那rebase操作就相当于使用了cherry-pick操作。但是fenzhi_2和fenzhi_3的基线不一致的话。就要考虑cherry-pick操作了,后面会通过案例详细说明。

2.3.1、 同基线不同分支的rebase操作

开始操作:
指定当前分支是fenzhi_2,在fenzhi_3上右击鼠标选择变基操作:
idea 实现git rebase操作详解_第50张图片

可以看到有代码冲突,说明在将fenzhi_3的提交变更一次依次合并到本分支的时候,遇到了fenzhi_2在同一文件的变更记录。这时候要慎重选择了。我这里需要保留俩个分支的变更。解决完冲突后,继续rebase即可

idea 实现git rebase操作详解_第51张图片
看下结果,可以看到,它是将fenzhi_3的变更记录放在了fenzhi_2的前面,这跟cherry-pick是不一样的。所以选择合并不同分支代码的时候就要想清楚了。
idea 实现git rebase操作详解_第52张图片
推送代码即可:这里是强制推送。这里前提是必须保证fenzhi_2的最新提交记录与远程仓库一样的,若不确定的话,还是不要进行强制推送了。
idea 实现git rebase操作详解_第53张图片

2.3.2、不同基线不同分支的rebase操作

看下分支fenzhi_1的基线是1639f5db,并提交俩次变更

在这里插入图片描述

看下分支fenzhi_2的基线是b269d2a0,提交一次变更。

在这里插入图片描述
从上面可以看到fenzhi_2的基线比fenzhi_1的基线高一个版本,这就会有俩种rebase情况,fenzhi_1 rebase onto fenzhi_2 或者 fenzhi_2 rebase onto fenzhi_1。
1、先看一下fenzhi_1 rebase onto fenzhi_2,操作步骤跟上面的一样,这里直接看结果:
idea 实现git rebase操作详解_第54张图片
看结果,这里不仅把fenzhi_2的提交合并,也会把master的新提交合并过来,这里很容易理解,因为rebase的操作就是从共同基线开始的。
2、看一下fenzhi_2 rebase onto fenzhi_1:可以看到有个提示
idea 实现git rebase操作详解_第55张图片
翻译下:
idea 实现git rebase操作详解_第56张图片
若继续rebase呢:看下结果,很明显fenzhi2_的基线就变了。
idea 实现git rebase操作详解_第57张图片

2.4、总结

Rebase操作可实现的功能有:
1、 同分支的多次提交合并、提交顺序改变,提交记录修改;
2、 修改下游分支的基线,同步上游的变更,将下游分支基线修改为最新;
3、 实现分支代码合并到主线上,类似于merge操作,但区别是提交路径的不同;
4、 实现不同分支之间的代码提交合并。
根据上面的操作就可以看到rebase的主要核心用途是下游分支与上游分支的基线同步、同分支的提交记录合并或者提交信息的修改。其他的操作只有特殊情况下才可以使用。

你可能感兴趣的:(git,java,git)