git rebase 指令的使用,对比 merge 命令

git rebase指令

一、基本使用

  1. github上新建一个项目

    image-20211213205417673
  2. 默认有master分支(注意:现在的Github默认创建的分支是main分支)

    image-20211213205622555
  3. 将项目clone到本地

模拟日常开发

A同学操作

  1. 执行git log

    image-20211213205839717

    可以看出此时该项目仅有一次提交记录

  2. 新增文件,执行commit、push操作

    image-20211213205906793 image-20211214091804785
  3. 刷新Github,发现A同学提交的记录

    image-20211213210040623
  4. 基于已有两次提交记录的本地master分支检出一个新分支dev,并将该分支推到远程仓库

    image-20211213210123526
  5. 查看远程仓库,多了一个dev分支

    image-20211213210141254
  6. 此时本地的git分支图类似如下(C1、C2表示提交的版本)

    image-20211213210200295
  7. 假设A同学基于dev分支开发功能,在本地新做了三次代码提交,git log 如下

    image-20211213210237887
  8. 此时的git分支图如下

    image-20211213210253548

B同学操作

如果此时在A同学准备进行第四次本地提交之前,另一个同学B向远程仓库推送了一个master分支的提交,即此时master实际的提交已经向前走了:

image-20211213210406182

A同学操作

  1. 切换到master分支,获取master最新的B提交的代码

  2. 此时的分支图如下

    image-20211213210607938
  3. A同学开发的dev分支是基于C2提交点切出来的,而这个时候master分支已经被更新了,如果A同学开发完毕,需要将其所作的功能合并到master分支 ,他可以有两种选择:

    • git merge
    • git rebase

方式一:git merge

切换到master分支,执行 git merge dev 命令,该命令的执行过程如下:

  • 找出dev分支和master分支的最近共同祖先commit点,即C2

  • 将dev最新一次commit(C5)和master最新一次commit(C6)合并后生成一个新的commit(C7),有冲突的话需要解决冲突

  • 将以上两个分支dev和master上的所有提交点(从C2以后的)按照提交时间的先后顺序依次放到master分支上(也就是说所有提交的记录都会保留)

  • 此时的分支图如下:

    image-20211213210912489

之后A同学继续在dev分支进行开发,master继续往前走,如果发生merge重复上述步骤。

这种方式的缺点:

由于merge会把所有分支的各种信息都会记录下来,如果项目分支较多且commit次数较多,就会出现如下情况,过于复杂:

image-20211214095613790

方式二:git rebase

  1. rebase之前需要将master的代码pull到最新

  2. 在dev分支,执行 git rebase master 命令,执行之后效果如下:

    image-20211214100149789

    可以发现并没有多出一次commit,而且dev后面几次提交的commit hash值已经变了,包括C3,C4,C5。

  3. 切换到master分支,执行 git rebase dev,执行之后效果如下:

    image-20211214100956938

    发现采用rebase的方式进行分支合并,整个master分支并没有多出一个新的commit,原来dev分支上的那几次(C3,C4,C5)commit在rebase之后其hash值发生了变化,整个master分支的commit记录呈线性记录,如下图:

    image-20211214101648176

    注意:原master的C6在dev的C3之前。

总结

  1. git merge 操作合并分支会让两个分支的每一次提交都按照提交时间(并不是push时间)排序,并且会将两个分支的最新一次commit点进行合并成一个新的commit,最终的分支树呈现非整条线性直线的形式。

  2. git rebase操作实际上是将当前执行rebase分支的所有基于原分支提交点之后的commit打散成一个一个的 patch(补丁),并重新生成一个新的commit hash值,再次基于原分支目前最新的commit点(所以需要将master拉取到最新)上进行提交,可以保持整个分支树的完美线性。

  3. 两种方式的对比图:

    image-20211214102904271

二、-i 参数合并commit

在日常开发中,代码变更比较频繁,有时候想让前几次提交的合并为一次提交(比如某一功能的多次提交只保留最后一次提交),这里可以使用git rebase -i 命令来完成。

格式:

git rebase -i [startpoint] [endpoint]

其中 -i 的意思是 –interactive,即弹出交互式的界面让用户编辑完成合并操作,[startpoint] [endpoint] 则指定了一个编辑区间,如果不指定 [endpoint],则该区间的终点默认是当前分支HEAD所指向的commit点(注意:该区间指定的是一个前开后闭的区间

举例:

// 合并从当前head到15f745b(commit id)
git rebase -i 15f745b

// 合并最近的两次提交
git rebase -i HEAD~2

执行这个命令后会跳到一个vi编辑器:

将这个编辑器中想要压缩的commit的最前端修改为s,s 为 squash 的缩写,表示将这次提交压缩为最后一次提交。

image-20211214102904271

输入 :wq 进行保存,会弹出如下界面:

image-20211214105155877

输入 :wq 进行保存,然后输入 git push -f 与github端同步。

三、补充指令

git rebase --continue:继续rebase操作,比如rebase时发生冲突,解决完后 git add,再执行 git rebase --continue 就可以继续rebase操作了。

git rebase --abort:终止本次rebase操作。

猜你喜欢

转载自blog.csdn.net/weixin_49343190/article/details/121924180