我在git pull
、git fetch
+git merge
和git 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 pull
是git fetch
后跟git merge FETCH_HEAD
的简写
rebase
在另一个基本提示之上重新应用提交。
所以你可以在fetch
ed之后做git rebase FETCH_HEAD
所以如果你有
(*) <-- HEAD
|
(*) <-- commit B
(*) <-- origin/master
/
(*) <-- commit A
如果你使用rebase
,git 将倒带你的 HEAD 来提交 A 并应用按日期排序的所有提交
如果你使用merge
,git 会将两个分支合并为一个分支,在origin/head
顶部应用你的提交