git pull、git fetch+merge 和 git rebase 之间的区别



我在git pullgit fetch+git mergegit rebase之间感到困惑。 它们似乎都执行相同的功能,那么它们之间有什么区别,特别是在提交日志方面。

如果远程分支和本地分支都有更改,则在所有三种情况下,谁的提交将首先出现。

正如您在问题中所暗示的那样,最令人困惑的部分是了解与远程存储库相比对本地存储库的影响,部分也是对使用远程存储库的其他所有人的影响。

首先,正如其他答案所示,git pull实际上与git fetch+git merge. 这两个命令都是从本地存储库拉取/获取+从远程存储库合并到本地存储库的角度。这发生在您在远程本地签出的同一分支到本地该分支。我将首先讨论这些,然后挤压和重新定位。

Git pull/git fetch + git merge

假设您已经在本地签出master,然后您将从远程获取master(除非您在这些命令上使用一些更高级的语法或标志)。我们将远程分支称为origin/master

origin/master获取意味着您希望从origin/master获取新提交,并更新本地跟踪引用以进行origin/master以匹配master在远程上的实际位置。 如果master在本地和远程之间有所不同,则会有提交从主分支分支出来,直到它们到达origin/master引用的当前位置。 您最近尚未推送的提交将位于可能不同的本地master分支上。

然后,当合并发生时,您基本上要求将origin/master合并到本地master分支中。 如果执行普通的合并命令,这将导致对本地master分支的新提交,该分支会将origin/master中的所有最新更改拉入本地master分支。 如果有冲突,您将在提交之前先解决它们。 但是,如果您没有在本地提交任何内容,则合并可以快进到新的origin/master位置,而无需执行任何其他操作(您的master将向前跳转以匹配origin/master)。

此时,如果您在其他人将更多内容推送到远程之前推送,那么您的新合并提交将与您单独的提交(它们看起来像一个单独的未命名分支)和原始远程提交一起推送,最后还有一个新的合并提交。

压扁呢?

您确实询问了这个问题,但是如果您与 --squash 合并,那么它将添加合并提交,但删除其他本地提交,以便历史记录中没有额外的未命名分支。 有些人喜欢这个,因为它"更干净",而另一些人更喜欢查看所有历史记录(即代码分歧以及在合并提交中究竟汇集了什么)。

变基

当你变基时,你基本上是把所有的本地提交,并将它们重播到远程主分支上,这样它们就不会显示为一个单独的分支。 这样可以保持本地历史记录的完整,而不会显示代码发散,同样,有些人更喜欢并认为它更"干净"。 这与任何历史是否重要等无关。

万一我取后别人犯了怎么办?

如果其他人忍者在您获取后承诺(好吧,刚刚提交...),那么您的推送将失败。 您可以使用--force,但随后您将完全覆盖他们的提交,因此这通常是不受欢迎的,因为它会给其他人带来各种问题。 在这种情况下,如果每个人都同意他的提交应该先进行,那么你需要再次经历这个过程(如果没有冲突,那么这是快速和容易的),但总的来说,团队需要对这类事情有一个策略,并且经常使用拉取请求和审查来管理推送以更有序的方式, 一旦团队变得足够大。

另一种思考方式

通过将本地主分支视为与远程分支分开的分支,可能很容易理解正在发生的事情 - 从 Git 的角度来看,这基本上就是正在发生的事情。

事实上,在我看来,在你准备好将某些东西合并到远程分支之前,你总是最好在你自己的独立分支中工作。Git 使拥有一个单独的分支变得如此简单、快速和无痛,这就是我所做的。

使用一些谷歌。git pull=git fetch后跟git merge。谷歌搜索git pull时第一次命中:https://git-scm.com/docs/git-pull:

在其默认模式下,git pull 是 git fetch 的简写,后跟 git merge FETCH_HEAD。

git rebase是完全不同的东西,与遥控器无关。同样,谷歌可以解决你的问题,但有一个简短的图形解释,当站在分支 A 上,并重新定位在 B 之上时(这与站在 A 上并将 B合并其中不同):

c1-c2-c3<-A
-c4-c5<-B

成为

c1-c4-c5-c2-c3<-A
^
B

我们在这里所做的是在 A(我们所在的)上获取发散提交并将它们应用于 B 之上,基本上删除了分支结构。永远不会有像"合并提交"这样的"变基提交"。这与远程更改无关,除了git pull --rebase将获取本地更改,然后在远程更改之上重新设置其基数,而不是将远程更改合并到本地提交中。再次,google.com 或 git-scm.com/docs。

来自 git 文档

git pull将来自远程存储库的更改合并到当前分支中。在其默认模式下,git pullgit fetch后跟git merge FETCH_HEAD的简写

rebase在另一个基本提示之上重新应用提交。

所以你可以在fetched之后做git rebase FETCH_HEAD

所以如果你有

(*) <-- HEAD
|
(*) <-- commit B
   (*) <-- origin/master
  /
(*) <-- commit A

如果你使用rebase,git 将倒带你的 HEAD 来提交 A 并应用按日期排序的所有提交

如果你使用merge,git 会将两个分支合并为一个分支,在origin/head顶部应用你的提交

最新更新