Git追踪分支

5

我已经在本地创建了一个代码库,并将所有更改推送到了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

但没有显示本地分支和远程分支之间的映射关系。

2个回答

10

首先我们需要一些定义。

一个本地分支(也被称为“分支”,没有修饰符)是一个完整名称以refs/heads/开头的分支。使用git branch时,默认情况下会显示您的本地分支。 git branch命令去掉了refs/heads/部分,留下像 masterv2这样的名称。

一个远程跟踪分支是一个完整名称以refs/remotes/开头的分支(然后是远程的名称)。使用git branch -r时,该命令会显示您的远程跟踪分支。git branch -r命令去掉refs/remotes/部分,留下像origin/masterorigin/v2这样的名称。

前缀剥离双向工作: git branch移除它,您也可以不加它。这是为方便而设计的,只要不小心给您的(常规,本地)分支命名以origin/开头,就可以正常工作。(如果您意外地将本地分支命名为origin/abc,则可能会混淆自己,并且git有用的前缀剥离变得有害。)

(请注意,所有这些实体都是本地的,尽管名称为“远程跟踪”。还可能存在其他引用,并且您可以使用git for-each-ref查看所有引用,该命令将以完整名称显示每个引用。大多数时候不需要这样做,git branch已经足够。)

(常规,本地)分支可以设置为跟踪另一个分支。使一个分支跟踪另一个分支会为您做一些事情,例如让git status告诉您何时落后和/或超前,并包括其他分支在git branch -vv输出中。(设置跟踪不同于远程跟踪分支。再次强调,本地分支是其名称以refs/heads/开头的,无论是否设置为跟踪另一个分支,其名称都不会更改。但是,术语肯定会让人感到困惑。)

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

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

要使本地分支跟踪另一个本地分支,只需使用本地分支名称而不是远程跟踪分支名称。 要使本地分支停止跟踪任何内容,请使用git branch --unset-upstream
还有一招是当您要求git checkout检出(但不创建)不存在的本地分支时,git checkout将搜索以查看是否存在具有类似名称的远程跟踪分支。 如果是,则会创建本地分支并设置其跟踪远程跟踪分支。 也就是说,如果分支v2不存在 - 例如,如果您重命名或删除了现有的本地v2 - 并且origin/v2仍然存在,则:
git checkout v2

创建了本地分支v2并将其设置为跟踪origin/v2,所有这些操作一次完成。

一个分支不需要跟踪另一个分支就可以进行推送、获取/合并/变基/拉取等操作,但将其设置为跟踪可以使所有这些操作更加方便。


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


好的回答。我想知道为什么当从该分支进行git push时,git不会为新的本地分支设置跟踪? - Artyom
@Artyom:如果你添加了-u标志,git push将会设置上游分支,正如我在注释中所提到的。这个功能是在Git 1.7.0中新增的。 - torek

4

TL;DR v2不是一个被追踪的分支,没有设置上游。所以pull无法正常工作。由于默认推送规则,push可以正常工作。

我的问题是为什么v2分支没有显示为被追踪的分支

如果你查看.git/config文件,会看到一个带有跟踪信息的branch "master"的段落,但是你看不到branch "v2"的段落,也就是说v2不是一个被追踪的分支。

即使远程分支在github上可用

推送非追踪分支并不会自动将其变成追踪分支。你需要在推送时添加-u来实现这一点。你可能是想在第一次推送非追踪分支时这样做:

$ git push -u origin v2

我能够进行这个分支的拉取和推送。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: 部分显示本地 repo 中的远程跟踪分支 origin/v2 跟踪了远程的分支 v2。(远程跟踪分支 origin/v2 与本地 v2 分支不同。)
  • Local branch configured ... 部分仅显示本地分支 master 受到 pull 的影响,即 master 跟踪远程的 master 分支。v2 未列出 - 因为没有设置上游,所以 pull 不会影响它。
  • Local refs configured ... 部分显示您的 v2 分支将推送/更新至远程的 v2(并更新 origin/v2)- 这是基于 push 命令的默认匹配规则(还取决于您的 push.default 配置以及您使用的 git 版本)。

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

进一步阅读:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接