Git 跟踪分支

Git tracking branches

我在本地创建了一个存储库并将所有更改推送到 github。 后来我创建了一个名为 "v2" 的新分支 ("git branch v2") 并做了一些修改,并将该分支也推到了 github。 稍后当我执行命令 "git remote show origin" 时,我得到以下输出。

  * remote origin
  Fetch URL: https://github.com/mayuran19/se24_P03.git
  Push  URL: https://github.com/mayuran19/se24_P03.git
  HEAD branch: master
  Remote branches:
    master tracked
    v2     tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local refs configured for 'git push':
    master pushes to master (local out of date)
    v2     pushes to v2     (local out of date)

但是当我执行命令时 "git branch -vv" 它显示分支 "v2" 不是跟踪分支。

  master bad4ed9 [origin/master] Correct name
  * v2     6ec46b0 Data files

我的问题是,为什么 v2 分支没有显示为跟踪分支,即使远程分支在 github 中可用并且我能够拉和推这个分支?

命令"git branch -a"的输出显示如下输出

  master
* v2
  remotes/origin/master
  remotes/origin/v2

但不显示本地和远程分支之间的映射。

首先我们需要一些定义。

一个local分支(也简称为"a branch",没有修饰符)是一个全名以refs/heads/开头的分支。使用 git branch 时,您将默认看到本地分支。 git branch 命令剥离了 refs/heads/ 部分,留下 masterv2.

这样的名称

remote-tracking 分支是全名以 refs/remotes/ 开头的分支(然后是远程名称)。使用 git branch -r 时,该命令将显示您的远程跟踪分支。 git branch -r 命令剥离了 refs/remotes/ 部分,留下 origin/masterorigin/v2.

这样的名称

前缀去除有两种作用:git branch去除它,你也可以不去除它。这是为了方便起见,只要您不意外地给您的(常规,本地)分支名称以 origin/ 开头,它就可以正常工作。 (例如,如果您确实不小心将本地分支命名为 origin/abc,您可能会混淆自己,并且 git 有用的前缀剥离变得有害。)

(请注意,尽管名称为 "remote-tracking",但所有这些实体都位于您自己的存储库的本地。可能还存在其他引用,您可以通过 git for-each-ref 查看所有这些实体,这将向您显示每个引用都使用其全名。大多数时候你不需要这个,git branch 就足够了。)

一个(常规,本地)分支可以设置为track另一个分支。让一个分支跟踪另一个分支可以为您做一些事情,例如让 git status 告诉您何时领先 and/or 落后,并在 git branch -vv 输出中包含另一个分支。 (设置跟踪与远程跟踪分支不同。同样,本地分支是名称以 refs/heads/ 开头的分支,无论是否设置跟踪另一个分支,其名称都不会改变。但是,术语肯定令人困惑。)

要让一个分支跟踪另一个分支,请先检查第一个分支(您要进行跟踪的分支)。然后,运行 git branch --set-upstream-to <em>otherbranch</em>。例如,要使 v2 跟踪 origin/v2:

git checkout v2
git branch --set-upstream-to origin/v2

要使本地分支跟踪另一个本地分支,只需使用本地分支名称而不是远程跟踪分支名称。要使本地分支停止跟踪任何内容,请使用 git branch --unset-upstream.

所有这一切还有一个技巧,1 就是当您要求 git checkout 检出(但不创建)一个本地分支时,该分支不存在,git checkout 将搜索以查看是否存在具有相似名称的远程跟踪分支。如果是这样,它将 创建 本地分支 将其设置为跟踪远程跟踪分支。也就是说,如果分支 v2 存在——例如,如果你重命名或删除现有的本地 v2——并且 origin/v2 仍然 是否存在,那么:

git checkout v2

创建 本地分支 v2 将其设置为跟踪 origin/v2,同时完成。

一个分支不需要跟踪另一个分支来推送和fetch/merge/rebase/pull,但是将其设置为跟踪可以使所有这些操作更加方便。


1与git一样,实际上有更多方法可以让本地分支跟踪其他内容。您可以通过在推送中添加 -u 来设置本地分支以在成功 git push 时跟踪远程跟踪分支。您可以使用(已弃用)git branch --set-upstream 命令。您可以使用 git checkoutgit branch 的标志来创建或重新创建带有跟踪集的分支。而且,您可以使用 git config(使用两个单独的 git config 命令)使本地分支跟踪其他分支。

TL;DR v2 不是跟踪分支 - 未设置上游。 pull 行不通(如您所想)。 push 由于默认推送规则而有效。

My question is, why the branch v2 is not showing as a tracked branch

如果您查看您的 .git/config,您会看到带有跟踪信息的 branch "master" 节,但不会看到 branch "v2" 节,即 v2 不是跟踪分支。

even though the remote branch is available in github

推送非跟踪分支不会使其自动成为跟踪分支。您需要在推送中添加 -u 才能做到这一点。您可能打算在第一次推送非跟踪分支时执行此操作:

$ git push -u origin v2

i am able to do the pull and push of this branch

pull 不会执行您期望的操作,因为 v2 不跟踪上游。它将更新本地存储库中的远程跟踪分支 origin/v2,但不会协调(合并或变基)本地 v2 分支中的本地提交与远程上的任何新提交。但是,如果没有其他人在远程更新 v2 分支,那么您可能不会注意到问题。

push 之所以有效,是因为默认的推送规则会根据分支名称进行匹配。

Remote branches:
   master tracked
   v2     tracked
 Local branch configured for 'git pull':
   master merges with remote master
 Local refs configured for 'git push':
   master pushes to master (local out of date)
   v2     pushes to v2     (local out of date)
  • Remote branches: 部分显示本地存储库中的远程跟踪分支 origin/v2 跟踪远程分支 v2。 (远程跟踪分支 origin/v2 与本地 v2 分支不同。)
  • Local branch configured ... 部分仅显示本地分支 masterpull 影响,即 master 跟踪远程 masterv2 未列出 - pull 不会影响它,因为它没有上游集。
  • Local refs configured ... 部分显示您的 v2 分支将 push/update 到远程的 v2(并更新 origin/v2)——这是基于推送命令的默认匹配规则(也取决于您的 push.default 配置设置方式以及您使用的 git 版本)。

请注意 pushpull 之间存在一些不一致或违反直觉的行为。传统上,push 没有完全指定的 refspec arg,默认情况下不关心上游 - 它只是将同名分支推送到远程。由于跟踪的远程分支通常与本地分支同名,所以一切正常,pushpull 命令似乎都使用配置的跟踪分支。但是,如果本地分支和远程分支的名称不同,push 可能无法正常工作。 git 的各种版本相对于 pushpush.default 的某些更改,即 trackingcurrentsimple,尝试协调这些差异。

补充阅读: