java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > idea  git rebase操作

idea 实现git rebase操作应用场景

作者:我是流浪者

本文结合idea工具进行rebase的各种场景的操作,借助工具更能直观地观察到分支之间地操作差异,方便我们理解rebase的各种操作以及场景的使用,对idea  git rebase操作知识感兴趣的朋友一起看看吧

idea 实现git rebase操作详解

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

1. git rebase介绍

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

2. git rebase应用

先准备好一个主基线:

在此基础上创建一个分支:名字为fenzhi_1,创建另一个分支,名字为fenzhi_2

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

2.1、 同一分支的rebase操作

当前分支为fenzhi_2,共有三个提交记录:

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

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

着重讲解红色部分:
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、红色的部分就是对提交记录的操作,左边的上下箭头可以改变提交记录的顺序:
操作一下,选中第一次修改记录然后点击下箭头:如图所示可以第一次记录跟第二次记录的顺序发生了变化

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

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

若修改第一次修改记录,再点击这个按钮呢:

可以看到记录给恢复原初的信息。

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

可以看到第二次提交记录合并到了第一次提交记录上

执行结果看一下:

要是点击Fixup呢:可以看到若第二次合并到第一次后,提交记录沿用第一次的提交记录。

执行结果看一下:
Rebase之前:可以看到俩次的提交记录
 

Rebase之后,可以看到提交记录合并到了一起。

F、drop:可以理解为丢弃,就是将删除当前提交的所有修改。将所有修改恢复到修改之前的样子,并且删除此次提交记录。

执行结果看一下:可以看到直接删除了第二次的所有改动记录,也可以理解为回退了第二次的所有操作。

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

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

可以看到push有俩种选择:若直接选择的push,看下结果:

翻译一下:push的时候它认为你本地的变更与远程版本不一致

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

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

可以看到第一次和第三次的行为是pick,而第二次的是fixup,所以进行push时选择的是merge时会出现上述的提交记录。

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

点击强制推送

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

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

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

再看一下master的提交记录:master在 1639f5db上提交了一次变更。

这就造成了fenzhi_2的基线不是最新的master了,现在要将fenzhi_2的基线改为提交id为f7ec72e7,看下面操作
本地分支改为fenzhi_2:

在master上右击鼠标:第二步操作翻译一下就是在master基础上改变fenzhi_2的基线。

点击操作:若看到有冲突,手动处理一下即可,

可以看到同一个位置都有改动,这就根据实际情况合并代码了,这里我的目的是master的改动和本分支的改动都要保留。

解决完后,会自动弹出一个窗口:是提交信息的修改,这个也是根据实际情况定,这里我不改,点击继续rebase。

看结果:提交id为f7ec72e7的成为了fenzhi_2的基线。

我们再看一下上面解决冲突后的代码变更记录:
先看基线的变更是Test.java文件进行了变更

分支第一次提交id为a6330cc0的也修改了这个Test.java。那我们上面rebase后,本次变更就得在基线的基础上变更,那我们看看是不是

结果来看,是我们想要的。这个结果是上面解决冲突的结果。

接下来push:可以看到push有俩个操作,一个push一个是force push(强制推送)。

若分支是自己使用,那我们就强制推送。本地的分支提交记录覆盖远程的。
看一下远程仓库记录:

上面的操作是分支改变基线,那反过来操作呢,在master上rebase呢。
看一下分支fenzhi_3:这个分支做了俩次变更

Master也做了俩次变更

在master上进行rebase onto fenzhi_3:

可以看到有个提示:

大概意思就是会对master的提交记录进行修改,看下执行结果:

发现分支的提交记录在master记录之前,这个与merge操作是相反的。继续操作push

可以看到上面提示,若点击合并呢:可以看到分支的提交跟master在一条线上,但最上面又有一条合并记录。

若点击的是rebase呢:可以看到是将分支fenzhi_3的提交放在了最前面。这个操作就模拟了代码merge,但提交记录是一条线。这个才是我们的本意。

这个时候若继续将fenzhi_3 merge到master时只会产生一个合并记录:

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

不同分支之间的rebase操作是一个分支合并另一个分支的变更。这种操作的应用场景是啥呢?看下面案例:
比如有个fenzhi_2和fenzhi_3

比如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上右击鼠标选择变基操作:

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

看下结果,可以看到,它是将fenzhi_3的变更记录放在了fenzhi_2的前面,这跟cherry-pick是不一样的。所以选择合并不同分支代码的时候就要想清楚了。

推送代码即可:这里是强制推送。这里前提是必须保证fenzhi_2的最新提交记录与远程仓库一样的,若不确定的话,还是不要进行强制推送了。

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,操作步骤跟上面的一样,这里直接看结果:

看结果,这里不仅把fenzhi_2的提交合并,也会把master的新提交合并过来,这里很容易理解,因为rebase的操作就是从共同基线开始的。
2、看一下fenzhi_2 rebase onto fenzhi_1:可以看到有个提示

翻译下:

若继续rebase呢:看下结果,很明显fenzhi2_的基线就变了。

2.4、总结

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

到此这篇关于idea 实现git rebase操作详解的文章就介绍到这了,更多相关idea git rebase操作内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文