我对git pull
,git fetch
+ git merge
和git rebase
感到困惑。
他们似乎都做了相同的功能,然后他们之间的差异特别是在提交日志方面。
如果远程和本地分支都有变化,那么在所有三种情况下,其提交将首先出现。
答案 0 :(得分:3)
正如您在问题中所暗示的那样,最令人困惑的部分是了解与远程仓库相比对本地仓库的影响,以及部分对使用远程仓库的其他人的影响。
首先,正如其他答案所示,git pull
与git fetch
+ git merge
完全相同。这两个命令都是从本地repo pull / fetching +从远程到本地repo的合并的角度出发的。这发生在您在本地远程检出本地分支的同一分支上。我先讨论那些,然后压扁和重新定位。
假设您已在本地签出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
只会跳转到匹配{ {1}})。
此时,如果你在其他人向遥控器推送任何其他内容之前推送,那么你的新合并提交将被推送到你的单独提交(它们看起来像一个单独的,未命名的分支),以及原始的远程提交,加上最后的新合并提交。
你确实问过这个问题,但如果你与--squash合并,那么它将添加合并提交,但删除其他本地提交,以便历史记录中没有额外的未命名分支。有些人更喜欢这个,因为它更干净",而有些人更喜欢看所有的历史记录(即代码分歧以及合并提交中的确切内容)。
当您进行rebase时,您基本上会进行所有本地提交,并将它们重播到远程主分支上,因此它们不会显示为单独的分支。这样可以保持当地历史的完整性,而不会显示代码分歧,这也是有些人更喜欢并认为它更加干净"。这与历史是否重要等无关。
如果其他人忍者犯了(嗯,刚刚犯了...),因为你抓了,那么你的推动就会失败。你可以使用origin/master
,但是你会完全覆盖他们的提交,所以这通常是不赞成的,因为它会为其他人创造各种各样的问题。在这种情况下,如果每个人都同意他的提交应该先进行,那么你需要再次完成这个过程(如果没有冲突,那么这很容易),但总的来说,团队需要制定政策在这种类型的事情上,一旦团队变得足够大,通常会使用拉取请求和评论来以更有序的方式管理推送。
通过将您当地的主分支机构视为与遥控器分开的一个分支,可能很容易理解发生了什么 - 这基本上是从Git的角度来看的。
事实上,在我看来,在你准备将某些东西合并到一个远程分支之前,你总是更好地在你自己的独立分支中工作。 Git让它变得如此简单,快速,轻松,拥有一个单独的分支,这就是我的工作。
答案 1 :(得分:2)
使用谷歌。 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 进入< / strong> it):
c1-c2-c3<-A
\-c4-c5<-B
变为
c1-c4-c5-c2-c3<-A
^
B
我们在这里做的是对A(我们所在的)进行不同的提交并将它们应用于B的顶部,基本上去除了分支结构。永远不会有像“合并提交”那样的“rebase提交”。这与远程控制无关,除了git pull --rebase
将获取然后在远程变更之上重新设置本地更改,而不是将远程变更合并到本地提交中。再次,google.com或git-scm.com/docs。
答案 2 :(得分:0)
来自git文档
git pull
将来自远程存储库的更改合并到当前分支中。在默认模式下,git pull
是git fetch
的缩写,后跟git merge FETCH_HEAD
rebase
在另一个基本提示之上重新提交提交。
所以你git rebase FETCH_HEAD
编辑后可以fetch
所以,如果你有
(*) <-- HEAD
|
(*) <-- commit B
\ (*) <-- origin/master
\ /
(*) <-- commit A
如果您使用rebase
,git将回退您的HEAD以提交A并应用按日期排序的所有提交
如果您使用merge
,git会将两个分支合并为一个分支,在origin/head