Git基础入门七:Git高级命令之Rebase

作者同系列博客参考链接:

Git基础入门六:标签管理(git tag)
Git基础入门五:分支管理
Git基础入门四:版本回退(撤销修改)
Git基础入门三:创建版本库和添加修改文件基本命令
Git基础入门二:工作区和暂存区
Git基础入门一:起源与安装

1、rebase概念:

rebase翻译过来的意思是变基,将你的当前分支重新设置开始点。

rebase会把你当前分支的 commit 放到公共分支的最后面,所以叫变基。就好像你从公共分支又重新拉出来这个分支一样。
举例:如果你从 master 拉了个feature分支出来,然后你提交了几个 commit,这个时候刚好有人把他开发的东西合并到 master 了,这个时候 master 就比你拉分支的时候多了几个 commit,如果这个时候你 rebase master 的话,就会把你当前的几个 commit,放到那个人 commit 的后面。

rebase操作的特点:把分叉的提交历史整理成一条直线,看上去更直观。缺点是本地的分叉提交已经被修改过了。

操作方法思路:你可以提取在旁支 中引入的补丁和修改,然后在 主分支 的基础上应用一次。

目的:rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。

2、Rebase和merge区别:

操作前:

Git基础入门七:Git高级命令之Rebase_第1张图片

Merge后:

Git基础入门七:Git高级命令之Rebase_第2张图片

Rebase后:

$ git checkout experiment

$ git rebase master

或者:

$ git rebase master experiment

 使用 git rebase [basebranch] [topicbranch] 命令可以直接将特性分支(即本例中的 experiment)变基到目标分支(即 master)上。这样做能省去你先切换到 experiment分支,再对其执行变基命令的多个步骤。

 

Git基础入门七:Git高级命令之Rebase_第3张图片

此时还需做下快速合并分支,使得experimentmaster指针到最新版本:

$ git checkout master

$ git merge experiment

Git基础入门七:Git高级命令之Rebase_第4张图片

请注意:无论是通过变基,还是通过三方合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了。 变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。

3、切片rebase--onto选项: 截取特性分支上的另一个特性分支,然后变基到其他分支

原场景:

Git基础入门七:Git高级命令之Rebase_第5张图片

诉求:只想把client的改动而不是server分支的改动合并到master

$ git rebase --onto master server client

以上命令的意思是:取出 client 分支,找出处于 client 分支和 server 分支的共同祖先之后的修改,然后把它们在 master 分支上重放一遍

Git基础入门七:Git高级命令之Rebase_第6张图片

然后再从client快速合并到master中:

$ git checkout master

$ git merge client

Git基础入门七:Git高级命令之Rebase_第7张图片

接下来你决定将 server 分支中的修改也整合进masterserver 中的代码被到了 master 后面。

$ git rebase master server

Git基础入门七:Git高级命令之Rebase_第8张图片

然后就可以快进合并主分支 master 了:

$ git checkout master

$ git merge server

至此,client  server 分支中的修改都已经整合到主分支里了,你可以删除这两个分支,最终提交历史会变成图 最终的提交历史 中的样子:

$ git branch -d client

$ git branch -d server

4、变基的风险:不要对在你的仓库外有副本的分支执行变基。

变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。 如果你已经将提交推送至某个仓库,而其他人也已经从该仓库拉取提交并进行了后续工作,此时,如果你用 git rebase 命令重新整理了提交并再次推送,你的同伴因此将不得不再次将他们手头的工作与你的提交进行整合,如果接下来你还要拉取并整合他们修改过的提交,事情就会变得一团糟。

5、在一个被变基然后强制推送的分支上再次执行变基

       如果团队中的某人强制推送并覆盖了一些你所基于的提交,你需要做的就是检查你做了哪些修改,以及他们覆盖了哪些修改。

实际上,Git 除了对整个提交计算 SHA-1 校验和以外,也对本次提交所引入的修改计算了校验和—— “patch-id”

如果你拉取被覆盖过的更新并将你手头的工作基于此进行变基的话,一般情况下 Git 都能成功分辨出哪些是你的修改,并把它们应用到新分支上。

举个例子,如果遇到前面提到的 有人推送了经过变基的提交,并丢弃了你的本地开发所基于的一些提交 那种情境,如果我们不是执行合并,而是执行 git rebase teamone/master, Git 将会:

  • 检查哪些提交是我们的分支上独有的(C2C3C4C6C7
  • 检查其中哪些提交不是合并操作的结果(C2C3C4
  • 检查哪些提交在对方覆盖更新时并没有被纳入目标分支(只有 C2 C3,因为 C4 其实就是 C4'
  • 把查到的这些提交应用在 teamone/master 上面

 

(1)原场景:

Git基础入门七:Git高级命令之Rebase_第9张图片

(2)Git pull方式会变成下图所示情况:

Git基础入门七:Git高级命令之Rebase_第10张图片

此时如果你执行 git log 命令,你会发现有两个提交的作者、日期、日志居然是一样的,这会令人感到混乱。 此外,如果你将这一堆又推送到服务器上,你实际上是将那些已经被变基抛弃的提交又找了回来,这会令人感到更加混乱。 很明显对方并不想在提交历史中看到 C4  C6,因为之前就是他把这两个提交通过变基丢弃的。

(3)用变基解决变基: git rebase teamone/master

上图变为:

Git基础入门七:Git高级命令之Rebase_第11张图片

要想上述方案有效,还需要对方在变基时确保 C4' C4 是几乎一样的。 否则变基操作将无法识别,并新建另一个类似 C4 的补丁(而这个补丁很可能无法整洁的整合入历史,因为补丁中的修改已经存在于某个地方了)。

在本例中另一种简单的方法是使用 git pull --rebase 命令而不是直接 git pull 又或者你可以自己手动完成这个过程,先 git fetch,再 git rebase teamone/master

如果你习惯使用 git pull ,同时又希望默认使用选项 --rebase,你可以执行这条语句 git config --global pull.rebase true 来更改 pull.rebase 的默认配置。

只要你把变基命令当作是在推送前清理提交使之整洁的工具,并且只在从未推送至共用仓库的提交上执行变基命令,就不会有事。 假如在那些已经被推送至共用仓库的提交上执行变基命令,并因此丢弃了一些别人的开发所基于的提交,那你就有大麻烦了,你的同事也会因此鄙视你。如果你或你的同事在某些情形下决意要这么做,请一定要通知每个人执行 git pull --rebase 命令,这样尽管不能避免伤痛,但能有所缓解。

到底合并还是变基好?总的原则是,只对尚未推送或分享给别人的本地修改执行变基操作清理历史,从不对已推送至别处的提交执行变基操作,这样,你才能享受到两种方式带来的便利。

 

作者同系列博客参考链接:

Git基础入门六:标签管理(git tag)标签管理(git tag)
Git基础入门五:分支管理
Git基础入门四:版本回退(撤销修改)
Git基础入门三:创建版本库和添加修改文件基本命令
Git基础入门二:工作区和暂存区
Git基础入门一:起源与安装

你可能感兴趣的:(GIT/GITLAB)