什么是“变基”,理解 git rebase 命令,它与 git merge 的区别
git merge
先简单说一下 git merge 命令,相信大家对 git merge 命令都很熟悉,我们日常合并代码用得最多的就是 git merge 命令。
基本用法如下:
// 将 yourBrach 的代码合并到当前分支
git merge yourBranch
使用 git merge 命令合并分支会产生一个新的提交。合并如果出现冲突需要手动解决冲突,并重新依次执行 git add . 和 git commit -m "提交说明" 提交代码。
快进式合并
git merge 默认是快进式合并,快进式合并时分支的提交历史没有 "开叉" 现象,也就是没有多个父提交节点。如下所示:
D1---D2--- dev
/
M1---M2---------- master
上面我们的 dev 分支是从 master 分出来的,后续我们在 dev 分支上有两次代码提交 D1 和 D2 ,在 master 分支上我们没有做任何修改。在这种情况写,我们就可以在 master 分支执行 git merge dev 进行快速合并,git 会直接将 master 分支指向 dev 分支,合并后的分支历史如下:
M1---M2---D1---D2--- master/dev
master 分支快进到了 dev 分支的位置。
非快进式合并
快进式的分支合并不会对合并操作产生提交历史,有时候这不是我们想要的结果,如果我们想要保留合并操作的历史记录怎么办?
这种情况下我们就可以使用非快进式的分支合并,结合上面的例子用法如下:
git merge --no-ff dev
git rebase(变基)
git rebase 也是分支合并的一种方法,以上面的 master 和 dev 分支为例,我们将 dev 分支中 D1 和 D2 的修改提取出来,在 M2 的基础上应用一次,这在 git 中就叫做变基。它的原理是找的 master 和 dev 的最近共同祖先 M2,然后将 D1 和 D2 的修改提取出来存临时文件,然后将当前分支指向 M2,然后应用缓存的 D1 和 D2 修改。
git rebase 应用场景
合并多个commit
例如对同一个功能的修改我们前前后后一共提交了3次,但是我们指向保留此意 commit 记录,我们就可以利用 git rebase 命令帮助我们达到此目的。
我们来合并最近的 3 次提交纪录,执行:
git rebase -i HEAD~3
接下来会自动进入 vi 编辑模式,按照注释中的命令进行你想要的操作
s cacc52da feat: 增加某功能
s f072ef48 fix: 功能完善
s 4e84901a fix: 功能自测bug修复
# Rebase 5f2452b2..8f33126c onto 5f2452b2 (4 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
完成后保存并退出,然后执行:
git rebase --continue
完成后,git log 查看日志,三次提交合并为了一次。
合并分支
git rebase 合并分支与 git merge 合并分支类似,这里我们合并 dev 到master,在 master 分支执行命令:
git rebase dev
如果没有冲突的话,就直接完成了,如果出现冲突,git 会停止合并,需要手动解决冲突并使用 git add 更新,无需commit,执行下面的命令即可:
git rebase --continue
注意:git rebase 只能操作你未 push 到远程的 commit,切记切记!