git rebase 一看就会,一上手就废

git merge

在团队开发中,少不了需要合并分支代码,常规的命令都是使用git merge来合并我们的代码,一般操作是:

  • 本地分支 拉取 目标分支最新代码
  • 切换到目标分支,拉取 本地分支代码

注意,这里的 拉取 ,我们用的是 VSCode 自带的 git 图形操作界面的 拉取 ,其实就是 git pull 指令,而 git pull 背后就是 git fetchgit merge 的结合。

这种 git merge 的方式比较简单且常规,可能唯一有点影响的就是美观?因为你的 git 提交历史记录会出现大量的合并记录,同时会出现很多分支的分叉。

git rebase

如果想要保证自己的提交历史记录是线性的,就可以使用 git rebase 命令,效果如下图:

注意,git rebasegit pull --rebase 效果是一样的!

现在模拟一下,假设本地开发分支是 dev 分支,我们需要将最新的提交 B2 合并到 master 分支,我们在 dev 分支上执行 git rebase master,会出现以下情况:

  1. dev 分支上的提交节点 B2 以补丁的形式保存起来,这里假设为 B2',放到 master 分支上最后一次提交。然后 dev 分支上的 HEAD 指针指向 master 分支上的最新提交的补丁节点B2'
  2. 但是此时 master 分支上的 HEAD 指针,还是指向自己分支最后一次提交,即B节点
  3. 所以要切到 master 分支,需要进行 拉取 我们的 dev 分支,此时会进行fast forward快进的一个操作,将 HEAD 也指向最新的提交。

git rebase 的 "坑"

正常像上面合并是没有任何问题的,git 提交记录也会是线性的,但那是有一个前提条件的,即我们在合并 master 分支的时候, master 分支上不能有任何新的提交,这在实际开发中基本不可能!

假设我们 rebase的时候,master 分支上有一次新的提交 C,我们继续之前的操作 git rebase master,会出现以下情况:

  1. 第一步没有变化,还是 将 dev 分支上的提交节点 B2 以补丁的形式保存起来,这里假设为 B2',放到 master 分支上作为最后一次提交。然后 dev 分支上的 HEAD 指针指向 master 分支上的最新提交的补丁节点B2'

  2. 但此时 VSCode 就会提示同步更改代码,即 pullpush 本地分支。简单说,就是 git rebase 会重新应用你的提交到最新的 master 分支之上,这个过程会修改你的提交历史,你的本地分支 dev 上的提交历史已经改变了,需要将这些更改同步到远程仓库。 但要命的是,如果你选择了同步更改代码,恭喜你,你的代码提交记录不再清爽了/(ㄒoㄒ)/~~ 会多了合并提交的记录,而且即使你删掉 dev 分支,dev 分支合并进来的图谱还存在。 那该如何解决呢?让历史提交记录继续保持清爽的线性?

    不能点击同步更改,而是使用 git push --force 来强制推送本地分支到远程分支!

这时候就会有人说,强制推送,这在公司能随便用吗?不怕覆盖别人的历史提交记录?

稍安毋躁,git rebase 的最佳实践就是在自己的本地分支上执行,不能在公共分支上执行! 所以自己分支上执行强制推送,没有任何问题,因为覆盖的只有自己的提交记录。同时,你要是觉得不保险,还可以使用git push --force-with-lease这种更安全的选项,它会在强制推送之前检查远程分支是否已经被其他人更新,防止意外覆盖。

  1. 跟之前一样。此时 master 分支上的 HEAD 指针,还是指向自己分支最后一次提交,即B节点
  2. 跟之前一样。切到 master 分支,需要进行 拉取 我们的 dev 分支,此时会进行fast forward快进的一个操作,将 HEAD 也指向最新的提交。最终就大功告成了,我们的提交记录又清爽了!

git rebase 注意点

  1. git rebase 的最佳实践就是在自己的本地分支上执行,不能在公共分支上执行!
  2. 执行 git rebase 的时候,一定要确保变基前服务区必须是干净的,不能有任何文件的更改。
  • 要么使用 git commit 提交本地代码
  • 要么使用 git stash 暂存本地代码
  1. 如果遇到冲突,有以下三个命令行可以来解决冲突:
  • git rebase -- skip会丢弃掉当前补丁,以目标分支上的为准,丢弃掉本地分支上的修改
  • git rebase --abort会丢弃掉整个 rebase 操作,重新恢复到 rebase 之前的状态
  • git rebase --continue 就是解决完一个冲突后,继续 rebase 下去

但实际开发中很少用命令行,直接在 VSCode 中,解决 rebase 合并冲突跟解决merge合并冲突一样,正常解决即可 4. 在自己分支上 rebase 完之后,一定要手动执行 git push -f 强制推送!!

git rebase 高阶操作

如果 rebase 只是为了保证 git 提交历史记录的线性,那也太小看 rebase 的强悍之处。

交互式 rebase

执行git rebase -i HEAD~~,这会打开一个交互式界面,一个~代表压缩(或者说删除)一次提交,也可以用数字代表git rebase -i HEAD~2,让你可以修改、合并、删除或重新排序最近的 2 个提交。

总结

因为 rebase 的时候要考虑的心智负担太重,如果我们用的是 VSCode 图形化界面操作 git,那本地分支最后还需要手动输入命令 git push -f 进行强制推送,不熟练的情况下还是比较繁琐的。除非公司有洁癖特别要求使用 rebase,大家还是老老实实使用 merge 吧。

相关推荐
FreeBuf_4 小时前
Radamsa:一款高性能通用模糊测试工具
git·测试工具
去捕风吗10 小时前
git命令
git
Salt-Kin10 小时前
#git 如何将现有更改追加到到已经提交的commit
git
keep090111 小时前
git revert和git reset工作中使用
git
程序员iteng13 小时前
需求开发全流程
java·git·spring
去捕风吗19 小时前
git add . 警告
git
fastjson_19 小时前
解决 IDEA 中使用 git 提交显示多余空行
git
知否技术20 小时前
Git系列教程,从小白到大神
git·后端
DieSnowK21 小时前
[Git][多人协作][上]详细讲解
git·仓库·代码管理·新手向·详细讲解·代码追踪·同一分支下多人协作
真我的风采i21 小时前
初始化seata在nacos的配置报错nacos-config.sh 127.0.0.1-nacos-config.txt-文件不存在
java·windows·git·nacos·seata·sh脚本