如何理解git rebase?

clipboard.png

在merge PR的过程当中,rebase and merge会产生冲突,所以须要补充一下Git rebase的知识点。git

Understanding Rebase (And Merge) in Git

merge 是Git中最简单也是最经常使用的集成change的方法,可是这并非惟一的一种方式。
Rebase是另一种可选的可是略微高级的集成方式。web

合并提交的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。
项目的历史是一条单的,直线。没有任何迹象代表它在某个时候拆分出一个分支来。
image
在一次rebase后,看起来就像development历来没有被拆分红不一样的分支。webstorm

咱们来一步一步拆分一个rebase操做。方案很简单:咱们想用rebase集成branch-B到branch-A。
image
一个rebase以前的方案。spa

命令很简单:3d

git rebase branch-B

首先,线条开始分支后,Git将"undo"全部的branch-A上的commits(在共同的祖提交后)。固然,它不会丢弃它们,而是临时将它们存了起来。
imagecode

其次,它会应用咱们想集成的来自branch-B的commits。此使,两个分支是相同的。
imageorm

最后,branch-A的新commits从新被应用,可是在一个新的位置,在branch-B的后面。(they are rebased)。
结果就是development在一条直线上开发。不是一个commit包含了全部的改变,而是让原始commit结构保持原样。
imageblog

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

BranchA
image

BranchB
image

Rebase BranchA onto branchB
image
其实就是将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的,只是方式不一样

image

Merge Option

git checkout feature
git merge master
git merge master feature

会有一个'merge commit', 可是merge是很是安全的,不会像rebase有不少陷阱。
可是若master很是活跃,每次merge都会有要给'merge commit',会致使feature的commit history很脏。
image

Rebase Option

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

image

  • 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

image

Golden Rule of Rebasing

永远不要在public 分支上使用git rebase!
image
每次使用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
image

feature
image

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

Rebase feature onto master
image

webstorm 的 Rebase Current onto selected什么操做?

能够理解成下图这样。

Rebase feature onto master

image

image

Current在WebStorm中指右下角的branch,selected通常指的original branch。

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

image
至关于:

git checkout feature
git rebase master

像下图这样:
image

image

相关文章
相关标签/搜索