Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带refspec的Git pull_Git - Fatal编程技术网

带refspec的Git pull

带refspec的Git pull,git,Git,我读了这篇文章,现在我对git pull如何与refpec一起工作产生了疑问: Step 1 : I am on branchA. Step 2 : I do `git pull origin branchB:branchC` . Step 3: I notice : a) commits from branchB on remote comes and update `remotes/origin/branchC` b) Then a merge happened. `branchC

我读了这篇文章,现在我对git pull如何与refpec一起工作产生了疑问:

Step 1 : I am on branchA.

Step 2 : I do `git pull origin branchB:branchC` .

Step 3: I notice : 

a) commits from branchB on remote comes and update `remotes/origin/branchC`

b) Then a merge happened. `branchC` was updated with `remotes/origin/branchC`

c) The `branchC` was merged into `branchA`.

现在,我很困惑,既然git pull=git fetch+git merge,那么2个合并是如何发生的呢?步骤b)和步骤c)都是合并。

步骤2不是真正的合并,而是合并。快进是非当前(即当前未签出)分支唯一可能的合并类型。如果无法实现快速转发,git将中止
获取/拉取
;在这种情况下,您可以执行真正的合并(签出branchC并运行
git pull origin branchB
),或者执行强制更新(
git fetch origin+branchB:branchC
),从而在branchC的头部丢失本地提交。

第2步不是真正的合并,而是一个错误。快进是非当前(即当前未签出)分支唯一可能的合并类型。如果无法实现快速转发,git将中止
获取/拉取
;在这种情况下,您可以执行真正的合并(签出branch并运行
git pull origin branchB
),或者执行强制更新(
git fetch origin+branchB:branchC
),从而在branchC的头部丢失本地提交。

是正确的。将
git pull
命令分解为两个组件:

  • git获取来源branchB:branchC
    。在相同的设置上运行此命令,即,将
    branchC
    设置为指向在
    git pull
    命令之前指向的提交

  • git合并
    。实际哈希ID取自
    .git/FETCH\u HEAD
    ,其中
    git FETCH
    保留它。在相同的设置上运行此命令,将
    branchA
    设置为指向在
    git pull
    命令之前指向的提交

  • 请注意,步骤2,即
    git合并
    ,对引用
    branchC
    没有影响。它确实对当前分支名称有一些影响,即,
    refs/heads/branchA
    。因为它运行的是
    gitmerge
    ,所以它可以进行快进合并,或者真正的合并,或者什么都不做

    让我们深入研究
    fetch
    步骤,这确实是一个更有趣,或者至少更具挑战性的步骤

    git-ls-remote
    在运行
    git fetch origin branchB:branchC
    之前,请运行
    git ls remote origin
    。下面是我在Git存储库上为Git运行它时得到的结果(有很多片段被截断):

    您可以看到,他们的Git为我的Git提供了一长串引用名和散列ID

    我的Git可以从中选择它喜欢的名称和/或ID,然后进入下一阶段的
    Git fetch
    :询问他们可以给我哪些哈希ID,例如提交
    e144d126d74f5d2702870ca9423743102eec6fcd
    (他们的
    主机的哈希ID
    )。如果我告诉Git将它们的
    master
    refs/heads/master
    作为refspec的左侧,我的Git就会这样做,因为这些名称字符串与它们的
    refs/heads/master
    匹配

    (如果没有refspec,我的Git将请求所有分支。标记更为复杂:
    --tags
    让我的Git获取所有,
    --no tags
    让我的Git不获取任何分支,但在这两者之间,在
    Git fetch
    中有一些可怕的扭曲代码)

    在任何情况下,他们都会提供一些散列,my Git会说它是否需要或有其他散列,他们的Git使用他们的
    Git rev list
    为提交、树、blob和/或带注释的标记对象构造一组散列ID,以放入所谓的瘦包中。在这个
    git fetch
    阶段,您会看到关于远程计数和压缩对象的消息

    git获取来源
    现在让我运行一个实际的
    git fetch

    $ git fetch origin
    remote: Counting objects: 2146, done.
    remote: Compressing objects: 100% (774/774), done.
    remote: Total 2146 (delta 1850), reused 1649 (delta 1372)
    
    最终,他们的Git完成打包所有要发送的对象,并发送这些对象。我的Git收到它们:

    Receiving objects: 100% (2146/2146), 691.50 KiB | 3.88 MiB/s, done.
    
    My Git修复了瘦包(
    Git index pack--fix thin
    ),使其成为一个可以在My
    .Git/objects/pack
    目录下运行的正常包:

    Resolving deltas: 100% (1850/1850), completed with 339 local objects.
    
    最后,我们最感兴趣的部分是获取:

    From [url]
       ccdcbd54c..e144d126d  master     -> origin/master
       1526ddbba..093e983b0  next       -> origin/next
     + 8b97ca562...005c16f6a pu         -> origin/pu  (forced update)
       7ae8ee0ce..7a516be37  todo       -> origin/todo
    
    ->
    箭头左侧的名称是它们的名称;右边的名字是我Git的名字。因为我只运行了
    git fetch origin
    (没有refspec),所以我的git使用了默认的refspec:

    $ git config --get remote.origin.fetch
    +refs/heads/*:refs/remotes/origin/*
    
    就好像我写了:

    $ git fetch origin '+refs/heads/*:refs/remotes/origin/*'
    
    它使用完全限定的refspec,而不是像
    branchB:branchC
    这样的部分名称。此特定语法还使用glob模式,如
    *
    字符。从技术上讲,这些都不是全局的,因为它们只是字符串而不是文件名,右边有一个
    *
    ,但原理类似:我要求我的Git匹配以
    refs/heads/
    开头的每个名称,并将它们复制到我自己的存储库中,名称以
    refs/remotes/origin/
    开头

    refs/heads/
    名称空间是我的Git的所有分支名称所在的位置。
    refs/remotes/
    名称空间是my Git的所有远程跟踪名称所在的位置,
    refs/remotes/origin/
    是my Git和我放置远程跟踪名称的位置,这些名称与我们在Git的
    origin
    中找到的分支名称相对应。前面的前导加号
    +
    设置强制标志,就好像我运行了
    git fetch--force

    参考名称更新 下一步需要查看提交图,即Git存储库中所有提交的有向无环图或DAG。在本例中,由于新的包文件已经集成,这包括了我刚刚通过git fetch添加的所有新对象,因此我从它们的git中获得了新的提交(以及与之相关的任何树和blob)

    每个对象都有一个唯一的哈希ID,但这些ID太难直接使用。我喜欢在StackOverflow上从左到右用文本绘制图形,并使用round
    o
    s或si
    $ git fetch origin '+refs/heads/*:refs/remotes/origin/*'
    
    ...--o--o--A   <-- master
                \
                 o--B   <-- develop
    
    ...--o--o--A   <-- master, origin/master
                \
                 o--B   <-- develop, origin/develop
    
                 C
                /
    ...--o--o--A   <-- master
                \
                 o--B   <-- develop
                  \
                   D
    
                 C   <-- origin/master
                /
    ...--o--o--A   <-- master
                \
                 o--B   <-- develop
                  \
                   D   <-- origin/develop
    
       aaaaaaa..ccccccc  master     -> origin/master
     + bbbbbbb...ddddddd develop    -> origin/develop  (forced update)
    
    git merge <commit-specifier>
    
    Step 1 : I am on branchA.
    
    Step 2 : I do `git pull origin branchB:branchC` .
    
    Step 3: I notice : 
    
    a) commits from branchB on remote comes and update `refs/heads/branchC`
    
    b) Then based on `remote.origin.fetch` was used to try to update `remotes/origin/branchB` on our local.
    
    [ Notice that no attempts will be made to update `remotes/origin/branchC`]
    
    c) The `branchC` was merged into `branchA`.