[给我自己和OP的一些提醒:远程origin
= GitLab,远程github
= GitHub。从根本上来说,使用的主要问题是git remote show
是它让假设。这些假设与您将如何运行其他 Git 命令有关 -git fetch
and git push
——未来,以及每个 Git 命令涉及的第二个 Git 存储库未来将如何布局。显然,每一个古老的丹麦谚语 https://quoteinvestigator.com/2013/10/20/no-predict/: 做出预测是很困难的,尤其是对未来的预测。]
让我在这里解决顶部编辑过的问题:
这是让我安心的消息:
mirror pushes to master (up to date)
我如何配置remote/github...或push.default...来获得此输出?
有件事值得一试:push.default
环境,upstream
,告诉 Git 默认情况下,git push
应该这样做。如果它有效并且达到了您想要的效果,那么您就万事大吉了。但请注意,无论 Git 在这里说什么,它都是谎言。
根本问题是mirror
doesn't推到master
. 直到您输入git push
command,它根本不会推动任何东西;一旦你输入该命令,you控制where它去with that git push
命令,它可以完全推翻任何声明git remote show
made.
您的选择位于git push
时间是:
-
不提供额外的参数。
在这种情况下,您的 Git 选择remote从当前的上游。如果上游设置为origin/...
遥控器是origin
。如果上游设置为github/...
遥控器是github
。它看起来像是一个简单的字符串替换(通常情况下确实如此,尽管由于历史原因,它实际上是一个非常复杂的字符串替换,usually事实证明很简单:取斜线之前的部分)。
此时,您的 Git 将继续处理此处列出的第二种情况。
提供一个附加参数。该参数指定要连接的其他 Git。它通常是一个remote (origin
or github
),不过此时您可以提供一个 URL,例如。
提供两个或多个附加参数。其中第一个名称为远程(或者是 URL)。其余的是refspecs,如下定义。
此时,您的 Git 连接到该远程服务器,并且实际上运行git ls-remote
看看他们有什么分支。该列表很重要,因为它与您提供的或未能提供的参考规格一起使用,具体取决于您的push.default
设置,以及当您do给出一个 refspec,你可以只给出half参考规格。
“半个参考规范”的情况尤其成问题。不管你做了什么或设置了什么,如果你真的跑了git push github mirror
当你在的时候mirror
,你的 Git 会询问远程的 Gitgithub
设置...好吧,这取决于您是否有上游设置,如果没有,您的push.default
环境。详细信息在the git push文档 https://www.kernel.org/pub/software/scm/git/docs/git-push.html,采用 Git 通常的神秘形式。这default不过,默认值是“half refspec”,名称mirror
means mirror:mirror
.
如果您提供完整的参考规范,例如,git push github mirror:asdf
,refspec 的后半部分确定您的 Git 要求其 Git 设置哪个分支名称。如果您给出一半的参考规范,则您给出的一半通常会成为两个名称。默认情况下push.default = simple
,你不能意外地推动你的mirror
to anyone else's master
,您必须使用显式的完整引用规范(然后由您决定是否正确)。
如果你给norefspec,你的 Git 依靠push.default
,并且只有五种设置。默认的,simple
,让你的 Git 将你的分支集与他们的分支集进行比较(来自git ls-remote
)。如果您的分支机构,例如mirror
, doesn't那里有任何相应的分支,你的 Git 不会要求他们的 Git 设置any分支机构。
假设您在您的分支上mirror
,其上游设置为github/master
,并且您已配置push.default
to upstream
(using git config push.default upstream
):
如果你跑git push
没有参数,或者git push github
没有额外的参数,remote将github
.
如果您不提供 refspec,则push.default
设置适用:Git 将构建的 refspec 将是mirror:master
.
但是,如果您提供一半的 refspec,即使在多次重新阅读文档之后,我也不确定,什么fullGit 将构建 refspec。我think这将是mirror:mirror
,这不是你想要的。
您还可以配置一个remote.github.push
提供默认参考规范的变量。这也可能让你得到你想要的东西,尽管push.default = upstream
看起来更简单。
我们现在回到原来的答案。 :-)
那么,为什么“为‘git Push’配置的本地引用”是“主站推送到主站”?
这意味着:
- 假设您当前的分支是
master
(即,你已经跑了git checkout master
)
- 如果你然后跑
git push github
(not git push github more-command-words
)
- Git——特别是your ownGit—将尝试推送您当前的
master
to https://github.com/nandoquintana/repo.git
's master
这可能会成功,也可能不会成功,具体取决于 GitHub 上的 Git 服务器对设置的礼貌请求所做的操作its master
到您的 Git 通过此推送请求发送的任何哈希 ID。
(如果您在master
并运行git push origin
,同样没有其他参数,除了名称origin
指的是 GitLab 上的 Git。)
另一方面,假设您当前的分支名为mirror
:
- 所以你就跑了
git checkout mirror
- 现在你跑了
git push github
- 你的 Git 会——基于它现在看到的,因此假设这是它再次看到的——not尝试推动anything.
造成这种情况的原因很可能是您有push.default
配置或默认为simple
. When push.default
被设定为simple
, a git push
没有refspec论证试图推动current分支,但是仅当另一个 Git 有同名分支时。所以如果 Git 在github
(我吃https://github.com/...
)仍然没有have一个名为mirror
,你的 Git 会对自己说:呵呵。没有命名的分支mirror
。最好不要推动任何东西。
(如果明天 GitHub 上的另一个 Gitdoes有一个名为mirror
,你的 Git 会对自己说:啊哈!有一个分支叫mirror
!好的,我会要求其他 Git 更新它的mirror
.)
为什么不“镜子推主”?
因为事实并非如此。即使您重新配置push.default
,没有默认设置意味着“如果我未能给出git push
一份参考规格,制作一个不匹配的规格。”
关于参考规范的简短片段
所有这一切都基于一个概念refspec。在 Git 中,refspec 本质上是一对参考文献.
A 参考是“分支或标签名称”的花哨词。 (它可以不仅仅是这两个,但它们是主要的两个。)像这样的分支名称master
是其完整拼写的简写,refs/heads/master
. This 参考 name, refs/heads/master
,是 Git 表达“不只是master
,但是branch master
“。一个简短的标签名称,例如v1.2
是参考名称的简写refs/tags/v1.2
。如果您省略refs/heads/
or refs/tags/
部分,Git 通常通过查看您现在拥有的分支和标签来确定您指的是哪一个。
无论如何,一个refspec大多只是two这些带有冒号的东西:
在中间:
refs/heads/master:refs/heads/master
例如。你需要其中两个,因为你正在使用两个 Git:一个在你的系统上,你要求它做某事,另一个在某些系统上remote, 例如gitlab
or github
。您让您的 Git 通过网络电话呼叫另一个 Git。然后你的 Git 和他们的 Git 互相对话,之后你的 Git 将fetch or push things.
获取和推送步骤需要每个 Git 的一个引用,因此这意味着您需要two参考文献:refspec。
refspec 的两半是source和目的地。如果你正在跑步git fetch
,源是otherGit,目的地是您自己的 Git。如果你正在跑步git push
, you是来源;另一个 Git 成为目的地。但无论哪种情况,源都会向目标提供一些提交,然后源的name— refspec 的左半部分 — 用于更改目的地的某些内容name— 参考规格的右半部分。
For git fetch
,两边有不同的名字是完全正常的。我们取自 their refs/heads/master
and write to我们自己的refs/remotes/origin/master
。我们从他们那里获取refs/heads/master
并写给我们自己的refs/remotes/mirror/master
。这让我们可以从许多不同的地方获取数据,但又保持它们完整。
For git push
,不过,使用更正常same每边都有名字。我们从他们那里获取master
,进入我们的refs/remotes/.../master
。然后我们工作一段时间并确保里面有什么our master
是在他们的基础上进行的更新master
,例如通过合并或变基。然后我们再次打电话给他们,交付我们的新承诺,并要求他们设置他们的master
——不是他们的nando/master
,他们甚至没有,但他们master
——基于他们之前的提交的最新提交。
我们确保它建立在他们的基础上,先获取,然后工作,然后推送。如果我们输掉了与 Sofia 的“比赛”——我们都在同一时间获取数据,但她工作得更快,然后她在我们之前推动——我们会得到“远程拒绝”“不快进”错误;我们必须再次获取,从 GitHub 或其他地方获取 Sofia 的工作,并使我们的工作构建在她的工作之上,然后再次尝试推送。
“本地过时”是什么意思?
当你的git remote show
调出遥控器——具体来说github
, i.e., https://github.com/nandoquintana/repo.git
——通过网络电话,other吉特 说:
I have these references:
refs/heads/master <some big ugly hash ID>
(尝试运行git ls-remote github
看看他们有什么,您将获得完整的列表)。
你自己的 Git 有一个名为master
,但是又大又难看的哈希IDyourGit 有your refs/heads/master
—your master
分支——是不同的。
由于两者不同,您的 Git 会假设您要么“领先”(您有一些他们没有的提交),要么“落后”(他们有一些您没有的提交),或者两者都有。你的 Git 无法告诉你如何far落后于你,如果你落后的话,但它can通过查看您的所有提交来了解您“领先”多远。如果你有承诺129bca4f...
谁的父母是e033fc12...
, and they正在提交e033fc12...
,那么您仅领先一次提交。
如果您的 Git 可以在您的 Git 中找到其 Git 的提交哈希 IDmaster
分支的历史,你是“领先的”,你可能可以git push
现在向他们发送您的新提交,要求他们设置他们的master
to 129bca4f...
,他们可能会接受提交并更新他们的master
.
但如果他们已经承诺930ab988...
你呢don't即使有该提交,您的 Git 所知道的只是他们有一些您没有的提交。你一定是“落后”的。你可以git fetch
从他们那里获得他们拥有而你没有的所有承诺,并记住它们refs/remotes/github/master
。然后你可以做任何需要做的事情add那些对你自己的承诺master
,这样你就可以与他们持平——既不领先也不落后——并做任何额外的工作,这样你现在就可以ahead of them.
由您决定这是否是一个好主意,如果是,是否要这样做。全部git remote show
就是打电话给他们,使用git ls-remote
,通过网络电话,将他们的参考资料与您的参考资料进行比较,以猜测是什么git fetch
and git push
根据这些结果会做。 (如果您使用git pull
,这仅仅意味着run git fetch
,然后运行git merge
. The git remote show
命令也尝试猜测这会做什么。)