为什么我必须设置我在本地创建的新分支的上游?

时间:2017-02-19 14:34:17

标签: git

我认为我的git配置存在问题,

每当我创建一个新的分支时,我首先必须设置上游

git push --set-upstream sensorAtHome pull-down-to-refresh

其中sensorAtHome是我的项目名称,pull-down-to-refresh是分支名称。

实际上我没有必要在我的工作场所这样做,我简单创建分支做我的工作提交和推送,我从来没有设置 - 上游但我在家里的项目当我推送到GitHub.com我必须..

我的工作流程中是否有一些我遗漏的错误?

1 个答案:

答案 0 :(得分:5)

假设您的Git工作版本是2.0之前(您的评论表明它可能是1.8),那么这就是您的家庭Git(2.0或更高版本)和工作Git(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放弃了警告。

请注意,您可能更喜欢currentsimple。见"simple" vs "current" push.default in git for decentralized workflow。但是,设置上游非常有用:如果您愿意,请参阅Why do I need to do `--set-upstream` all the time?继续阅读以获取更多背景信息。

配置

无论是这样,还是仅仅因为您决定应该对其进行配置,您可能已经为任何特定存储库中的push.default设置了自己的值,或者为您自己的个人全存储库设置了自己的值--global设置。 (请注意,如果您在一个特定存储库中git config --global进行了某些设置,然后还git config 相同的设置,则本地设置通常会覆盖。此例外有一些例外情况。规则,例如,对于branch.master.fetch,但将{1}设置为任何内容往往是不明智的!)

匹配,简单和其他模式

如果设置它,或者已将其明确设置为工作设置中的--global,而是设置为家庭设置中的matching。这两种模式的不同行为解释了这个问题。 simple的行为在Warning: push.default is unset; its implicit value is changing in Git 2.0的已接受答案中有所描述,Default behavior of "git push" without a branch specified中的更多内容 - 但请注意,这两者都描述了您在运行时获得的内容:

matching

或:

git push sensorAtHome

git push

更准确地说,描述总是开始讨论当你没有 refspecs 推送时会发生什么。 (我们将在短时间内得到refspec。)

git push sensorAtHome pull-down-to-refresh 实际上有五个可能的设置(虽然新标准push.default仅在Git 1.7.11版中引入,但仍有一些人使用Git 1.7)。这五个设置包括simplenothingcurrentupstreamsimple

matching设置实际上是最简单的,但我尝试了它并发现它很烦人。 :-)它强制您命名要推送的分支。因此,我们大多可以忽略它,只考虑其他四个。

如果您没有指定任何分支,其他四个设置将直接推送某些分支或分支以推送。更准确地说,如果省略所有 refspecs ,这四个设置就会直截了当。但是,当你包含一些refspecs时,它们也会影响会发生什么。

nothing语法

如果我们忽略所有的flags参数,syntax for git push是:

git push

也就是说,git push <repository> <refspec> <refspec> ... 之后的第一个参数(也跳过任何标志和标志参数)是存储库。您可以在此处写出完整的URL,例如:

git push

但使用远程通常要好得多,远程是一个简短的名称,如git push https://github.com/... ,或者在您的情况下,origin。对于sensorAtHome,远程主要是避免每次都必须输入一个长URL(对于git push 提供远程的git fetch部分 - 跟踪分支名称)。

存储库参数之后,任何剩余的参数都是 refspecs 。 repository参数实际上是可选的,但如果您想要提供任何refspec参数,则必须首先提供存储库参数。但究竟什么一个refspec?我们为什么要关心他们?

Refspecs

refspec最简单的形式就是你在这里使用的形式:它只是一个分支名称。你写道:

origin/

和Git推送命名分支。但refspecs实际上更为通用。

首先,refspec开始时用冒号分隔两部分。例如,您可以写下:{/ p>,而不只是说git push someremote branch

branch

左侧的名称是您的名称,右侧的名称是他们的名称。请记住,当您运行git push someremote branch:branch 时,您正在使用两个 Gits,以及两个不同的存储库。你告诉你的Git打电话给一些远程Git。一旦你的Git在网络电话上有另一个Git(通过https或ssh或其他),你的Git会将你的一些提交发送给他们的Git,然后你的Git要求他们设置他们的分支,通常基于您刚发送的提交。

由于有两个Gits,因此涉及两个不同的分支名称。你的分支可能被命名为弗雷德,例如,他们的名字可能被命名为弗雷德里克。你的可能是Zaphod,他们可能是Beeblebrox。您的分支是您的,其分支可能是您的上游。没有要求它们具有相同的名称 - 好吧,几乎没有要求。而且,如果你真的拼写出两个部分,写git push或其他什么,Git假设你知道你在做什么,并运行它。

如果这些名称​​不相同,事情会变得非常疯狂。如果它们始终匹配,那么更简单。所以,四个中有三个&#34;有趣的&#34;设置 - zaphod:beeblebroxmatchingcurrent - 尝试确保 保持相同。您只需使用 名称,Git就会尝试确保他们的名称匹配。

一个不执行此操作的设置 - simple模式 - 告诉您的Git在您身边使用您的名称,以及您配置为上游的任何内容< / em>设置他们的方面。显然,要使其工作,您必须设置上游。但是这仍然会留下upstreammatchingcurrent,并且可能会让您想知道它们的用途。

简短的回答是simple是Git最初所做的,但事实证明这是一个错误,你可能永远不应该使用它。您应该使用matchingsimple代替。 current设置更安全,但要求您设置上游。同样,如果需要更多信息并帮助您在它们之间进行选择,请参阅"simple" vs "current" push.default in git for decentralized workflow

如果您提供至少一个refspec,旧的simple设置就像matching一样。你的Git采用你提供的refspec或refspecs(即分支名称) - 请记住,这仅适用于你没有写current的情况,所以只有一个本地名称 - 并且他们的Git创建或更新一个具有相同名称的分支,你的分支是否有一个上游集。但如果你遗漏所有 refspecs,local-name:remote-name告诉你的Git向他们的Git询问所有他们的分支,然后查找所有你的分支,并匹配这些名称。如果名称相同,您的Git会将您的提交发送给他们的Git,并要求他们设置同名的分支。

对于大多数人来说,在大多数情况下,这种差异很小。您有matching,也许是您的master和一两个功能分支。你develop拿起新东西,工作一段时间,git fetch发送你写的东西。您的Git要求他们的Git更新您的功能分支git push master 。如果您不应该在develop上工作,那么 master上工作 - 仅在{{1}上在你的master中你的Git没有任何东西可以推动,所以没有问题。即使其他人向其他Git的主人推送了一些新东西,你也会因为错误而拒绝部分推送:你的develop更改被推送,并且你试图从他们的{{{ 1}}遇到错误。

但是看看:你刚刚要求你的Git从master删除他们的新提交。如果没别的话,这是一个不好的迹象。而且,如果你在一个功能分支上做了一些实验性的工作,并且它还没有准备好推进而你计划修复一些东西并在该功能分支中修改一些不好的提交,那么你可能只是意外地推动了< em>两者 develop 这些功能分支。

这一切都很糟糕。 master设置与master设置非常相似,但默认情况下只推送一个分支,这是您现在已经检出的分支。

develop设置就像current设置一样,但增加了一个安全带:当前分支需要将其上游设置为另一个Git中同名的分支。

Refspecs不仅仅是分支

为了完整起见,我想提一些关于refspecs的内容。一个是他们不必命名分支:你也可以命名标签。如果你不为标签和分支使用相同的名称,你的Git通常会找出你的意思(不要这样做 -Git对发生的事情有一套规定的规则,但它们很奇怪且冲突,会让你感到困惑)。你可以拼出&#34;全名&#34;任何参考:matchingsimple等等。您可以省略本地名称,方法是写current,要求他们的Git 删除分支或标记或其他参考。最后,您可以设置per-refspec force 标志。

摘要

以下是refs/heads/master的五种可能设置:

  • refs/tags/v1.2:您必须至少包含一个 refspec 参数(这会强制您包含远程部分)。这个设置你真的不会出错;问题是它很烦人,也就是说,你也不能正确。
  • :delete:这是旧的,2.0之前的Git行为。它可以推动太多分支,所以除非你真的很顽固,否则不要使用它。 : - )
  • push.default:这是nothing
  • 的表现更好的变体
  • matching:这与current相同,增加了安全检查,您的分支机构需要具有上游集,并具有相同的基本分支名称。安全检查可能有点烦人:它会强制您设置上游。设置上游的价值不仅仅是让matching满意,所以对大多数人来说这是最好的simple
  • current:这是针对稍微疯狂的情况,由于某种原因,即使上游是simple,或者其他什么,你必须为你的分支push.default命名。它是upstream的一种更宽松的变种:你仍然必须设置上游,但你可以设置它来乘坐疯狂的火车。