多用 Git rebase ?

之前公司项目分支合并基本都使用 git merge , 久而久之发现有一些代码合并缺漏的问题。

git merge 会产生一个多余的 commit, 并且这个 commit 在文件的 commit 历史的找不到的,这样导致代码遗漏缺失很难溯源。

后来在一篇知乎问答「 Git commits 历史是如何做到如此清爽的? (opens new window)」下面看到尤雨溪的回答:多用 rebase!

那么 merge 和 rebase 究竟有什么区别呢 ?rebase 能解决什么问题?

1. 首先我们看一个 git merge 例子:

我们在 master 分支初始化一个 commit

git commit -m 'init', 此时 commit ID 为 640d9a77271d614eeb826b1b53b3a1419e73c0cd

console.log("init");

接着创建 test 分支 git checkout -b test,并新增一个 commit 'test'

git commit -m 'test', 此时 commit ID 为 278ba9e59aa83d706017f32f6c64260c815fc638

console.log("init");
console.log("test");

再者回到 master git checkout master 新增一个 commit 'master'

git commit -m 'master', 此时 commit ID 为 065a9a2480a024ceef7dca3ecc7856c299377141

console.log("init");
console.log("master");

再将 test 分支合并到 master, 就会出现冲突

// git merge test
console.log('init')
<<<<<<< HEAD
console.log('master')
=======
console.log('test')
>>>>>>> test

此时我们保留 master 的变动, 并添加一句注释 use master,再用编辑器默认 message 提交 commit

console.log("init");
// use master
console.log("master");

此时 master 分支的 git 记录如下:

commit 89a68f5acd87e5de3e0ff38cd146fefef1f256d0 (HEAD -> master)
Merge: 065a9a2 278ba9e
Author: xiaopika <zxpscau@163.com>
Date:   Wed May 22 10:49:37 2024 +0800

    Merge branch 'test'

commit 065a9a2480a024ceef7dca3ecc7856c299377141
Author: xiaopika <zxpscau@163.com>
Date:   Wed May 22 10:45:56 2024 +0800

    master

commit 278ba9e59aa83d706017f32f6c64260c815fc638 (test)
Author: xiaopika <zxpscau@163.com>
Date:   Wed May 22 10:45:35 2024 +0800

    test

commit 640d9a77271d614eeb826b1b53b3a1419e73c0cd
Author: xiaopika <zxpscau@163.com>
Date:   Wed May 22 10:45:15 2024 +0800

    init

和之前的 commit ID 对比我们发现,commit ID 没有变化,并按照时间顺序排列,并且 merge 还会新增一个“无效”commit, merge 的好处是:提交历史记录清晰,便于溯源。

2. 我们再来看 git rebase 的例子

和上述同样的操作,只不过这次我们是将 master 合进 test 分支, 在 test 分支上执行 git rebase master

test 分支合并前的记录如下:

commit cb5de32691465d8e8ef188d4fa576637d883a03b (HEAD -> test)
Author: xiaopika <zxpscau@163.com>
Date:   Wed May 22 11:42:14 2024 +0800

    test

commit 1557ff20f62592f028e66ac33a11cb5e24af02d2 (t)
Author: xiaopika <zxpscau@163.com>
Date:   Wed May 22 11:41:04 2024 +0800

    init

test 分支合并后的记录如下:

commit 5cf3442b8e9c30f202cf21edb4352ac3d7d59775 (HEAD -> test)
Author: xiaopika <zxpscau@163.com>
Date:   Wed May 22 11:42:14 2024 +0800

    test

commit 9148a21b44db2aef8708804003c25c591a23fcbc (master)
Author: xiaopika <zxpscau@163.com>
Date:   Wed May 22 11:42:33 2024 +0800

    master

commit 1557ff20f62592f028e66ac33a11cb5e24af02d2 (t)
Author: xiaopika <zxpscau@163.com>
Date:   Wed May 22 11:41:04 2024 +0800

    init

观察前后两个记录你会发现,test 这个 commit 时间人物没有变,但是顺序和 id 都变了

总的来说就是 rebase 会删除你本地分支原来的 commit, 合并主分支后又生成原来的 commit, 但顺序和 id 变化了

总的来说,merge 和 rebase 这两者哪种操作更好,这是取决于不同的场景的。

  • 当我们拉取公共分支最新代码的时候建议使用 rebase,也就是 git pull -rgit pull --rebase,这样不会生成多余 commit;
  • 当我们功能分支合并公共分支的时候建议用 git rebase [branch],让我们的 commit 处于最前方且不会有多余的 commit。
  • 当我们往公共分支上合代码的时候,使用 merge 合并可以使提交历史记录清晰,便于溯源。