git - 远程 Git 分支不可见

标签 git

git pull 之后,我总是能够通过执行 git branch 来查看所有分支。
现在(出于某种原因)运行 git branch 向我展示了 master 和另一个我正在积极工作的分支。git remote show origin 向我展示了所有分支。如果我对其中一个执行 git checkout,它会在本地 pull 下分支并交换到它。之后,当我运行 git branch 时它是可见的
问题
当我运行 git branch 时,如何让远程分支再次显示?
注意:这只是一个视觉问题 - 我仍然可以毫无问题地访问我的远程分支,我只是想知道为什么当我执行 git 分支时它们没有像通常那样显示

最佳答案

TL;DR:只需使用 git branch -rgit branch -a(在 git fetch 之后更新)。完全不清楚为什么您会看到没有这些标志的远程跟踪分支(也许您一直在使用自动显示它们的 GUI?)。

但是,您的问题中至少存在一个小的误解——这并不奇怪; Git 的这个特殊部分起初很棘手。

事实上,这个问题涉及三组分支名称。

git remote show origin shows me all branches.



不完全是。让我们稍微备份一下,并定义两个分支集合(或类,或任何您喜欢将它们分组的词)。 Git 提供:
  • 您的常规、普通、本地分支机构。这些是 git branch 在不带参数和标志的情况下显示的内容。
    $ git branch
      diff-merge-base
    * master
      precious
      stash-exp
    

    “分支”一词通常表示其中之一:一个名称,当输入 git rev-parse 时,解析为提交 ID:
    $ git rev-parse diff-merge-base
    2d0cc5001c1a88995727521d4ef77f7a4acc4e14
    

    并且其全名以 refs/heads/ 开头:
    $ git rev-parse --symbolic-full-name diff-merge-base
    refs/heads/diff-merge-base
    
  • 您的远程跟踪分支。这些是 git branch -r 显示的内容:
    $ git branch -r
      origin/HEAD -> origin/master
      origin/maint
      origin/master
      origin/next
      origin/pu
      origin/todo
    

  • 它们之间的主要区别在于,您的本地分支是您可以随意操作的名称,而您的远程跟踪分支是您的名称,Git 会自动从属于其他东西。您可以自己操作它们,但这没有利润,因为它们的目的是记住一些其他 Git 的分支名称(以及相应的 SHA-1 值)。

    请注意,将远程跟踪分支名称提供给 git rev-parse 也是有效的,您也可以获得它的 symbolic-full-name :这只是以 refs/remotes/ 开头,后跟远程名称,然后是本地名称,如果您看到的是 Git在 Remote 上运行 。因此:
    $ git rev-parse --symbolic-full-name origin/master
    refs/remotes/origin/master
    

    意味着我的 Git 的 origin/master 是我的 Git 对 master 的含义的内存,在 origin 上,我的 Git 上次调用 0x2518122313,4314 和 .1 和..
    origin(有时)实际上调用了远程Git

    请记住,每次获取或推送提交时,都会涉及两个(有时甚至更多)Git 版本控制数据库。所以你可以查看你的信息,或者你可以让你的 Git 通过互联网电话调用他们的 Git,并查询他们的信息。他们也可能拥有自己的本地分支机构,甚至远程跟踪分支机构。 (通常,对于这种情况,他们只有本地分支机构。)

    出于说明目的,让我删除我自己的一个远程跟踪分支(这是非常无害的,因为我稍后将运行 git remote 来恢复它):
    $ git branch -r -d origin/pu
    Deleted remote-tracking branch origin/pu (was 7c79844).
    

    现在,如果我运行 git fetch 我将不再有 git branch -r :我的 Git 不再将其作为远程跟踪分支。但是他们的 Git 在 origin/pu 上仍然有一个名为 origin 的本地分支,所以:
    $ git remote show origin
    * remote origin
      Fetch URL: git://git.kernel.org/pub/scm/git/git.git
      Push  URL: git://git.kernel.org/pub/scm/git/git.git
      HEAD branch: master
      Remote branches:
        maint  tracked
        master tracked
        next   tracked
        pu     new (next fetch will store in remotes/origin)
        todo   tracked
      Local branches configured for 'git pull':
        master    merges with remote master
        stash-exp merges with remote master
      Local ref configured for 'git push':
        master pushes to master (local out of date)
    

    当我运行 pu 时,我的 Git 调用他们的 Git(这恰好是 Git 的 Git 存储库的副本——现在 github.com 上还有另一个可能更合适)并从他们那里获取所有分支的列表.我已经将其中大部分作为我自己的“远程跟踪分支”,但我删除了 git remote show origin ,因此它显示为"new"。

    一个类似的命令 pu 也调用另一个 Git 并查询它,但会显示更多信息:它会显示每个分支的提交哈希(以及每个标签的对象哈希)。有很多标签,所以让我将其限制为一个分支:
    $ git ls-remote origin master
    e05806da9ec4aff8adfed142ab2a2b3b02e33c8c        refs/heads/master
    

    在这两种情况下,你的 Git(或我的 Git)调用他们的 Git 并从他们那里获取信息,但它只是显示它,而不是保存它。为了保存信息,我们必须运行 git ls-remote 。我有一段时间没有运行它,所以:
    $ git fetch origin
    remote: Counting objects: 2064, done.
    remote: Compressing objects: 100% (1294/1294), done.
    remote: Total 2064 (delta 1383), reused 1118 (delta 767)
    Receiving objects: 100% (2064/2064), 2.12 MiB | 2.29 MiB/s, done.
    Resolving deltas: 100% (1383/1383), done.
    From git://git.kernel.org/pub/scm/git/git
       de2efeb..e05806d  master     -> origin/master
       3074f94..c69c2f5  next       -> origin/next
     * [new branch]      pu         -> origin/pu
       1a46792..2135c1c  todo       -> origin/todo
    

    这个 git fetchgit fetchgit remote show 做了同样的事情,但也做了更多的事情:它收集了我需要完成我的存储库的对象,然后更新我的远程跟踪分支名称以对应于它们的存储库中的分支名称。

    这就是为什么我重新获得了 git ls-remote :他们仍然有一个 origin/pu ,而我丢弃了我的,所以我获得了他们的,现在又拥有了。

    这也是我更新除 pu 之外的所有其他内容的原因:时间已经足够长,它们都已更新。我的 maint 过去指的是提交 origin/master ,但现在它指的是 de2efeb ,这与我们在上面运行 0x25181223134314 时看到的 ID 相同(这意味着他们没有在我输入所有内容的几分钟内更新他们的 e05806d。想象一下,数十亿纳秒没有更新!:-))

    (请注意, git ls-remote 跳过了 master 的调用,只是向您展示了您的 Git 记录的内容。其他几个 git remote show -n origin 命令也可以在本地运行;请参阅文档了解具体信息。)

    概括

    回顾一下,这里涉及三组分支名称:
  • 您本地的分支机构;
  • 你的远程跟踪分支;和
  • 他们的分支(在远程 Git 中)。

  • 大多数情况下,最后一组分支名称无关紧要。大多数时候,您在自己的存储库中工作。只涉及一个 Git,它是你的。他们的 Git 有自己的分支,就在图片之外。

    但有时——啊,这样的时候!——有时,你必须将你的 Git 连接到另一个 Git。现在他们的名字很重要!这里真正棘手的事情是你的名字根本不需要匹配他们的名字。您的 origin 必须与它们的 git remote 相对应并没有硬性的理由——但是您的 Git 会将它们的 master 复制到您的 master 中,如果它们的名称与您的大脑名称匹配,那么它会保存很多名称。您可以解决这个问题(以多种不同的方式),但在您遇到真正需要它的情况之前不要这样做(多个 Remote 使用冲突的分支名称——这几乎从未发生过)。
    master 怎么样?

    您在上面指出:

    If I do a git checkout on one of [their branch names that I don't see in git branch output], it pulls the branch down locally and swaps to it.



    假设您运行了 origin/master(而不是 git checkout blah)并看到了一个名为 git branch -r 的分支。假设您还没有名为 git remote show origin 的(本地)分支。你跑:
    $ git checkout zorg
    

    你的 Git 说:
    Branch zorg set up to track remote branch zorg from origin.
    Switched to a new branch 'zorg'
    

    你的 Git 没有在这里“pull 下”任何东西。它所做的是创建一个新的本地分支名称 origin/zorg ,指向与 zorg 相同的提交——同样丑陋的 SHA-1 哈希 ID。该提交已经在您的存储库中,随时可以 check out ,实际上您可以这样做:
    $ git checkout origin/zorg
    

    看看它——但这会给你一个 Git 所谓的“分离的 HEAD”。

    这里发生的事情是,在 Git 中,分支名称只是一个指向特定提交的可移动指针。 zorg 命令以这种方式使用时,会做两件事:检查一个特定的提交(进入工作树),以及切换 Git 对“当前分支名称”的概念。当您 origin/zorg 一个现有的、本地的、普通的分支名称时,Git 会检查有问题的一个提交,并将您置于“分支”上,如 git checkout 会说:
    $ git status
    On branch master
    

    当你 git checkout 任何提交不是一个简单的分支名称时,Git 仍然会检查一次提交,但会让你离开任何分支,即给你一个“分离的 HEAD”。

    我们从上面知道 git status 是(现在)提交 git checkout ,所以:
    $ git checkout origin/master
    

    要么:
    $ git checkout e05806da9ec4aff8adfed142ab2a2b3b02e33c8c
    

    两者都做同样的事情。由于 origin/master 不是本地分支,我最终得到:
    $ git status
    HEAD detached at e05806d
    

    (或有时 e05806da9ec4aff8adfed142ab2a2b3b02e33c8c )。

    因此, origin/master 所做的是尝试将您给它的名称转换为分支名称。如果失败, HEAD detached at origin/master 有这个额外的内置功能:它搜索所有远程跟踪分支,看看是否有一个“主要匹配”名称的分支。因此 git checkout 检查名为 git checkout 的本地分支,但未能找到它,然后在所有远程跟踪分支中搜索与 git checkout zorg 匹配的分支。实际上只有一个——zorg——所以这会触发特殊情况代码。

    特殊情况代码简单地实现了“创建新的本地分支设置以跟踪相应的远程跟踪分支”。也就是说,创建一个本地 zorg ,其上游(Git 现在称之为这些东西)设置为 origin/zorg

    请注意,要使其正常工作,必须恰好有一个合适的远程跟踪分支。如果我根本没有 zorg,这将失败——如果我同时拥有 origin/zorgorigin/zorg ,其中 origin/zorg 是否也会失败,因为我的存储库是否会像另一个 2231 这样的 Git 指向第三个远程 0x2131,本地 thirdrepo/zorg 应该有 thirdrepoorigin 作为其上游。

    大多数情况下,您只有一个 Remote ,名为 zorg 。因此,只要您将 origin/zorg 的所有分支都保存为您自己的 Git 的远程跟踪分支内存,您就可以只使用 thirdrepo/zorg 这些名称来让您的 Git 创建它们。但有时你会发现你必须先运行 origin 才能更新你的远程跟踪分支。

    关于git - 远程 Git 分支不可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41406903/

    相关文章:

    git - 列出 GIT 历史中给定行号的所有版本

    git clone 永远不会完成

    Git:本地跟踪,添加新分支?

    git - 如何在保留历史记录的同时将文件从一个 git 存储库移动到另一个

    git - 从 Github 更新克隆的存储库

    git - git 中的 svnadmin 转储

    git - 如何计算 Git 存储库中特定作者更改的总行数?

    git - rebase 后如何更新提交消息中的 SHA1?

    git 预提交钩子(Hook) : trigger only to actual to be commited code?

    git - Mercurial 和 Git 自定义 SSH key 位置