Git pull与fetch-对于新获取的分支没有区别吗?

Git pull与fetch-对于新获取的分支没有区别吗?,git,git-pull,git-fetch,Git,Git Pull,Git Fetch,我一直在阅读gitpull和fetch命令以及它们之间的区别 我同意当我们在本地和远程都有主分支时,这两个命令之间存在差异,因此pull将集成我们获取的任何更改 但是,如果新的分支被推到了以前从未获取过的远程位置,该怎么办呢。如果我们只使用git-fetchvsgit-pull在获取/拉取这些分支之后,从git的角度来看,内部会有什么不同?如果我们只运行git fetch,新的分支是否没有集成 我想测试它,并做了以下工作: 我有一个远程存储库,我克隆了两次,让我们称这些本地reporepo 1和

我一直在阅读git
pull
fetch
命令以及它们之间的区别

我同意当我们在本地和远程都有主分支时,这两个命令之间存在差异,因此pull将集成我们获取的任何更改

但是,如果新的分支被推到了以前从未获取过的远程位置,该怎么办呢。如果我们只使用
git-fetch
vs
git-pull
在获取/拉取这些分支之后,从git的角度来看,内部会有什么不同?如果我们只运行
git fetch
,新的分支是否没有集成

我想测试它,并做了以下工作:

我有一个远程存储库,我克隆了两次,让我们称这些本地repo
repo 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

对于新分支,无论是I
pull
还是
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 ID
    H
    ,commit
    H
    指向一些更早的提交
    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