如何理解git rebase?

如何理解git rebase?

在merge PR的过程中,rebase and merge会产生冲突,因此需要补充一下Git rebase的知识点。

Understanding Rebase (And Merge) in Git

merge 是Git中最简单也是最常用的集成change的方法,但是这并不是唯一的一种方式。
Rebase是另外一种可选的但是略微高级的集成方式。

合并提交的case

通常情况下,一个由人类认真创建的commit,是一个有意义的单元:它仅仅包含相关的change并且每个commit都伴随着一个comment。
有一种merge commit可以让所有comments丢失:Git自动创建的commit,并且由Git填充所有的differ change。没有语义,没有主题。当然,这些独立commits的内容是保留的。但是history分成了注释的,分离的有意义的commit,由于这个原因,在一次merge commit中不会保留。
这就是为什么有些人不喜欢merge,喜欢rebase的原因。

Rebase之美

与一笼统把commits塞到一个commit不同,一个rebase会保留原始的commits。
项目的历史是一条单的,直线。没有任何迹象表明它在某个时候拆分出一个分支来。
如何理解git rebase?
在一次rebase后,看起来就像development从来没有被拆分成不同的分支。

我们来一步一步拆分一个rebase操作。方案很简单:我们想用rebase集成branch-B到branch-A。
如何理解git rebase?
一个rebase之前的方案。

命令很简单:

git rebase branch-B

首先,线条开始分支后,Git将"undo"所有的branch-A上的commits(在共同的祖提交后)。当然,它不会丢弃它们,而是临时将它们存了起来。
如何理解git rebase?

其次,它会应用我们想集成的来自branch-B的commits。此使,两个分支是相同的。
如何理解git rebase?

最后,branch-A的新commits重新被应用,但是在一个新的位置,在branch-B的后面。(they are rebased)。
结果就是development在一条直线上开发。不是一个commit包含了所有的改变,而是让原始commit结构保持原样。
如何理解git rebase?

下面尝试开BranchA,BranchB两个分支,然后基于webstorm的Version Control,观察git rebase操作会不会有上述的变化。

BranchA
如何理解git rebase?

BranchB
如何理解git rebase?

Rebase BranchA onto branchB
如何理解git rebase?
其实就是将branchB的母分支branchA进行了integrate changes,也就是把branchB的2次commit,放在共同的起点与branchA的新commit之间,或者也可以理解成将branchA的新commit,移动到了branchB的2次commits之后。

rebase的是谁,就修改的是谁
onto的是谁,谁就是被rebase的分支的新commits

其实,rebase只做了一件事:更新base branch!(重点!重点!重点!)

而想将谁的更新内容作为新的base branch的提交,就将作为topicBranch。

非常重要的命令。

git checkout baseBranch
git rebase topicBranch

再说的通俗一点,其实就是:挑了一个branch,把它的特性拿过来,放在我的新特性之前。

Merging vs. Rebasing

看完上面这篇文章后,并没有搞清楚rebase做了什么操作,所以还是需要多读一些文章。

  • 对于初学者来说,git rebase命令就像一个magic voodoo
  • merge和rebase都是用来从一个分支到另一个分支integrate changes的,只是方式不同

如何理解git rebase?

Merge Option

git checkout feature
git merge master
git merge master feature

会有一个'merge commit', 但是merge是非常安全的,不会像rebase有很多陷阱。
但是若master非常活跃,每次merge都会有要给'merge commit',会导致feature的commit history很脏。
如何理解git rebase?

Rebase Option

git checkout feature
git rebase master
  • feature从master tip处开始合并master上的commits
  • 重写project的history

如何理解git rebase?

  • rebase后,project的history更加干净了。没了多余的'merge commit',并且成了一条线。
  • rebase 需要遵循Golden Rule of Rebasing,否则会导致灾难性的合作workflow。
  • rebase 会丢失掉merge commit,导致看不到之后合并到feature的commit。

灵活一点的Rebasing

  • 选择特定的commits移动到新分支,加一个i选项
  • fixup某一个提交
git checkout feature
git rebase -i master
pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3
pick 33d5b7a Message for commit #1
fixup 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3

如何理解git rebase?

Golden Rule of Rebasing

永远不要在public 分支上使用git rebase!
如何理解git rebase?
每次使用git rebase前,问自己"有没有人也正在基于这个branch写代码?"若是的话,就老老实实用merge,不要尝试rebase。
若有gitflow的经验,其实就是当你开了一个feature/foo时,若同事也开了一个feature/bar,而且你们是同时基于develop checkout出来的分支,那么当develop有hotfix merge进去时,若你想拉去最新的develop代码,就不能用git rebase,只能用merge,否则会导致同事的develop分支与我们的develop分支不同,而此时她想再与我们保持同步是很复杂的。

Force-Pushing

若想将rebased的master分支推到远程仓库,Git 将会阻止你,因为它与远程的master分支冲突了。但是,你可以force push。

# 这个命令一定要小心使用
git push --force
  • 只有100%确定自己在做什么时再force,否则会让团队的人很困惑
  • 若是想将某个feature远程分支彻底替换掉,可以这样做。

下面尝试开master,feture两个分支,然后基于webstorm的Version Control,观察git rebase操作会不会有上述的变化。

master
如何理解git rebase?

feature
如何理解git rebase?

git checkout feature
git rebase master
# resolve conflict1
git rebase --continue
# resolve confict2
git rebase --continue

Rebase feature onto master
如何理解git rebase?

webstorm 的 Rebase Current onto selected什么操作?

可以理解成下图这样。

Rebase feature onto master

如何理解git rebase?

如何理解git rebase?

Current在WebStorm中指右下角的branch,selected一般指的original branch。

rebase and merge 一个Pull request做了什么操作?

如何理解git rebase?
相当于:

git checkout feature
git rebase master

像下图这样:
如何理解git rebase?

如何理解git rebase?

相关推荐