Git跟踪一个远程分支,但推送到另一个分支?

时间:2016-06-29 22:03:12

标签: git bitbucket

假设我有一个叫做“我的本地更改”的分支,这是一个本地分支,它是从名为“远程分支”的分支创建的,其中是一个遥远的分支。

我们还假设有第三个分支称为“开发”,这是一个远程分支,代码从多个分支机构中拉出(' some-remote-branch' ;是其中之一,我还有一个名为“开发”的本地分支跟踪远程开发分支。

我的问题是如何设置“我的本地更改”#39;跟踪“发展”分支,但推进分支机构的远程分支机构'

对于那些好奇的人,至于我为什么要这样做,我希望能够运行git状态,看看我是否落后于开发'而不必切换到那个分支,并且很容易仍然可以推送到某个远程分支'

我目前的流程如下(我也非常喜欢改善这一点的建议)

git checkout -b my-local-branch some-remote-branch

(进行一些更改并添加)

git fetch origin 
git checkout develop
git status

(执行此操作以查看我需要合并的开发是否有任何更改,如果没有运行)

git push origin my-local-branch some-remote-branch

1 个答案:

答案 0 :(得分:4)

(不知道为什么这个问题被低估了, 1 你自己几乎已经自己回答了......)

您就在那里:只需将push.default配置为simplenothing,以便您必须为此案例指定推送目标,然后为你的最后一个命令,使用:

git push origin my-local-branch:some-remote-branch

这种方法的工作方式是git pushorigin(遥控器的名称)之后采用一系列 refspecs 。 refspec不是很复杂:它只是一对名称,例如master:masterdevelop:developdevelop:foo,可选择带有前导加号+ ,并可选择省略第一个或第二个名称::foodevelop

Refspecs稍微复杂一点,因为当你遗漏两个名字中的一个时,它们在git fetchgit push中的工作方式不同。如果每次都使用这两个名称,则它们保持简单:左侧的名称是 source 存储库中的名称,右侧的名称是目标。对于fetch,源是远程的,目标是您自己的存储库。对于push,源是您的存储库,目标是远程。

省略源名称仅适用于push,在这种情况下,它意味着删除。因此,git push origin :foo表示删除远程foo 上的origin。 (那不是你想要的,所以要避免这种情况。)

保留目的地名称适用于fetchpush,但对他们来说意味着不同的事情。我们在这里忽略fetch。使用push,意味着在本地和远程上使用相同的名称。由于您不想想要这里,所以不要在这里使用它。 (或者,对于那些想要它的情况,请继续使用它。)

前导+符号(如果存在)与--force相同。 (实际上--force只会在所有内容上添加+。)

如果您运行git push origingit push(甚至没有 remote 参数),Git会查找push.default以查看要推送的内容。将其设置为nothing意味着只是失败/错误输出,因此我必须输入refspec 。将其设置为simple意味着只将一个分支(当前分支)推送到当前分支的上游,但也要求上游名称匹配。由于my-local-branchsome-remote-branch不匹配,因此本地分支foo正在跟踪远程跟踪分支origin/develop :名称foodevelop不匹配。

无论哪种方式,Git都会强迫你为这次推送输入一个refspec。

使用nothing配置时,Git会强制您输入每次推送的refspec。 (我已经使用了它并且它有效,但它并不是非常方便。)使用simple配置,Git将允许您轻松地将develop推送到上游develop ,并且允许您明确地将foo推送到上游develop(或上游jazzy或任何其他名称,而不是foo),但不会将foo推送到foo,因为它不是其定义的上游。 (我已经使用了它,效果更好。)

从Git 2.0版开始,simple是默认配置。因此,如果你有Git 2.0或更高版本,那么你已经很好了。如果没有,看看你是否可以升级你的Git版本,但push.default可以配置为早在Git 1.6版本。 (我不确定它可以采用什么值。那么,如果不是更早的话,当前的5个值会回到1.7.11。)

为完整起见,其他三个可能的值为:currentupstreammatchingcurrent值表示使用当前分支的名称:git push origin $branch:$branch其中$branch是当前分支。 upstream值表示使用当前分支的上游名称:git push origin $branch:$merge,其中$merge来自git config --get branch.$branch.merge

matching值是最难描述的,并且是Git 2.0版之前的默认值:它意味着获取遥控器上每个分支的列表,并匹配它们的名称和我们的本地分支名称,然后将所有本地分支机构全部推送到遥控器上同名分支,两个名称匹配的地方。这不是一个非常安全的设置,尽管只要你不要使用--force,它实际上在实践中效果很好,这就是它可以使用多年的原因。

附注:术语

Git的术语有点乱。

  • 本地分支(或只是"分支"或"分支名称"),如master,是refs/heads/名称空间中的名称。它指向一个提交ID。当您在该分支上进行新的提交时,Git读取提交ID,使用该ID作为新提交的父级进行新提交,然后将新提交的ID写入分支名称,以便分支现在指向新提交(转而指向前一个分支提示,依此类推)。

    您可以git checkout一个本地分支,它会让您在分支上播放",以便git statusOn branch master。如上所述,这设置了新的提交以推进分支。

  • origin/master之类的远程跟踪分支refs/remotes/名称空间中的名称。在refs/remotes/之后,我们找到了遥控器本身的名称origin,然后是另一个斜杠,最后是在该遥控器上看到的分支的名称(当然没有refs/heads/)。这些名称存储在本地存储在您自己的存储库中:它们实际上根本不是远程的。当您的Git通过git fetch和(在更有限的范围内)通过git push与远程联系时,它们只是自动更新

    您可以git checkout远程跟踪分支,但如果您这样做,git checkout会让您进入"分离的HEAD"模式,以便git statusgit branch声称您不在任何分支上(或者在"没有分支"或类似,有时使用"分离的HEAD& #34;措辞)。当发生这种情况时,您实际上是在(单个,特殊的)匿名分支上。当你回到普通分支时,你在匿名分支上所做的任何工作最终都会逐渐消失。 (因此,如果你想保留工作,设置一个名称,以便它不再是匿名的 - 或者在你做这项工作之前使用git checkout回到常规分支。)

  • 本地分支可以跟踪另一个分支(本地远程)。当本地分支 B 跟踪另一个分支 U 时,Git将其称为"上游"当地分公司这个上游由两部分组成:遥控器的名称,如origin,以及遥控器上看到的分支名称,如master。要将本地分支作为分支 B 的上游进行跟踪,Git只需将远程设置为.

    因此,如果配置了这两个项目,则本地分支 B 正在跟踪上游 U U 本身通常是远程跟踪分支,它是一个本地实体(其中一个refs/remotes/名称空间名称)。您必须git fetchgit push更新远程跟踪分支,之后git statusgit branch -vv将报告跟踪远程跟踪分支的本地分支机构,作为领先和/或落后于同行。

    本地分支 B 可以改为跟踪另一个本地分支作为其上游。在这种情况下,由于所有内容都已在本地更新,git statusgit branch -vv将是最新的,不需要任何git fetch

    当然,本地分支 B 无需跟踪任何内容。命令git branch --set-upstream-to upstreamgit branch --unset-upstream将设置或取消设置当前分支的上游。您还可以使用branch.$branch.remote设置,更改和检查上游的两个部分(branch.$branch.mergegit config部分),尽管使用git branch通常更好,更方便。

1 也许downvote是因为Git 2.0默认push.default