【问题标题】:Understanding "git remote show" command output... Which is the meaning of: "Local ref configured for 'git push'"?了解“git remote show”命令输出......这是什么意思:“为'git push'配置了本地参考”?
【发布时间】:2023-03-30 02:44:02
【问题描述】:

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

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

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

...

[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

这是“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)

“push”和“pull”命令都能正常工作:

  • “push”命令将本地分支中提交的编辑发送到“她”远程分支。
  • “pull”命令将提交从远程分支带到“她”本地分支。

那么,为什么“为'git push'配置的本地参考”是“主推到主控”?为什么不“镜像推送到大师”? “本地过时”是什么意思?

更新@torek 回答后:

这里有一些参考:

$ 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

确切地说,“refs/remotes/github/master”和“refs/heads/master”不相等。这就是出现“本地已过期”消息的原因:

master pushes to master (local out of date)

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

不过,“remotes/github/master”和本地“mirror”中的代码是相同的。其实 refs "refs/remotes/github/master" 和 "refs/heads/mirror" 是相等的。

这是让我安心的信息:

mirror pushes to master (up to date)

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

【问题讨论】:

  • 从本地mirror 分支推送更改时使用的确切命令是什么?
  • 在镜像分支(“git checkout mirror”)只是“git push”。
  • 也许只是通过重新应用“镜像”跟踪的位置来检查您的跟踪是否一切正常:git branch -u github/master(第一个结帐镜像)。然后再次运行git remote show github 命令。你确定你的推送去对了地方吗?
  • @code_fodder 感谢您的建议...恐怕在“重新申请”之后,输出是相同的... :-( 是的,提交到正确的地方: -)

标签: git github git-branch


【解决方案1】:

[对我自己和 OP 的一些提醒:远程origin = GitLab,远程github = GitHub。从根本上说,使用git remote show 的主要问题是它做出了假设。这些假设是关于您将来将如何运行其他 Git 命令(git fetchgit push),以及将来如何布置每个 Git 命令中涉及的第二个 Git 存储库。显然,old Danish proverb很难做出预测,尤其是关于未来。]

让我在这里解决顶部已编辑的问题:

这是让我安心的信息:

mirror pushes to master (up to date)

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

有一件事值得一试:push.default 设置 upstream 告诉 Git 默认情况下,git push 应该这样做。如果这行得通并且做你想要的,那么你就准备好了。但请注意,无论 Git 在这里说什么,这都是谎言。

根本问题是mirror 推送到master在你输入git push 命令之前,它根本不会推送任何东西;一旦你输入了那个命令,控制where它去with那个git push命令,它可以完全覆盖git remote show所做的任何声明.

您在git push 时间的选择是:

  • 不提供额外的参数。

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

    此时,您的 Git 继续执行此处列出的第二种情况。

  • 提供一个额外的参数。此参数命名要连接的另一个 Git。它通常是一个远程origingithub),但此时您可以提供一个 URL,例如。

  • 提供两个或更多附加参数。其中第一个为远程命名(或者是一个 URL)。其余的是 refspecs,定义如下。

此时,您的 Git 连接到该远程,实际上运行 git ls-remote 以查看它们有哪些分支。此列表很重要,因为它与您提供或未提供的 refspecs 一起使用,具体取决于您的 push.default 设置,并且当您确实提供 refspec 时,您可以只提供 一半一个参考规范。

这是特别成问题的“半个 refspec”案例。不管你做了什么或设置了什么,如果你在mirror上实际运行git push github mirror,你的Git会要求远程github上的Git设置......好吧,这取决于你是否有上游为它设置,如果没有,你的push.default 设置。详细信息在the git push documentation 中,采用 Git 通常的神秘形式。但是,default 默认是“半 refspec”,名称 mirror 表示 mirror:mirror

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

如果你给 no refspec,你的 Git 会退回到push.default,并且它只有五个设置。默认的simple 让您的 Git 将您的分支集与其分支集进行比较(来自git ls-remote)。如果你的分支,例如mirror没有在那里有任何对应的分支,你的 Git 不会要求他们的 Git 设置任何个分支。

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

  • 如果您运行不带参数的git push,或不带其他参数的git push github,则远程将为github

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

  • 但是,如果您提供半个 refspec,我不确定,即使在多次重新阅读文档之后,full refspec Git 会构造什么。我认为会是mirror:mirror,这不是你想要的。

  • 您还可以配置提供默认参考规范的remote.github.push 变量。尽管push.default = upstream 看起来更简单,但这也可能让你得到你想要的。

我们现在回到原来的答案。 :-)


那么,为什么“为 'git push' 配置的本地引用”是“主推送到主控”?

这意味着:

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

这可能会或可能不会成功,这取决于 GitHub 上的 Git 服务器通过礼貌请求将 its master 设置为 Git 通过此推送请求发送的任何哈希 ID。 p>

(如果您在 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(即https://github.com/...)的Git 仍然没有一个名为mirror 的分支,你的Git 会对自己说:嗯。没有名为 mirror 的分支。最好不要推任何东西。

(如果明天 GitHub 上的其他 Git确实有一个名为 mirror 的分支,你的 Git 会告诉自己:啊哈!有一个名为 mirror 的分支!好的,我会要求其他 Git 更新其mirror)

为什么不“镜像推送到主控”?

因为它没有。即使您重新配置您的 push.default,也没有默认设置意味着“如果我没有给 git push 一个 refspec,则创建一个不匹配的。”

关于 refspecs 的简短部分

所有这些都以 refspec 的概念为基础。在 Git 中,refspec 本质上是一对引用

reference 是“分支或标签名称”的花哨词。 (它可以不仅仅是这两个,但它们是主要的两个。)像master 这样的分支名称是其完整拼写的简写,refs/heads/master。这个reference 名称refs/heads/master 是Git 表达“不仅仅是master,而是分支 master”的方式。像v1.2 这样的短标签名称是参考名称refs/tags/v1.2 的简写。如果你省略了refs/heads/refs/tags/ 部分,Git 通常会通过查看你现在拥有的分支和标签来判断你的意思。

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

refs/heads/master:refs/heads/master

例如。您需要其中的两个,因为您使用了两个 Git:一个在您的系统上,您要求它做某事,另一个在某些 remote 上,例如 gitlabgithub。你让你的 Git 通过网络电话呼叫另一个 Git。然后你的 Git 和他们的 Git 相互交谈,之后你的 Git 将 fetchpush 东西。

每个 Git 的 fetch 和 push 步骤需要一个引用,这意味着您需要 两个 引用:一个 refspec。

refspec 的两半是 sourcedestination。如果您正在运行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 说:

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

(尝试运行git ls-remote github 看看他们有什么,你会得到完整的列表)。

你自己的 Git 有一个名为 master 的分支,但是 your Git 为 your refs/heads/master(你的 master 分支)拥有的又大又丑的哈希 ID 是不同。

由于两者不同,你的 Git 假设你要么“领先”——你有一些他们没有的提交——要么“落后”(他们有一些你没有的提交),或者两者兼而有之。您的 Git 无法判断您落后了多远,如果您完全落后,但它可以通过查看您的所有信息来判断您“领先”多远提交。如果你有提交129bca4f...,其父级是e033fc12...,并且他们在提交e033fc12...,那么你只领先一个提交。

如果您的 Git 可以在您的 master 分支的历史记录中找到他们的 Git 提交哈希 ID,那么您就“领先”了,您可能现在可以 git push 向他们发送您的新提交,要求他们设置他们的 master129bca4f...,他们可能会接受提交并更新他们的master

但如果他们有提交 930ab988... 而你根本没有提交,那么你的 Git 只知道他们有一些你没有的提交。你必须“落后”。你可以从他们那里git fetch,获取他们所有你没有的提交,并用refs/remotes/github/master 记住它们。然后,您可以尽一切努力将这些提交添加到您自己的master,这样您就可以与它们保持一致——无论是在前面还是在后面——并做任何额外的工作,以便您现在领先于他们。

由您决定这是否是一个好主意,如果是,是否要这样做。 git remote show 所做的只是通过网络电话使用git ls-remote 给他们打电话,然后将他们的参考资料与您的参考资料进行比较,以根据这些结果猜测git fetchgit push 会做什么。 (如果你使用git pull,这意味着运行git fetch,然后运行git mergegit remote show 命令也试图猜测它会做什么。)

【讨论】:

  • 非常感谢您对 refspecs 等的解释。
  • 我已经用 cmets 更新了我关于你的回答的问题
  • 当你的意思是 remotes/github 时,我认为你已经写了 remotes/mirror :-(
  • 这是可能的 - 很难保持名称正确。让我再经历一遍……
  • 顺便说一句,另请参阅stackoverflow.com/q/45984929/1256452 - 如果您有一些上游设置并将push.default 设置为upstream 并运行git push &lt;remote&gt;upstream 设置似乎会传播,即使您已经覆盖了默认的 remote。因此,如果您将 push.default 设置为 upstream,请务必小心。
猜你喜欢
  • 2017-11-13
  • 1970-01-01
  • 2014-06-08
  • 2022-01-22
  • 2015-03-18
  • 1970-01-01
  • 1970-01-01
  • 2010-10-25
相关资源
最近更新 更多