为什么分支在 "local ref configured for git push" 部分存在,但在 "local branch configured for git pull" 部分不存在

Why is a branch is present in section "local ref configured for git push" but absent in section "local branch configured for git pull"

我目前正在按照"progit 2nd edi"这本书学习git。

在"inspecting a remote"节中,作者有如下例子

我注意到 "markdown-strip" 分支在 "local branch configured for git pull" 部分中不存在,但在 "local ref configured for git push" 部分中存在。我想知道为什么会这样。

PS:我了解 "git pull" 和 "git push" 的工作原理。 "local branch configured for git pull" 中缺少 "markdown-strip" 分支让我感到困惑。

这似乎是一个合成示例,因此可能只是一个错误。但是,它也可能是特定配置的副作用,其中本地分支 markdown-strip 没有上游集。

请记住,任何分支的 upstream 是一个两部分设置,您可以使用一个命令进行设置:

git branch --set-upstream-to=<upstream> <branch>

如:

git branch --set-upstream-to=origin/master master

或者使用两个单独的 git config 命令相当笨拙地配置:

git config branch.master.remote origin
git config branch.master.merge refs/heads/master

每个分支名称,例如master,可以有一个个上游集,也可以有没有个上游集. (也就是说,你不能设置两个或多个上游。你可以设置一个remote和两个或多个mergegit show做某事对他们来说很特别;但这不是正常的配置,git branch --set-upstream-to 不能也不会这样做。)

要以正常方式删除上游,请使用 git branch --unset-upstream。下面,我以一种不正常的方式进行,尽管对 git remote show origin 的影响是相同的。 (我在我的编辑器中删除了两个设置中的一个,因为这让我可以在编辑器中撤消删除,这比输入 git branch 命令更容易。当然,我现在花更多的时间来解释这个,而不仅仅是以正常方式进行。:-) )

任何本地分支的上游可以是另一个本地分支,但更常见的是 Git 所谓的 远程跟踪分支。1 您通常不希望或不需要 取消设置 上游。有时你确实想要 set 一个上游,但是如果你使用正常的方法,你不能为一个新的分支设置上游,直到你先 pushed那个新分支:

$ git checkout -b newbr
... the usual stuff here ...
$ git commit
$ git branch --set-upstream-to=origin/newbr

这个报错失败了,因为origin/newbr还不存在,因为我们在本地创建了newbr但是还没有推送到origin,所以有在我们的存储库中 没有 origin/newbr。一旦我们 do 运行 git push origin newbr,就会在 origin 上创建 newbr。这反过来创建了我们自己的 origin/newbr 来记住我们刚刚在 origin 上创建的 newbr,并且——哇!——现在我们终于可以将 origin/newbr 设置为 newbr 的上游。

我认为在这种情况下,Pro Git 作者有一个存储库,他们在其中创建了一个本地分支,然后将其推送到名为 origin 的远程,但从未到过 运行宁git branch --set-upstream-to在树枝上。

一个例子

例如,我的 Git 存储库副本 Git 的本地分支 master 配置了其上游设置为 origin/master。如果我 运行 git remote show origin 我得到(在通常的早期输出之后):

  Remote branches:
    maint  tracked
    master tracked
    next   tracked
    pu     tracked
    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 (up to date)

stash-exp 是我很久以前为 git stash 修复错误的地方)。如果我 删除 .git/configmerge = refs/heads/master 和 运行 git remote show origin 再次,我得到这个:

  Remote branches:
    maint  tracked
    master tracked
    next   tracked
    pu     tracked
    todo   tracked
  Local branch configured for 'git pull':
    stash-exp merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

请注意,这仍然声明 master pushes to master。事实上,nothing 推送到 anything,因为 origin 存储库是只读的。

如果我 运行 git push origin master,Git 会 尝试 ,那么这个声明就是这样。在这种情况下,我的 Git 会调用他们的 Git 并发现我们都有一个名为 master 的分支。然后我的 Git 会建议他们的 Git 他们应该设置 他们的 refs/heads/master 指向与 my[ 相同的提交=150=] refs/heads/master。他们会拒绝——他们的存储库被设置为拒绝这样的尝试——但我的 Git 不知道。

当我删除 branch.master.merge = refs/heads/master 设置时,我的 Git 不再说 master merges with remote master。一旦我把那个设置放回去,我的 Git 又开始说了。这并不意味着我的 master 总是 与他们的 master 合并:它只是意味着如果我要 运行 git pull,他们的 master 有新的提交,我的 Git 会作为 git pull、运行 git merge origin/master(或多或少)的第二步。 git pull 命令使用上游设置来确定要做什么。但是我从来没有2运行git pull,因为git pull是一个糟糕的工具。

(我总是先 git fetch,然后一般检查东西,然后 运行 git rebase 如果合适,或者使用我的 git mff 别名,它是 git merge --fast-forward。请注意 git rebasegit merge 使用上游设置。git status 也是如此——所以它非常有用设置上游,即使你避免 git pull.)


1记住,一个所谓的远程跟踪分支origin/master是[=119中的(a) =]你的 存储库(它根本不是远程的,它是本地的); (b) 只是您的 Git 记住您的 Git 上次 originmasterorigin 上看到的内容的方式182=] 调用了 origin 的 Git。您无法获得 "on" origin/master git checkout master 获得您自己的 origin 分支的方式,这意味着 (c) 远程跟踪分支甚至不是分支!因此,远程跟踪分支 (1) 不是远程分支,(2) 确实记得您的 Git 在另一个 Git 上看到的内容,并且 (3) 不是分支。名字里的tracking三个字只有一个对了一半! :-)

带连字符的形式 remote-tracking 使它变得更好,因为它是 "tracks a branch as seen on a remote" 的东西。整个事情有点道理,但这个名字一开始就非常具有误导性。人们认为 远程跟踪分支 就像本地分支,但事实并非如此。但这还不是最糟糕的问题:它们过去被称为 远程分支 ,有些人仍在使用该短语。无论如何,这些本地名称和这些远程跟踪名称都只是名称;分支机构本身是另一个实体。参见 What exactly do we mean by "branch"?

2What, never? Well, hardly ever!