我到底应该用git-merge还是git-rebase呢?

本文一共3165字 , 将通俗的解释git中两种合并策略——merge和rebase的不同、运用方式和使用的场景 , 并辅以我在工作中的运用来介绍;
我到底应该用git-merge还是git-rebase呢?文章插图
什么是git merge?git merge是我们在git操作中频繁会用到的一个命令 , 它主要实现的功能便是为我们进行分支代码的合并 , 也就是将两个或两个以上的开发历史合并在一起的操作 。
它有以下两种用途:

  1. 更新代码时 , 整合另一个代码仓库中的变化 , 也就是git pull命令中 , 我们使用git pull命令时 , 实际上相当于git fetch+git merge , 进行了远程仓库代码的拉取 , 以及整合另一代码仓库中的变化
  2. 用于从一个分支到另一个分支的合并 , 我们一般会通过该命令进行从指定的commit(s)合并到当前分支的操作 , 要注意的是这里的指定commit(s)是指从这些历史commit节点开始 , 一直到当前分开的时候 。
git merge有个重要的特点 , 便是在合并过程中 , 它会创建一个新的commit节点 , 来作为我们的合并结果节点 , 如下图
a. 假设master目前的历史提交情况如下 , head处于commit-D的位置 。
我到底应该用git-merge还是git-rebase呢?文章插图
b. 我们从D的位置 , checkout出一个新分支feature , 并增加了两次提交E和F 。
我到底应该用git-merge还是git-rebase呢?文章插图
c. 然后我们想将feature分支合并到master上 , 此时我们只需要在master分支上执行
git merge feature
此时将在master上将合并结果生成一个新的commit节点G , 最终推送远程分支 。
我到底应该用git-merge还是git-rebase呢?文章插图
可见merge命令的强大和便利 , 通过分支来完成需求代码的编写 , 再通过合并的方式 , 保证了主分支的整洁性 。
什么是git rebase?说完了git merge , 我们来说一说git rebase 。
我们可以把git rebase理解成是“重新设置基线” , 将你的当前分支重新设置开始点 。 我们便能知道你当前分支与你需要比较的分支之间的差异 。
也就是基于一个分支来设置你当前的分支的基线 , 这基线就是当前分支的开始时间轴向后移动到最新的跟踪分支的最后面 , 这样你的当前分支就是最新的跟踪分支 。
它有以下几点用途:
  1. 合并提交记录 , 比如说对于我们拉取出来的开发分支 , 可能会在开发过程中多次提交测试 , 会产生很多不规范的、不必要的提交 , 这类提交将会造成我们的分支污染 , 当出现问题需要回退时 , 将增加难度 。
  2. 合并分支 , 乍一看好像与merge命令拥有同样的功能 , 是的 , 它们都能合并 , 不过彼此的合并原理却大大不同 , git merge是将合并结果产生新节点 , 不影响历史的提交 , 而git rebase是基于变基的操作 , 它会将分支的开始点基于rebase的分支重新设置 , 并将rebase的分支重新提交 , 直接贴到该分支开始点之后 , 再之后才是该分支自己的提交 。
多说无益 , 我们根据这两点来描述下场景 , 加深大家的理解:
合并提交记录
假设此时分支上有三次提交 , 分别是first commit , second commit , third commit , 我希望将前两次进行合并 , 最终得到两次提交的结果 。
a. 我们使用“git rebase -i HEAD~3”命令查看最近三次提交 , 并打开一个编辑器 , 其中第一列为“操作指令” , 第二列和第三列为我们的提交信息:
我到底应该用git-merge还是git-rebase呢?文章插图
git rebase -i HEAD~3
b. 操作指令包括:
pick:保留该commit;reword:保留该commit但是修改commit信息;edit:保留该commit但是要修改commit内容;squash:将该commit和前一个commit合并;fixup:将该commit和前一个commit合并 , 并不保留该commit的commit信息;exec:执行shell命令;drop:删除该commit 。
在本次操作中 , 我们将使用squash命令 , 将第二个合并到第一个里面去 , 修改后保存退出 , 如下:
我到底应该用git-merge还是git-rebase呢?文章插图
在编辑器中修改 , 将第二个的操作指令修改为squash
c. 保存退出 , 进入编辑器 , 对合并后的commit信息进行编辑 , 我们将“1 --tt-darkmode-color: #A3A3A3;">rebase:会把你当前分支的 commit 放到公共分支的最后面,所以叫变基 。 就好像你从公共分支又重新拉出来这个分支一样 。
就像刚刚上面的例子: 如果你从 master 拉了个dev分支出来,然后你提交了几个 commit,这个时候刚好有人把他开发的东西合并到 master 了,这个时候 master 就比你拉分支的时候多了几个 commit,如果这个时候你 rebase master 的话 , 就会把你当前的几个 commit , 放到那个人 commit 的后面 。