Py学习  »  Git

如何理解git rebase?

趁你还年轻233 • 5 年前 • 308 次点击  
阅读 29

如何理解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。 项目的历史是一条单的,直线。没有任何迹象表明它在某个时候拆分出一个分支来。

image
在一次rebase后,看起来就像development从来没有被拆分成不同的分支。

我们来一步一步拆分一个rebase操作。方案很简单:我们想用rebase集成branch-B到branch-A。

image
一个rebase之前的方案。

命令很简单:

git rebase branch-B
复制代码

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

image

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

image

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

image

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

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


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/6Kq1XKiqlN
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/27132
 
308 次点击