假设您的 Git 工作版本是 pre-2.0(您的评论表明它可能是 1.8),这就是您的家庭 Git(2.0 或更高版本)和工作 Git(pre-2.0)行为不同的原因。
在 Git 2.0 中,push.default 的默认值从 matching 更改为 simple。从 Git 1.8.0 开始,Git 开始生成有关此的警告消息。有关详细信息,请参阅Warning: push.default is unset; its implicit value is changing in Git 2.0。 Git 版本 2.8.0 删除了警告。
请注意,您可能更喜欢current 而不是simple。见"simple" vs "current" push.default in git for decentralized workflow。但是,设置上游很有用:如果您愿意,请参阅 Why do I need to do `--set-upstream` all the time? 了解更多背景信息。
配置
无论是因此,还是仅仅因为您决定应该配置它,您可能已经为 push.default 设置了自己的值,无论是在任何特定存储库中,还是为您自己的个人所有存储库范围内的 @987654334 @ 环境。 (请注意,如果您 git config --global 某些设置,然后还 git config 在一个特定存储库中本地设置 same 设置,则本地设置通常会覆盖。此规则有一些例外情况,例如,对于branch.master.fetch,但使用--global! 将其设置为任何东西往往是不明智的)
匹配、简单等模式
如果您没有设置它,或者在您的工作设置中将其明确设置为matching,但在您的家庭设置中设置为simple。这两种模式的不同动作说明了这个问题。 matching 的行为在Warning: push.default is unset; its implicit value is changing in Git 2.0 的公认答案中有所描述,Default behavior of "git push" without a branch specified 中的更多内容有所描述——但请注意,这两者都描述了你运行后得到的结果:
git push sensorAtHome
或:
git push
但不是:
git push sensorAtHome pull-down-to-refresh
更准确地说,描述总是开始谈论当你在没有 refspecs 的情况下推送时会发生什么。 (稍后我们将讨论 refspecs。)
push.default 实际上有五种 种可能的设置(尽管新标准simple 仅在 Git 1.7.11 版本中引入,仍然有一些人在使用 Git 1.7)。这五个设置是nothing、current、upstream、simple和matching。
nothing 设置实际上是最简单的设置,但我试了一下,发现它很烦人。 :-) 它迫使您命名要推送的分支。因此,我们大多可以忽略它,只考虑其他四个。
如果你不指定任何分支,其他四个设置将直觉一些分支或分支推送。更准确地说,如果你省略了所有 refspecs,这四个设置很直观。但是当你包含一些参考规范时,它们也会影响发生的事情。
git push 语法
如果我们忽略所有标志参数,syntax for git push 是:
git push <repository> <refspec> <refspec> ...
也就是说,git push 之后的 first 参数(也跳过任何标志和标志参数)是 repository。您可以在此处写出完整的 URL,例如:
git push https://github.com/...
但通常使用 remote 会更好,它是一个短名称,例如 origin,或者在您的情况下为 sensorAtHome。对于git push,远程大多只是避免每次都必须输入一个长 URL(对于git fetch,它也提供了 remote-tracking 分支的origin/ 部分 名称)。
在 repository 参数之后,任何剩余的参数都是 refspecs。 repository 参数实际上是可选的,但如果您想提供任何 refspec 参数,您必须首先提供一个 repository 参数。但是 到底是什么?我们为什么要关心他们?
参考规范
最简单的 refspec 形式就是您在此处使用的形式:它只是一个分支名称。你写:
git push someremote branch
然后 Git 推送指定的分支。但 refspecs 实际上更通用。
首先,参考规范以冒号分隔的两部分开始。例如,您可以写:
git push someremote branch:branch
左边的名字是你的名字,右边的名字是他们的名字。请记住,当您运行git push 时,您使用的是两个 Git,具有两个不同的存储库。您正在告诉您的 Git 调用某个远程 Git。一旦您的 Git 在互联网电话上拥有另一个 Git(通过 https 或 ssh 或其他方式),您的 Git 会将您的一些提交发送到他们的 Git,然后您的 Git 要求他们设置 他们的 分支,通常基于您刚刚发送的提交。
由于有两个 Git,因此涉及到两个不同的分支名称。例如,您的分支可能被命名为 Fred,而他们的分支可能被命名为 Frederick-the-Great。你的可能是赞福德,而他们的可能是 Beeblebrox。你的分支是你的,他们的分支可能是你的上游。没有要求它们具有相同的名称——嗯,几乎没有要求。而且,如果你从字面上拼出这两个部分,写 zaphod:beeblebrox 或其他什么,Git 会假设你知道自己在做什么,并以此运行。
但是,如果这些名称不相同,事情就会变得非常疯狂。如果它们一直都匹配,那就要简单得多。因此,四个“有趣”设置中的三个——matching、current 和 simple——尝试确保它们保持相同。你只需要使用你的名,你的Git会尝试确保他们的名匹配。
不这样做的一个设置——upstream 模式——告诉你的 Git 使用你身边的 your 名字,以及你配置为 upstream的任何东西> 他们方面的设置。显然,要使其正常工作,您必须设置一个上游。但这仍然会留下 matching、current 和 simple,并且可能会让您想知道它们的用途。
简短的回答是 matching 是 Git 最初所做的,但结果证明这是一个错误,你可能永远不应该使用它。您应该改用simple 或current。 simple 设置更安全,但需要您设置上游。同样,要了解更多信息并帮助您在它们之间进行选择,请参阅 "simple" vs "current" push.default in git for decentralized workflow。
如果您提供至少一个 refspec,旧的 matching 设置就像 current 一样工作。你的 Git 使用你提供的 refspec 或 refspecs(即分支名称)——记住,这仅适用于你没有写 <em>local-name</em>:<em>remote-name</em>,所以只有一个本地名称——并让他们的 Git 创建或更新一个分支同名,您的分支是否有上游集。 但是如果您省略 所有 refspecs,matching 会告诉您的 Git 向他们的 Git 询问 所有他们的分支,并查找所有你的分支,并匹配名称。无论名称相同,您的 Git 都会将您的提交发送到他们的 Git,并要求他们设置同名分支。
对于大多数人来说,在大多数情况下,这种差异很小。你有你的master,也许还有你的develop 和一两个功能分支。你git fetch 来获取新东西,工作一段时间,git push 发送你写的东西。你的 Git 要求他们的 Git 更新 master 和 develop 你的功能分支。如果你不应该在master 上工作,并且你没有在master 上工作——只是在develop 上工作——你的@987654392 中什么都没有@为你的Git推送,所以没有问题。即使其他人向其他 Git 的 master 推送了一些新的东西,你也只是因为错误而拒绝了你的部分推送:你的 develop 更改被推送,并且你尝试从他们的 master 中删除他们的新提交时遇到了错误。
但是看:你只是要求你的 Git 从他们的master 中删除他们的新提交。这是一个不好的迹象,如果没有别的。而且,如果你在一个特性分支上做了一些实验性的工作,但它实际上还没有准备好推送,并且你打算修复一些东西并在那个特性分支中重新定位一些错误的提交,你可能只是不小心推送了 bothdevelop和那个特性分支。
周围都很糟糕。 current 设置与matching 设置非常相似,但默认情况下它只推送 一个 分支,这是您现在签出的分支。
simple 设置与current 设置类似,但多了一条安全带:当前分支需要将其上游设置到另一个 Git 中的同名分支。
Refspecs 比分支更通用
为了完整起见,我想再提一些关于 refspec 的内容。一是他们不必命名分支:您也可以命名标签。你的 Git 通常会弄清楚你指的是哪一个,前提是你不要对标签和分支使用 same 名称(不要这样做——Git 有一组定义的规则,但它们很奇怪且有冲突,会让你感到困惑)。您可以拼出任何引用的“全名”:refs/heads/master、refs/tags/v1.2 等等。你可以省略本地名称,写:delete,要求他们的Git删除一个分支或标签或其他引用。最后,你可以设置一个 per-refspec force 标志。
总结
这是push.default 的五种可能设置:
-
nothing:您必须至少包含一个 refspec 参数(这会强制您也包含 remote 部分)。这个设置真的不会出错。问题是它很烦人,也就是说,你也不能直接走。
-
matching:这是旧的 2.0 之前的 Git 行为。它可以推动太多的分支,所以除非你真的很固执,否则不要使用它。 :-)
-
current:这是 matching 的表现更好的变体。
-
simple:这与 current 相同,但添加了安全检查,即您的分支需要具有相同的基本分支名称的上游集。安全检查可能有点烦人:它迫使您设置上游。不过,设置上游的价值不仅仅是让simple 开心,所以大多数时候这对大多数人来说确实是最好的push.default。
-
upstream:这是一个有点疯狂的案例,由于某种原因,您必须将您的分支命名为 fred,即使上游是 ginger 或其他。这是simple 的一种更宽松的变体:您仍然需要设置上游,但您可以将其设置为乘坐疯狂的火车旅行。