git pull和git pull --rebase之间的区别


311

有时我开始使用git,但并不完全了解其中的复杂性。我在这里的基本问题是找出a git pull和之间的区别git pull --rebase,因为添加--rebase选项似乎并没有太大不同:只是拉。

请帮助我理解区别。




Answers:


326

git pull= git fetch+ git merge禁止跟踪上游分支

git pull --rebase= git fetch+ git rebase禁止跟踪上游分支

如果你想知道如何git mergegit rebase不同,阅读本


12
值得一提的是说法git pull --rebase是一样的git fetch,并git rebase基本上它是如何,但它并不准确语义上等效。存在一些差异,此处将对其中一些进行解释。gitolite.com/git-pull--rebase
w0rp

8
借用斯科特·迈耶斯(Scott Meyers)的一句话,这就是我所说的“方便的谎言”。无论如何,这都是一个很好的解释方式。
w0rp

非常简短。我不明白其中的区别。那么重要的是fetch什么?
绿色的

240

有时,我们有一个上游,该上游重新定义/倒退了我们所依赖的分支。这可能是一个大问题-如果我们在下游,则会给我们造成混乱的冲突。

魔术是 git pull --rebase

粗略地说,一个普通的git pull是这样的事情(在所有这些示例中,我们将使用一个名为origin的远程对象和一个名为foo的分支):

# assume current checked out branch is "foo"
git fetch origin
git merge origin/foo

乍一看,您可能会认为git pull --rebase可以做到这一点:

git fetch origin
git rebase origin/foo

但是,如果上游基准库涉及任何“压缩”(这意味着提交的补丁程序ID发生变化,而不仅仅是它们的顺序更改),那将无济于事。

这意味着git pull --rebase必须做的更多。这是它的作用和方式的解释。

假设您的出发点是这样的:

a---b---c---d---e  (origin/foo) (also your local "foo")

时间的流逝,您已经在自己的“ foo”上进行了一些提交:

a---b---c---d---e---p---q---r (foo)

同时,出于反社会的愤怒,上游维护者不仅改变了他的“ foo”基础,甚至还使用了一两个南瓜。现在,他的提交链如下所示:

a---b+c---d+e---f  (origin/foo)

此时进行git pull将导致混乱。甚至是git fetch;git rebase origin / foo不会削减它,因为在一侧提交“ b”和“ c”,在另一侧提交“ b + c”会发生冲突。(并且与d,e和d + e类似)。

是什么git pull --rebase呢,在这种情况下,就是:

git fetch origin
git rebase --onto origin/foo e foo

这给您:

 a---b+c---d+e---f---p'---q'---r' (foo)

您可能仍然会遇到冲突,但是它们将是真正的冲突(在p / q / r与a / b + c / d + e / f之间),而不是由b / c与b + c冲突引起的冲突,等等。

答案取自(并稍作修改):http :
//gitolite.com/git-pull--rebase


9
这是最好的答案。您可能希望将最终结果更改为,a---b+c---d+e---f---p'---q'---r' (foo)因为重新设置基础会改变哈希值。
巴斯蒂安2014年

22
此答案是从gitolite.com/git-pull--rebase复制并逐字粘贴的,并且应在该页面上包含每个许可证的出处
2015年

这是一个很好的解释。但是我遇到了一种情况,即我已经提交了A,并且我向被接受的上游回购发送了PR。然后当我做git pull --rebase对上游回购A'进行操作时,在拉出的上游回购之上没有得到新的提交。实际上根本不A'存在。这是因为A已合并到系统中吗?还是因为上游与我的基础版本之间没有区别?
CMCDragonkai '16

我目前正在阅读Git教程,并使用此回复进一步了解git pull --rebase。但是在这种假设的情况下,令我感到困惑的是上游维护者改变了已经载入本地开发商存储库的项目历史。通常这不是不好的做法吗?如果他想压缩提交/重写历史记录,应该在将其集成到中央存储库之前完成,以避免这些类型的冲突。
bmcentee148

44

假设您在本地分支中有两次提交:

      D---E master
     /
A---B---C---F origin/master

在“ git pull”之后,将是:

      D--------E  
     /          \
A---B---C---F----G   master, origin/master

在“ git pull --rebase”之后,将没有合并点G。请注意,D和E变为不同的提交:

A---B---C---F---D'---E'   master, origin/master

1
是A --- B --- C --- D'--- E'-F吗?
prgmrDev

5
@prgmrDev为什么在F之前插入D和E?
乔恩(Jon)

1
难道不是git rebase真的吗?但是我们在谈论git pull --rebase。他们是不同的东西。
绿色

10

在最简单的情况下,没有碰撞

  • 使用rebase:在远程HEAD上重新建立本地提交,并执行 创建一个合并/合并提交
  • 无/正常:合并并创建合并提交

也可以看看:

man git-pull

更精确地讲,git pull使用给定的参数运行git fetch,并调用git merge将检索到的分支头合并到当前分支中。使用--rebase,它将运行git rebase而不是git merge。

另请参阅:
什么时候应该使用git pull --rebase?
http://git-scm.com/book/en/Git-Branching-Rebasing


3
如果发生碰撞?
Rndm

1
您将被要求手动解决它们,然后-继续进行变基:git sdd modified-file; git rebase --continue或合并:您手动修改的本地文件/ 合并工具git add modified-file; git commit;在哪里modified-file
drahnr 2013年

有什么特别之处fetch?他们为什么创建两个rebase流程?1)git rebase和2)git pull --rebase
绿色的

7

为此,了解合并和重新设置之间的区别很重要。

重新设置是更改应如何从层次结构的顶部向下传递,而合并则是更改如何向上流动的基础。

有关详细信息,请参阅-http: //www.derekgourlay.com/archives/428


我认为您的答案提供了一个简单得多的解释,而上述其他答案并不明显。谢谢。
亚伦C
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.