为什么“git fetch origin branch:branch”仅适用于非当前分支?

时间:2015-03-13 09:24:59

标签: git

在处理功能分支时,我使用此Git命令将我的“develop”分支更新为最新状态,紧接在将我的功能分支与“develop”合并之前:

git fetch origin develop:develop

这可行,即本地“开发”指向与“origin / develop”相同的提交,并且处于最新状态。

但是,不知怎的,当签出“develop”分支时,此命令失败:

fatal: Refusing to fetch into current branch refs/heads/develop of non-bare repository
fatal: The remote end hung up unexpectedly

如果我知道为什么会发生这种情况,那将有助于我更好地理解Git。

2 个答案:

答案 0 :(得分:13)

错误讯息来自builtin/fetch.c#check_not_current_branch() 该功能一直追溯到commit 8ee5d73, Oct. 2008, git 1.6.0.4

评论很有启发性:

  

一些令人困惑的教程表明获取是一个好主意   用这样的东西进入当前的分支:

git fetch origin master:master
  

(或更糟糕的是:使用“pull”而不是“fetch”的相同命令行)   虽然存储你想要的东西可能是有意义的,但它通常是   当前分支为“master”时出现明显错误   只有在(不正确的)“git pull origin master:master”尝试通过将--update-head-ok提供给基础“git fetch”时才允许这样做,否则我们应该拒绝它,但是在某个地方我们失去了这种行为。

     

现在检查当前分支仅 在非裸机中执行   存储库,这是对原始行为的改进。

考虑到函数check_not_current_branch()called with

if (!update_head_ok)
        check_not_current_branch(ref_map);

这意味着git fetch -u origin develop:develop应该有用。

-u
--update-head-ok
  

默认情况下,git fetch拒绝更新与当前分支对应的头部。此标志禁用检查   这纯粹是为了git pullgit fetch进行通信的内部使用,除非您实施自己的瓷器,否则您不应该使用它。

即使您不应该使用该选项,它也会回答您的初始要求,使“git fetch origin branch:branch”能够在当前分支上运行。

关于此补丁的来源,follow the discussion there

  

虽然存储你想要的内容可能是有意义的

这是fetch部分:它存储来自更新后的origin/master的远程历史记录 但是当当前的本地分支也是master时,这尤其会被打破 如上所述in this answer

  

git fetch url side:master是当前分支时,我认为“master”   我们省略--update-head-ok已被删除   当前master测试失败。

     

它也无法更新工作目录并将离开   索引就像你要删除所有内容一样。

请参阅“git pull with refspec”作为示例 torek展示了一个例子:

  

假设我运行git fetch,它会引入两个新的提交,我将标记为CD
  C的父级是A,而DB之前的节点:

             C
            /
...--o--o--A   <-- master
            \
             o--B   <-- develop
              \
               D
  

此git fetch的输出将其列为:

  aaaaaaa..ccccccc  master     -> origin/master
+ bbbbbbb...ddddddd develop    -> origin/develop  (forced update)

如果当前分支 develop,那么强制更新可能就是您想要的。
但是如果您在键入develop on git fetch origin develop:develop,并且如果允许获取更新HEAD,那么...当前的索引将反映D ,不再是B 因此,在您的工作树中完成git diff会显示您的文件与D之间的差异,而不是之前的HEAD B

这很糟糕,因为您的初始git checkout develop创建了一个与B HEAD文件相同的工作树。
即使您的git status是干净的(没有任何类型的修改),如果git fetch origin develop:develop更新了HEAD(强制从B更新到D),git status现在会报告之前没有的差异获取。

这就是为什么默认情况下 git fetch拒绝更新与当前分支相对应的头

答案 1 :(得分:1)

git fetch仅从远程仓库中提取数据

  1. 它不会更新您的本地分支机构,即使是设置为跟踪远程分支机构
  2. 也是如此
  3. (因为1)它无法将远程分支提取到本地分支。它只是而不是 git fetch
  4. 根据man

      

    git fetch [&lt;选项&gt; ] [&lt;存储库&gt; [&lt; refspec&gt; ......]

    您可以像git fetch origin develop一样运行它,它只会更新您的远程分支参考origin/develop

    为了更新您的本地分支,您可以通过以下方式之一完成此操作:

    1. 明确指定应将哪个远程分支拉到哪个本地分支:git pull origin develop:develop
    2. 如果现在签出develop分支,并且设置为跟踪origin/develop,您可以运行git pull并确定要提取的内容

    3. <强>更新

      更多来自男人:

        

      使用显式分支和/或标记运行git fetch以获取时   命令行,例如git fetch origin master,给出了s   在命令行上确定要获取的内容(例如,在...中)   例子,这是master的简写:反过来意味着   “取得主分支,但我没有明确说出什么   远程跟踪分支从命令行“)更新它,和   示例命令将仅获取主分支。该   remote..fetch值确定哪个远程跟踪   分支,如果有的话,更新。当以这种方式使用时,   remote..fetch值在决定时没有任何影响   获取的内容(即,当该值不被用作refspecs时   命令行列出refspecs);他们只是用来决定在哪里   通过充当映射来存储被提取的引用。

      可以更新本地分支,但我仍然不明白为什么当你在要更新的分支上时不可能这样做。