git fetch和git fetch origin master之间的差异

 鉴佳熙萍 发布于 2023-01-29 16:21

我正在进行获取/合并,并想知道做之间是否有任何区别

git fetch

git fetch origin master

remote repository在GitHub上没有任何其他分支和原点.

当我做:

git fetch origin master
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From github.com:XXXXXXXXXXXXXXX
 * branch            master     -> FETCH_HEAD

只是:

git fetch
From github.com:XXXXXXXXXXXXXXX
   531d466..aaf6df0  master     -> origin/master

请注意,主人指向不同的东西; 在一个案例FETCH_HEAD和其他情况下,origin/master?他们不一样吗?

1 个回答
  • 这是"TL; DR"版本(它掩盖了很多特殊情况):git fetch 总是更新FETCH_HEAD,在不同的情况下有多行.它有时会更新"远程分支",这些分支是全名开头的引用refs/remotes/.剩下的主要是"有时",它根据给出的参数数量git fetch和git版本而有所不同.


    我有机会测试这个.让我们区分三种情况,所有情况都假定在git fetch没有额外选项的情况下运行,-a甚至是--all.让我们也排除的怪异变种git fetch,如直接使用URL,或者insteadOf在列出的条目,或文件.git/remotes.git/branches.(我承认我只是猜测,但我认为这些是从[remote "name"]条目进入git的配置文件前几天留下来的.编辑,2019:结果证明是正确的.)

      git fetch,没有其他论点.

      Git确定你当前的分支(以通常的方式,通过阅读HEAD,但你当然可以看到它是什么git branchgit status).然后它为该分支查找命名它的配置条目remote.例如,假设您在分支机构dummy并且.git/config(在其他条目中):

      [branch "dummy"]
          remote = remote-X
      

      在这种情况下git fetch相当于git fetch remote-X.在那之后,这相当于案例2,即:

      git fetch remote (并没有更多的论据).

      这次Git不看你当前的分支.要使用的遥控器是命令行上给出的遥控器.它确实在寻找给定遥控器的配置部分.假设您正在使用remote-X:在这种情况下,它会查找:

      [remote "remote-X"]
          url = ...
      

      如果该部分不存在,或者没有url =条目,则会收到错误:fatal: 'remote-X' does not appear to be a git repository.1 否则提供URL,并git fetch尝试连接到那里.假设它可以连接......

      通常还有至少一个配置条目,可能更多,读取:

          fetch = +refs/heads/*:refs/remotes/remote-X/*
      

      (遥控器的名称在这里是硬编码的).假设有...

      接下来,git fetch向遥控器询问它有什么引用(主要是分支和标签,虽然你可以获得所有引用,但大多数人只关心分支和标签).你可以自己做同样的事情git ls-remote remote-X,这会溢出这样的东西:

      676699a0e0cdfd97521f3524c763222f1c30a094        HEAD
      222c4dd303570d096f0346c3cd1dff6ea2c84f83        refs/heads/branch
      676699a0e0cdfd97521f3524c763222f1c30a094        refs/heads/master
      

      HEADref 的处理并不完全一致(我已经看到它表现得很奇怪)但通常在这里它会被丢弃.2 其余分支根据fetch =refspec 重命名和更新.(如果有多个fetch =refspec,它们会根据所有这些重新命名和更新.例如,这主要用于将refs/notes/自己的"远程标签"名称空间带入或制作refs/rtags/.)

      在这种情况下,取拿过来需要两个分支的任何对象branchmaster,和更新(本地)"远程分支"的名称,refs/remotes/remote-X/branchrefs/remotes/remote-X/master根据需要.对于每个更新的,fetch打印一行如下:

         22b38d1..676699a  master     -> remote-X/master
      

      如果fetch =缺少线条,你会得到一些完全不同的东西.输出将显示为:

       * branch            HEAD       -> FETCH_HEAD
      

      在这种情况下,就好像(缺失的)fetch =线在那里并且包含fetch = HEAD.

      git fetch remote refspec(该refspec部分是一个或多个refspecs,实际上,如下所述).

      这与情况2类似,只是这次,"refspecs"在命令行上提供,而不是从fetch =远程的配置条目提供.但是,这里的获取行为非常不同.


    在这种特殊情况下,让我们暂停片刻并正确描述refspec.(Refspec也会出现git push但是,和git一样,实现细节会泄露出来,并且它们的工作方式略有不同.)refspec有一个可选的前导加号(+)符号,我在这里忽略它; 3然后两个部分,用冒号(:)分隔.两者通常只是一个分支名称,但在分支名称的情况下,您可以(和fetch =行)拼出"完整"引用名称.refs/heads/branch

    对于获取操作,左侧的名称是远程本身的名称(例如,如图所示git ls-remote).右侧的名称是要在本地git存储库中存储/更新的名称.作为一种特殊情况,您可以*在斜杠之后使用星号()作为最后一个组件,例如refs/heads/*,在这种情况下,左侧匹配的部分将替换为右侧.因此refs/heads/*:refs/remotes/remote-X/*导致refs/heads/master(如在遥控器上看到的那样git ls-remote)refs/remotes/remote-X/master(在本地存储库中看到,并以较短的形式,->在行的右侧git fetch打印).

    如果你不把在做:,不过,git fetch有没有好的地方放的副本"的分支那边".让我们说它将带来遥控器refs/heads/master(遥控器上的master分支).如果您在分支中拥有自己的提交,而不是更新您 - refs/heads/master显然会很糟糕master- 只需将更新转储到FETCH_HEAD.

    在这里,事情变得尤为突出.假设你运行git fetch remote-X master branch,即给出至少一个,也许几个refspecs,但都没有冒号.

    如果你的git版本低于1.8.4,那么更新只会进入FETCH_HEAD.如果你给了两个无冒号的refspecs,FETCH_HEAD现在包含行:

    676699a0e0cdfd97521f3524c763222f1c30a094        branch 'master' of ...
    222c4dd303570d096f0346c3cd1dff6ea2c84f83        branch 'branch' of ...
    

    如果你的Git版本是1.8.4或更高版本,更新去那里,这部分是不变的,但是,抓取借此机会来记录这些部门永久,以正确的远程分支机构通过给出fetch =的远程线路.

    但是,无论出于何种原因,git fetch只打印出->实际更新的远程分支的更新行.由于它始终记录所有更新FETCH_HEAD,因此它始终在此处打印分支名称.

    (另一个问题,除了需要git的1.8.4或更高版本,以获得更新的远程分支机构是那些fetch =必须存在线.如果他们不这样做,有没有映射,通过该取知道重命名refs/heads/*refs/remotes/remote-X/*.)

    换句话说,git 1.8.4和更新版确实"机会性地更新"所有远程分支.较旧版本的git可以执行此操作git push,因此之前一直不一致.即使在git 1.8.4中它仍然不一致git pull,我认为(虽然我没有git pull足够注意:-)); 应该在git 1.9中修复.

    现在让我们回到和之间的区别.git fetch remotegit fetch remote refspec ...


    如果你运行,即省略所有refspecs,fetch会像往常一样回到行.获取操作将从线路中获取所有引用. 所有这些都进入了,但是这次它们被标记为"not-for-merge"(带有标签,我将其更改为一个空格以更好地适应网页):git fetch remotefetch =fetchFETCH_HEAD

    676699a0e0cdfd97521f3524c763222f1c30a094 not-for-merge branch ...
    

    不是分支的refs/notes/引用,例如引用的引用,而是读取:

    f07cf14302eab6ca614612591e55f7340708a61b not-for-merge 'refs/notes/commits' ...
    

    同时,如有必要,可以更新远程分支引用,并通过消息告知您哪些已更新:

       22b38d1..676699a  master     -> remote-X/master
    

    同样,所有内容都被转储FETCH_HEAD,但只是更新和打印"需要更新"的内容.新的分支机构打印出"新分支",旧的分支机构打印出新的SHA-1缩写,master -> remote-X/master如上所述.

    另一方面,如果你运行,fetch 只会带来指定的refspecs.这些所有进入像往常一样,6但这一次他们每个人都被打印出来.然后,如果你的git是1.8.4或更新,那么任何可以映射(通过合理的行)并需要更新的引用更新也会更新和打印:git fetch remote refspec ...FETCH_HEADfetch =

     * branch            master     -> FETCH_HEAD
     * branch            branch     -> FETCH_HEAD
       22b38d1..676699a  master     -> remote-X/master
    

    如果你的git版本早于1.8.4,那么remote-X/master这种情况下不会发生更新- 或者更确切地说,除非你的命令行refspec之一是refs/heads/master:refs/remotes/remote-X/master,或者refs/heads/*:refs/remotes/remote-X/*是那些带有加号的变体,否则它不会发生.在前面的迹象.


    1这不是一个很好的错误信息.这个remote-X论点从来不应该是一个"存储库",它应该是一个"远程"!如果git在这里说了更多信息,那可能会很好.

    2 git远程协议中存在一个缺陷:HEAD通常是间接引用,因为它是远程的当前分支,所以它应该以"ref:refs/heads/master"为例,但它取而代之的是完全解决了SHA-1.至少有一个git命令(git clone)尝试通过将此SHA-1与每个分支头的SHA-1进行比较来"猜测"远程上的当前分支.例如,在上面,很明显遥控器是"在分支主机上",HEAD并且refs/heads/master具有相同的SHA-1.但是,如果多个分支名称指向同一个提交,并且HEAD匹配该commit-ID,则无法确定哪个分支(如果有)HEAD已打开.远程也可能处于"分离的HEAD"状态,在这种情况下,它不在任何分支上,无论SHA-1值如何.

    编辑,2019:在Git版本1.8.4.3中修复了此错误.只要你在克隆的机器上和你自己的机器上的两个Git版本都是1.8.4.3或更新版本,Git再也不用猜测了.

    3加号表示"接受强制更新",即对于分支采用"只有快进" 4规则拒绝的更新,或者对标签"永不更改标签" 5.

    4当提交定向非循环图中的旧SHA-1是新SHA-1的祖先时,标签的"快进"可以从旧的SHA-1更改为新的SHA-1.

    5 "永不改变标签"规则是git 1.8.2中的新规则.如果您的git比那个旧,git也使用标签的分支规则,允许快速转发而不"强制更新".

    6但没有not-for-merge这个时间.基本上,当你提供无冒号的refspecs时,git fetch假定它们是"for merge"并将它们放入FETCH_HEAD以便git merge FETCH_HEAD找到它们.(我没有测试过非分支引用会发生什么.)

    2023-01-29 16:23 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有