Git pull与fetch-对于新获取的分支没有区别吗?
我一直在阅读gitGit pull与fetch-对于新获取的分支没有区别吗?,git,git-pull,git-fetch,Git,Git Pull,Git Fetch,我一直在阅读gitpull和fetch命令以及它们之间的区别 我同意当我们在本地和远程都有主分支时,这两个命令之间存在差异,因此pull将集成我们获取的任何更改 但是,如果新的分支被推到了以前从未获取过的远程位置,该怎么办呢。如果我们只使用git-fetchvsgit-pull在获取/拉取这些分支之后,从git的角度来看,内部会有什么不同?如果我们只运行git fetch,新的分支是否没有集成 我想测试它,并做了以下工作: 我有一个远程存储库,我克隆了两次,让我们称这些本地reporepo 1和
pull
和fetch
命令以及它们之间的区别
我同意当我们在本地和远程都有主分支时,这两个命令之间存在差异,因此pull将集成我们获取的任何更改
但是,如果新的分支被推到了以前从未获取过的远程位置,该怎么办呢。如果我们只使用git-fetch
vsgit-pull
在获取/拉取这些分支之后,从git的角度来看,内部会有什么不同?如果我们只运行git fetch
,新的分支是否没有集成
我想测试它,并做了以下工作:
我有一个远程存储库,我克隆了两次,让我们称这些本地reporepo 1
和repo 2
-repo 1
将创建新的分支并将它们推到远程,而repo 2
将从远程拉取它们
我创建了一个新分支,并将其从repo1
推送到远程回购。然后我回到repo2
并使用git pull
。然后我运行了git branch-a
,看到新的分支是remotes/origin/side\u branch\u 1
。我还打开了.git/FETCH\u HEAD
文件,看到了该分支的行:不用于合并分支侧\u分支1
之后,在repo1
中,我创建并推送了side\u branch\u 2
,在repo2
中,我这次使用了git fetch
。然后我再次运行git branch-a
,看到新的分支是remotes/origin/side\u branch\u 2
。我还再次打开了.git/FETCH\u HEAD
文件,看到了该分支的行:不用于合并分支侧\u分支2
对于新分支,无论是Ipull
还是fetch
,都没有区别吗?如果是,那么与Git内部观点的区别是什么
因为侧分支\u 1
被标记为不用于合并
,即使它已被拉入。为什么?我错过了什么?TL;博士
git pull
表示运行git fetch
,然后运行第二个git命令。第一步-git fetch
-不会影响任何分支。它不会改变你正在做的任何事情,如果你正在做任何事情的话
第二步,默认运行git merge
,影响当前分支。它不会创建新的分支,因此一般来说,在其他Git中创建的任何新分支名称都不相关,除非您在Git pull
命令中显式命名它们
假设您在没有额外参数的情况下运行git pull
,运行git pull
的远程设备是与当前分支关联的远程设备,而用于重新基址或合并的提交是与当前分支上游关联的提交,由git fetch
步骤更新。Git对存储库中分支名称的上游设置施加了限制:特别是,如果Git还不知道另一个Git中存在某个名称,Git将不允许您将其设置为上游。因此,我们没有正确定义的“新”分支实际上并不相关
如果在git pull
命令行中添加更多参数,情况会变得更复杂
长的
对于新的分支,无论我拉还是取,都没有区别吗
Git pull始终意味着:运行Git fetch
,然后运行第二个Git命令。所以很明显,这些是不同的,因为git fetch
不运行第二个git命令。在这里,fetch步骤是否看到Git以前没有看到的分支名称无关紧要
如果是,那么与Git内部的观点有什么区别
在这里,您需要密切了解Git的实际工作原理。为了保持这个答案的简短(ish),我会说,请参阅我的许多其他答案以了解更多细节,但是:
- 每个提交都有一个唯一的散列ID,这是一个长而随机的提交名称,
git log
向您显示:commit 1c56d6f57adebf2a0ac910ca62a940dc7820bb68
- 每次提交都会存储所有文件的快照。每次提交中的文件都是一种特殊的、只读的、仅Git的压缩格式,并且一直处于冻结状态
- 每个提交还存储一些元数据:关于提交的信息不是与提交一起保存的文件,而是包含诸如谁进行了提交、何时以及为什么(他们的日志消息)之类的内容。在该元数据中,每个提交存储其直接父提交的哈希ID(对于大多数提交;有些存储两个或多个父提交,这些是合并提交,并且至少有一个是存储库中的第一个提交,因此没有父提交)
- 像
master
这样的分支名称只保存链中最后一次提交的原始散列ID。因此,如果您有一个名为master
的分支和一些提交,master
保存一些hash IDH
,commitH
指向一些更早的提交G
,它指向更早的提交F
,依此类推:
... <-F <-G <-H <--master
在上面的六个步骤git clone
序列中,步骤5实际上是git fetch
。然而,gitfetch
所做的不是获取每个提交,而是与另一个git对话,看看它们有哪些提交,而您没有。在初始克隆过程中,您没有任何提交,因此这只是他们的所有提交。后来,这是他们的新产品
当您稍后运行git fetch
时,如果他们仍然有master
标识提交H
和开发标识提交J
,您的git将在您的存储库中查找,使用
...--F--G--H--I <-- master
...--G--H <-- master, origin/master
\
I--J <-- origin/develop
...--G--H <-- master, origin/master
\
I--J <-- origin/develop
\
K
...--G--H <-- master, origin/master
\
I--J--K <-- origin/develop
...--G--H <-- master, origin/master
\
I--J <-- origin/develop
\
K [no name: hard to find!]
...--G--H <-- dave, master, origin/master
\
I--J--K <-- origin/develop
...--G--H <-- dave (HEAD), master, origin/master
\
I--J--K <-- origin/develop
L <-- dave (HEAD)
/
...--G--H <-- master, origin/master
\
I--J--K <-- origin/develop
L <-- dave (HEAD)
/
...--G--H <-- master
\
M <-- origin/master
git checkout master; git merge origin/master
L <-- dave
/
...--G--H--M <-- master (HEAD), origin/master
git pull # no arguments at all
git pull origin # just a remote
git pull origin master # a remote and a branch name *on the remote*
git fetch
git merge
merge branch origin/dave into dave
git pull
merge branch dave of <url> into dave