了解"git remote show"命令输出...的含义是:“为'git push'配置的本地引用"? [英] Understanding "git remote show" command output... Which is the meaning of: "Local ref configured for 'git push'"?

查看:55
本文介绍了了解"git remote show"命令输出...的含义是:“为'git push'配置的本地引用"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个遥控器和两个本地分支:

  • 本地分支"master"正在跟踪远程分支"origin/master"
  • 本地分支"mirror"正在跟踪远程分支"github/master"

这是在我的.git/config文件中:

  ...[远程来源"]网址= http://my.gitlab.com/nandoquintana/repo.git提取= + refs/heads/*:refs/remotes/origin/*[远程"github"]网址= https://github.com/nandoquintana/repo.git获取= + refs/heads/*:refs/remotes/github/*[分行主人"]远程=起源合并=裁判/负责人/大师[分支镜子"]远程= github合并=裁判/负责人/大师[推]默认=跟踪 

这是"git remote show origin"的输出:

  $ git remote show origin*遥远的起源获取网址:http://my.gitlab.com/nandoquintana/repo.git推送网址:http://my.gitlab.com/nandoquintana/repo.gitHEAD分支:主远程分支:掌握大师为'git pull'配置的本地分支:母版与远程母版合并为'git push'配置的本地引用:主人推向主人(最新)$ git remote show github*远程github获取网址:https://github.com/nandoquintana/repo.git推送网址:https://github.com/nandoquintana/repo.gitHEAD分支:主远程分支:掌握大师为'git pull'配置的本地分支:镜像与远程主服务器合并为'git push'配置的本地引用:主推送到主(本地已过期) 

"push"和"pull"命令均能正常工作:

  • 推"命令将本地分支中的已提交编辑发送到她"的远程分支.
  • 拉"命令将提交从远程分支提交到她"的本地分支.

那么,为什么配置为'git push'的本地引用"是"master pushs to master"?为什么不镜子推向高手"?本地过时"是什么意思?

在@torek回答后,

更新:

这里有一些裁判:

  $ git ls-remote github455063a9db09977535ac808af5729181b153f4c7 HEAD455063a9db09977535ac808af5729181b153f4c7 Refs/Heads/Master$ cat .git/refs/heads/masterca9e4399058a4998bd7c993f86d6740cfaec820b$ cat .git/refs/heads/mirror455063a9db09977535ac808af5729181b153f4c7$ cat .git/refs/remotes/github/master455063a9db09977535ac808af5729181b153f4c7 

确实,"refs/remotes/github/master"和"refs/heads/master"不相等.这就是为什么出现本地过时"消息的原因:

  master推送到master(本地已过期) 

这对我来说不是问题,我肯定知道"remotes/github/master"和本地"master"中的代码是不同的.

尽管如此,"remotes/github/master"和本地"mirror"中的代码是相同的.实际上,refs"refs/remotes/github/master"和"refs/heads/mirror"是相等的.

这是让我省心的消息:

 镜像推送至主服务器(最新) 

如何配置remote/github ...或push.default ...以获得此输出?

解决方案

[对我本人和OP的一些提醒:远程 origin = GitLab,远程 github = GitHub.从根本上说,使用 git remote show 的主要问题是它会产生假设.这些假设是关于将来如何运行其他Git命令( git fetch git push ),以及有关第二个Git存储库如何与每个这些Git命令有关的假设将在未来进行布局.显然,是古老的丹麦谚语:这很困难做出预测,尤其是对未来的预测.]

让我在此处顶部顶部介绍编辑后的问题:

这是让我省心的消息:

 镜像推送至主服务器(最新) 

如何配置remote/github ...或push.default ...以获得此输出?

有一件事值得一试:一个 push.default 设置 upstream 告诉Git默认情况下是 git push 应该这样做.如果这行得通,并且可以满足您的要求,那么您已经准备就绪.但是请注意,无论Git在这里说什么,无论如何都是骗人的.

根本的问题是镜子 推送到 master .在您输入 git push 命令之前,它根本不会推送任何内容;输入该命令后,控制位置,它将与 git push 命令一起使用,该命令可以完全覆盖任何声明 git remote show .

您在 git push 时选择的选项是:

  • 不提供其他参数.

    在这种情况下,您的Git从当前上游选择远程.如果上游设置为 origin/...,则远程服务器为 origin .如果上游设置为 github/...,则远程服务器为 github .看起来像是一个简单的字符串替换(尽管出于历史原因,通常是这样,实际上它是一个非常复杂的字符串替换,通常变得很简单:在斜杠前加上部分).

    这时,您的Git继续进行此处列出的第二种情况.

  • 提供另外一个参数.此参数命名要连接的另一个Git.通常它是一个远程( origin github ),尽管例如,此时您可以提供一个URL.

  • 提供两个或更多其他参数.其中第一个名称是远程名称(或是URL).其余的是 refspecs ,如下所述.

这时,您的Git连接到该远程服务器,实际上,它运行 git ls-remote 来查看它们具有哪些分支.此列表很重要,因为它与您根据 push.default 设置提供或未提供的refspecs一起使用,并且当您 do 给出refspec时就可以使用该列表,您可以给一半 refspec.

这是半个refspec"案例,特别有问题.无论您做什么或设置什么,如果您在 mirror 上时实际运行 git push github mirror ,您的Git都会在远程 github上询问Git进行设置...好吧,这取决于您是否为其设置了上游设置,如果没有,则取决于您的 push.default 设置.详细信息位于 git push 文档,以Git常用的神秘形式表示.但是, default 默认值是半参考规范"的名称, mirror 的名称表示 mirror:mirror .

如果您提供完整的refspec,例如 git push github mirror:asdf ,则refspec的后半部分将确定您的Git要求设置其Git的分支名称.如果您提供一半的refspec,通常您提供的一半将同时成为两个名称.使用默认的 push.default = simple ,您不会意外地将 mirror 推送给任何人其他人的 master ,则必须使用显式的完整refspec(然后由您自己决定是否正确).

如果您给 no refspec设置,则您的Git会退回到 push.default 上,并且只有五个设置.默认的 simple 使Git将您的分支集与其分支集进行比较(来自 git ls-remote ).如果您的分支(例如 mirror )没有相应的分支,则您的Git不会要求其Git设置任何个分支

假设您在分支 mirror 上,该分支的上游设置为 github/master ,并且您已经配置了 push.default 上游(使用 git config push.default上游):

  • 如果运行不带任何参数的 git push 或不带附加参数的 git push github ,则 remote 将为<代码> github .

  • 如果不提供refspec,则将应用 push.default 设置:Git将构造的refspec将是 mirror:master .

  • 但是,如果您提供了一半的refspec,我不确定,即使在多次阅读文档后,Git会构造什么 full refspec.我认为它将是 mirror:mirror ,这不是您想要的.

  • 您还可以配置提供默认参考规范的 remote.github.push 变量.尽管 push.default =上游似乎更简单,但这也可能使您得到想要的东西.

我们现在返回原始答案.:-)


那么,为什么配置为'git push'的本地引用"是"master pushs to master"?

这意味着:

  • 假设您当前的分支是 master (即您已经运行 git checkout master )
  • 然后如果您运行 git push github (不是 git push github more-command-words )
  • Git(特别是您自己的 Git)将尝试将您当前的 master 推送到 https://github.com/nandoquintana/repo.git master

成功与否,具体取决于GitHub上的Git服务器执行的有礼貌的请求,以将 its master 设置为您的Git随此发送的任何哈希ID推送请求.

(如果您使用的是 master ,并且再次运行 git push origin ,则没有其他任何参数,只是名称为 origin 指的是GitLab上的Git.)

另一方面,假设您当前的分支名为 mirror :

  • 所以您只运行了 git checkout mirror
  • 现在您运行 git push github
  • 您的Git将会-根据现在看到的内容,因此假设这是它再次看到的内容-尝试推送任何内容.

最可能的原因是您已经将 push.default 配置或默认设置为 simple .当 push.default 设置为 simple 时,没有 refspec 参数的 git push 会尝试推送当前分支,但是仅当另一个Git具有相同名称的分支时.因此,如果位于 github 的Git(即位于 https://github.com/... 的Git)仍然没有拥有一个名为 mirror ,您的Git会对自己说:嗯.没有名为 mirror 的分支.最好不要压任何东西.

(如果明天GitHub上的其他Git确实有一个名为 mirror 的分支,您的Git会自言自语: Aha!有一个分支名为 mirror !好吧,我请其他Git更新其 mirror .)

为什么镜像推向高手"?

因为不是.即使您重新配置 push.default ,也没有默认设置意味着如果我无法给 git push 一个refspec,请做出一个不匹配的refspec."

关于refspecs的简短片段

所有这些都基于 refspec 的概念.在Git中,refspec本质上是一对引用.

引用是分支或标签名称"的花哨词.(它不仅可以是这两个,而且是主要的两个.)像 master 这样的分支名称是其完整拼写的简称, refs/heads/master .这个 reference 名称,即 refs/heads/master ,是Git所说的不仅是 master ,还有 branch master ".短标记名称(例如 v1.2 )是引用名称 refs/tags/v1.2 的简写.如果您忽略了 refs/heads/ refs/tags/部分,那么Git通常会通过查看您现在拥有的分支和标签来找出您的意思.

无论如何, refspec 大多只是其中的两个 ,中间带有一个冒号::

  refs/heads/master:refs/heads/master 

例如

.您需要其中两个,因为您使用的是两个Git:一个在系统上要求执行某项操作,另一个在一些 remote (例如 gitlab 或<代码> github .您的Git通过互联网电话呼叫另一个Git.然后您的Git和他们的Git互相交谈,之后您的Git将获取东西.

每个git的提取和推送步骤都需要一个引用,因此这意味着您需要两个引用:一个refspec.

refspec的两半是 source destination .如果您正在运行 git fetch ,则源是 other Git,而目标是您自己的Git.如果您正在运行 git push ,则是源;另一个Git成为目的地.但是无论哪种情况,源都会向目标提交一些提交,然后源的 name (refspec的左半部分)用于更改目标的 name 中的某些内容.— refspec的右半部分.

对于 git fetch ,在每侧使用不同的名称是完全正常的.我们获取他们的 refs/heads/master ,并写入我们自己的 refs/remotes/origin/master .我们从他们的 refs/heads/master 获取并写入我们自己的 refs/remotes/mirror/master .这样一来,我们就可以从许多不同的地方提取东西,而又保持它们笔直.

不过,对于 git push ,在每侧使用 same 名称更为常见.我们从他们的 master 提取到我们的 refs/remotes/.../master 中.然后,我们进行一段时间的工作,并通过合并或重新确定基础来确保我们 master 中的内容是在其 master 之上的更新例如.然后,我们再次调用它们,提交新的提交,并要求他们设置自己的 master -不是他们甚至没有的 nando/master ,而是他们的 master -基于他们先前提交的最新提交.

我们先获取内容,然后进行工作,再进行推送,以确保它建立在他们的基础之上.如果我们在索非亚(Sofia)失去了竞争",我们俩大约都在同一时间拿到钱,但是她工作得更快,然后她就尽力而为了.我们会得到远程拒绝",不快进"的错误;我们必须再次获取信息,以便从GitHub或其他任何地方获取Sofia的作品,并将我们的作品构建在她的作品之上,然后再次尝试推送.

本地过期"是什么意思?

当您的 git remote show 调用了远程程序时-特别是 github ,即 https://github.com/nandoquintana/repo.git -Git所说的 other 在互联网电话上

 我有这些参考资料:refs/heads/master<一些丑陋的哈希ID> 

(尝试运行 git ls-remote github 看看它们有什么,您将获得完整列表).

您自己的Git有一个名为 master 的分支,但是Git的您的 refs/heads有一个丑陋的哈希ID your /master (您的 master 分支)不同.

由于两者不同,您的Git会假设您要么领先"(您有一些他们不提交的提交),要么是落后"(他们有一些您不提交的提交),或者两者兼而有之.如果您根本不在后面,您的Git不能告诉您身后有多远 ,但是通过查看您所有的人,它可以 告诉您有多远提交.如果您有提交 129bca4f ... 且其父代为 e033fc12 ... ,并且他们位于提交 e033fc12 ... ,那么您只需提交一次即可.

如果您的Git可以在您的 master 分支的历史记录中找到其Git的提交哈希ID,那么您就领先"了,您现在可以通过 git push 发送给他们新的提交,要求他们将其 master 设置为 129bca4f ... ,然后他们可能会接受这些提交并更新其 master .

但是,如果他们提交了 930ab988 ... 而您根本没有拥有该提交,那么您的Git所知道的就是他们有一些提交,而您没有t.您必须落后".您可以从它们中进行 git fetch ,获取他们没有的所有提交,并通过 refs/remotes/github/master 记住它们.然后,您可以执行将 add 提交到您自己的 master 的所有操作,以便与他们保持一致-既不领先也不落后-并且要做任何其他工作这样您就可以先于了.

由您决定这是否是一个好主意,如果是,则决定是否这样做.所有 git remote show 所做的就是通过Internet电话使用 git ls-remote 对其进行调用,然后将它们的引用与您的引用进行比较,以猜测是什么 git根据这些结果,fetch git push 会执行此操作.(如果使用 git pull ,则仅表示运行 git fetch ,然后运行 git merge . git remote show 命令也会尝试猜测会发生什么.)

I have two remotes and two local branches:

  • local branch "master" is tracking remote branch "origin/master"
  • local branch "mirror" is tracking remote branch "github/master"

This is in my .git/config file:

...

[remote "origin"]
    url = http://my.gitlab.com/nandoquintana/repo.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[remote "github"]
    url = https://github.com/nandoquintana/repo.git
    fetch = +refs/heads/*:refs/remotes/github/*
[branch "master"]
    remote = origin
    merge = refs/heads/master
[branch "mirror"]
    remote = github
    merge = refs/heads/master
[push]
    default = tracking

This is the output of "git remote show origin":

$ git remote show origin 

* remote origin
  Fetch URL: http://my.gitlab.com/nandoquintana/repo.git
  Push  URL: http://my.gitlab.com/nandoquintana/repo.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

$ git remote show github

* remote github
  Fetch URL: https://github.com/nandoquintana/repo.git
  Push  URL: https://github.com/nandoquintana/repo.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    mirror merges with remote master
  Local ref configured for 'git push':
    master pushes to master (local out of date)

Both "push" and "pull" commands work properly:

  • "push" command sends committed edits in a local branch to "her" remote branch.
  • "pull" command brings commits from a remote branch to "her" local branch.

So, why "Local ref configured for 'git push'" is "master pushes to master"? why not "mirror pushes to master"? and what does "local out of date" means?

UPDATED after @torek answer:

Here we are some refs:

$ git ls-remote github
455063a9db09977535ac808af5729181b153f4c7    HEAD
455063a9db09977535ac808af5729181b153f4c7    refs/heads/master

$ cat .git/refs/heads/master
ca9e4399058a4998bd7c993f86d6740cfaec820b
$ cat .git/refs/heads/mirror
455063a9db09977535ac808af5729181b153f4c7
$ cat .git/refs/remotes/github/master
455063a9db09977535ac808af5729181b153f4c7

Exactly, "refs/remotes/github/master" and "refs/heads/master" are not equal. That is why "local out of date" message appears:

master pushes to master (local out of date)

That is not a problem for me, I positively know that code in "remotes/github/master" and in local "master" are different.

Nevertheless, code in "remotes/github/master" and local "mirror" are the same. In fact, refs "refs/remotes/github/master" and "refs/heads/mirror" are equal.

This is the message that would give me some peace of mind:

mirror pushes to master (up to date)

How could I configure remote/github... or push.default... to get this output?

解决方案

[Some reminders, to both myself and OP: remote origin = GitLab, remote github = GitHub. Fundamentally, the main problem with using git remote show is that it makes assumptions. These assumptions are about how you will run other Git commands—git fetch and git push—in the future, and about how the second Git repository involved in each of those Git commands will be laid out in the future. Per, apparently, an old Danish proverb: It is difficult to make predictions, especially about the future.]

Let me address the edited question at the top here:

This is the message that would give me some peace of mind:

mirror pushes to master (up to date)

How could I configure remote/github... or push.default... to get this output?

There is one thing that is worth a try: one push.default setting, upstream, tells Git that by default, git push should do this. if that works and does what you want, you're all set. But note that whatever Git says here, it's something of a lie anyway.

The fundamental problem is that mirror doesn't push to master. Until you enter a git push command, it doesn't push to anything at all; once you do enter that command, you control where it goes with that git push command, which can totally override any claim git remote show made.

Your options at git push time are:

  • Supply no additional arguments.

    In this case, your Git picks the remote from the current upstream. If the upstream is set to origin/... the remote is origin. If the upstream is set to github/... the remote is github. It looks like a simple string substitution (and usually it is, although for historical reasons, it's actually a horribly complicated string substitution that usually turns out to be simple: take the part before the slash).

    At this point, your Git proceeds on to the second case listed here.

  • Supply one additional argument. This argument names the other Git to connect to. It's usually a remote (origin or github), though at this point you can give a URL instead, for instance.

  • Supply two or more additional arguments. The first of these names the remote (or is a URL). The rest are refspecs, as defined below.

At this point, your Git connects to that remote and, in effect, runs git ls-remote to see what branches they have. This list is important because it's used with the refspecs you gave, or failed to give, based on your push.default setting, and the fact that when you do give a refspec, you can give just half a refspec.

It's the "half a refspec" case that's particularly problematic. No matter what else you do or set, if you actually run git push github mirror while you're on mirror, your Git will ask the Git on remote github to set ... well, this depends on whether you have an upstream set for it, and if not, your push.default setting. The details are in the git push documentation, in Git's usual cryptic form. The default default, though, is that for a "half refspec", the name mirror means mirror:mirror.

If you give a full refspec, e.g., git push github mirror:asdf, the second half of the refspec determines which branch name your Git asks their Git to set. If you give half a refspec, the half you gave usually becomes both names. With the default of push.default = simple, you can't accidentally push your mirror to anyone else's master, you must use the explicit full refspec (and then it's up to you to get it right).

If you give no refspec, your Git falls back on push.default, and there are only five settings for it. The default one, simple, has your Git compare your set of branches to their set of branches (from git ls-remote). If your branch, such as mirror, doesn't have any corresponding branch there, your Git won't ask their Git to set any branches.

Let's assume you are on your branch mirror, which has its upstream set to github/master, and that you have configured push.default to upstream (using git config push.default upstream):

  • If you run git push with no arguments, or git push github with no additional arguments, the remote will be github.

  • If you supply no refspec, the push.default setting applies: the refspec Git will construct will be mirror:master.

  • However, if you supply half a refspec, I'm not sure, even after re-reading the documentation several times, what full refspec Git will construct. I think it will be mirror:mirror, which is not what you want.

  • You can also configure a remote.github.push variable that supplies default refspecs. This might also allow you to get what you want, although push.default = upstream seems simpler.

We now return to the original answer. :-)


So, why "Local ref configured for 'git push'" is "master pushes to master"?

This means that:

  • assuming your current branch is master (i.e., you have run git checkout master)
  • and if you then run git push github (not git push github more-command-words)
  • Git—specifically your own Git—will attempt to push your current master to https://github.com/nandoquintana/repo.git's master

which may or may not succeed, depending on what the Git server at GitHub does with a polite request to set its master to whatever hash ID your Git sends with this push request.

(The same holds if you're on master and run git push origin, again with no additional arguments, except that the name origin refers to the Git at GitLab.)

On the other hand, let's assume your current branch is named mirror:

  • so you just ran git checkout mirror
  • and now you run git push github
  • your Git will—based on what it sees right now, hence assuming this is what it sees again—not attempt to push anything.

The reason for this is most likely that you have push.default configured, or defaulted, to simple. When push.default is set to simple, a git push without a refspec argument tries to push the current branch, but only if the other Git has a branch with the same name. So if the Git at github (i.e., at https://github.com/...) still does not have a branch named mirror, your Git will say to itself: Huh. No branch named mirror. Better not push anything.

(If, tomorrow, that other Git on GitHub does have a branch named mirror, your Git will say to itself: Aha! There's the branch named mirror! OK, I'll ask that other Git to update its mirror.)

why not "mirror pushes to master"?

Because it doesn't. Even if you re-configure your push.default, there's no default setting that means "if I fail to give git push a refspec, make a non-matching one up."

A brief segment on refspecs

All of this is keyed on the concept of a refspec. In Git, a refspec is essentially a pair of references.

A reference is the fancy word for "branch or tag name". (It can be more than just those two, but those are the main two.) A branch name like master is short-hand for its full spelling, refs/heads/master. This reference name, refs/heads/master, is Git's way to say "not just master, but the branch master". A short tag name like v1.2 is short-hand for the reference name refs/tags/v1.2. If you leave out the refs/heads/ or refs/tags/ part, Git usually figures out which one you mean by looking at the branches and tags you have now.

Anyway, a refspec is mostly just two of these things with a colon : in the middle:

refs/heads/master:refs/heads/master

for instance. You need two of them because you are using two Gits: one on your system, which you ask to do something, plus another one on some remote, such as gitlab or github. You have your Git call up the other Git over the Internet-phone. Then your Git and their Git talk to each other, after which your Git will fetch or push things.

The fetch and push steps need one reference for each Git, so that means you need two references: a refspec.

The two halves of a refspec are the source and the destination. If you're running git fetch, the source is the other Git and the destination is your own Git. If you are running git push, you are the source; the other Git becomes the destination. But in either case, the source gives some commits to the destination, and then the source's name—the left half of the refspec—is used to change something in the destination's name—the right half of the refspec.

For git fetch, it's entirely normal to have a different name on each side. We fetch from their refs/heads/master and write to our own refs/remotes/origin/master. We fetch from their refs/heads/master and write to our own refs/remotes/mirror/master. This lets us fetch from a bunch of different places, yet keep them all straight.

For git push, though, it's much more normal to use the same name on each side. We fetch from their master, into our refs/remotes/.../master. Then we work for a while and make sure whatever is in our master is an update that goes on top of their master, by merging or rebasing for instance. Then we call them up again, deliver our new commits, and ask them to set their master—not their nando/master, which they don't even have, but their master—to this latest commit that builds upon their previous commits.

We make sure that it builds upon theirs, by fetching first, then working, then pushing. If we lose a "race" with Sofia—we both fetch about the same time, but she works faster and then she pushes before we can—we get that "remote rejected" "not fast forward" error; we must fetch again, to pick up Sofia's work from GitHub or wherever, and make our work build atop her work, and then try the push again.

and what does "local out of date" means?

When your git remote show called up the remote—specifically github, i.e., https://github.com/nandoquintana/repo.git—over the Internet-phone, that other Git said:

I have these references:
  refs/heads/master  <some big ugly hash ID>

(try running git ls-remote github to see what they have, you will get the complete list).

Your own Git has a branch named master, but the big ugly hash ID your Git has for your refs/heads/master—your master branch—is different.

Since the two are different, your Git assumes you are either "ahead"—you have some commits they don't—or "behind" (they have some commits you don't), or perhaps both. Your Git can't tell how far behind you are, if you are behind at all, but it can tell how far "ahead" you are, by looking at all your commits. If you have commit 129bca4f... whose parent is e033fc12..., and they are at commit e033fc12..., then you're ahead by just one commit.

If your Git can find their Git's commit hash ID in your master branch's history, you are "ahead" and you can probably git push right now to send them your new commits, asking them to set their master to 129bca4f..., and they will probably take the commits and update their master.

But if they have commit 930ab988... and you don't have that commit at all, all your Git knows is that they have some commits you don't. You must be "behind". You can git fetch from them, get all the commits they have that you don't, and remember them with refs/remotes/github/master. You can then do whatever it takes to add those commits to your own master, so that you are even with them—neither ahead nor behind—and do any additional work it takes so that you are now ahead of them.

It's up to you to decide whether that's a good idea, and if so, whether to do it. All git remote show does is call them up, using git ls-remote, over the Internet-phone, and compare their references to your references to guess what git fetch and git push would do, based on those results. (If you use git pull, that just means run git fetch, then run git merge. The git remote show command tries to guess what that will do, too.)

这篇关于了解"git remote show"命令输出...的含义是:“为'git push'配置的本地引用"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆