Git 跟踪远程分支但推送到不同的分支?
Git track a remote branch but push to a different branch?
假设我有一个名为 'my-local-changes' 的分支,它是一个本地分支,它是从一个名为 'some-remote-branch' 的分支创建的,它是一个远程分支。
我们还假设有第三个分支叫做'develop',它是代码从多个分支拉入的远程分支('some-remote-branch'是其中之一,我也有一个本地分支称为 'develop' 跟踪远程开发分支)
我的问题是如何设置 'my-local-changes' 来跟踪 'develop' 分支,但推送到分支 'some-remote-branch'?
对于那些好奇的人,至于我为什么要这样做,我希望能够 运行 git status 看看我是否落后于 'develop' 而没有切换到那个分支,仍然可以轻松地推送到 'some-remote-branch'
我目前的流程如下(我也很乐意提出任何改进建议)
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 反正你几乎已经自己回答了...)
你就快完成了:只需将push.default
配置为simple
或nothing
,这样你必须为此指定推送目标案例,然后对于您的最终命令,请使用:
git push origin my-local-branch:some-remote-branch
其工作方式是 git push
在 origin
(遥控器的名称)之后采用一系列 refspecs。 refspec 不是很复杂:它只是一对名称,如 master:master
,或 develop:develop
,或 develop:foo
,可选地带有前导加号 +
,并可选地省略名字或名字::foo
或 develop
.
Refspecs 变得稍微复杂一些,因为它们在 git fetch
和 git push
中的工作方式不同,当您省略这两个名称之一时。如果您每次都使用这两个名称,它们将保持简单:左侧的名称是 source 存储库中的名称,右侧的名称是 中的名称]目的地。对于 fetch
,源是远程,目标是您自己的存储库。对于 push
,源是您的存储库,目标是远程。
省略源名称仅适用于 push
,在本例中,这意味着 删除。因此 git push origin :foo
意味着 删除远程 origin
上的 foo
。 (这不是你想要的,所以请避免。)
省略目的地名称对 fetch
和 push
都有效,但对它们意味着不同的事情。让我们在这里忽略 fetch
。对于 push
,这意味着 在本地和远程上使用相同的名称。既然你不想要它,就不要在这里使用它。 (或者,对于您 需要的情况,请继续使用它。)
开头的 +
符号(如果存在)与 --force
的含义相同。 (实际上 --force
只是在所有内容上添加 +
。)
如果您 运行 git push origin
,或 git push
(甚至没有 remote
参数),Git 查找 push.default
以查看要推送的内容。将其设置为 nothing
意味着 只是失败/错误输出,因此我必须输入 refspec。设置为 simple
意味着 只将一个分支,即当前分支推送到当前分支的上游,但还要求上游名称匹配 。由于 my-local-branch
和 some-remote-branch
不匹配,对于 local branch foo
is tracking remote-tracking branch origin/develop
[=196] 的情况,这将失败=]: 名称 foo
和 develop
不匹配。
无论哪种方式,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 就可以配置。 (那么我不确定它可以采用什么值。我认为当前的 set-of-5 值可以追溯到 1.7.11,如果不是更早的话。)
为了完整起见,其他三个可能的值是:current
、upstream
和 matching
。 current
值表示使用当前分支的名称: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的术语有点乱。
A local branch (or just "a branch" or "a branch name"), like master
, is a name in refs/heads/
名字-space。它指向一个提交 ID。当您在该分支上进行新提交时,Git 读取提交 ID,使用该 ID 作为新提交的父项进行新提交,然后将新提交的 ID 写入分支名称,以便branch 现在指向新的提交(它又指向以前的分支提示,依此类推)。
你可以 git checkout
一个本地分支,它会把你放在 "on the branch" 上,这样 git status
就会说 On branch master
。正如我在上面提到的那样,这会进行设置,以便新提交推进分支。
A remote-tracking branch like origin/master
是refs/remotes/
name-space中的一个名字。在 refs/remotes/
之后,我们找到遥控器本身的名称,origin
,然后是另一个斜杠,最后是在该遥控器上看到的分支名称(当然没有 refs/heads/
)。这些名称存储在本地,在您自己的存储库中:它们实际上根本不是远程的。当您的 Git 通过 git fetch
和(在更有限的范围内)通过 git push
.[=108 联系遥控器时,它们只是 自动更新 =]
您可以 git checkout
远程跟踪分支,但如果您这样做,git checkout
会将您置于 "detached HEAD" 模式,因此 git status
和 git branch
声称你不在任何分支上(或者在 "no branch" 或类似的分支上,有时使用 "detached HEAD" 措辞)。当这种情况发生时,你实际上是在(单一的,特殊的)anonymous 分支上。当您回到正常分支时,您在匿名分支上所做的任何工作最终都会消失。 (所以如果你想保留工作,设置一个名字,这样它就不再是匿名的——或者在你做那项工作之前使用 git checkout
回到常规分支。)
本地分支可以跟踪另一个分支(本地或远程)。当本地分支B正在跟踪另一个分支U时,Git称其为本地分支的"upstream"。这个上游由两部分组成:远程名称,如 origin
,以及在远程上看到的分支名称,如 master
。要跟踪本地分支作为分支 B 的上游,Git 只需将遥控器设置为 .
。
因此本地分支 B 正在跟踪上游 U 如果它配置了这两项。 U 本身通常是一个远程跟踪分支,它是一个本地实体(refs/remotes/
名称-space 名称之一)。您必须 git fetch
或 git push
才能更新远程跟踪分支,之后 git status
和 git branch -vv
将报告正在跟踪远程跟踪分支的本地分支,领先 and/or 落后于同行。
本地分支 B 可以改为跟踪另一个本地分支作为其上游。在这种情况下,由于所有内容都是本地更新的,因此 git status
和 git branch -vv
将是最新的,而不需要任何 git fetch
。
A 本地分支 B 当然不需要跟踪任何东西。命令 git branch --set-upstream-to <em>upstream</em>
和 git branch --unset-upstream
将设置或取消设置上游当前分支。您还可以使用 git config
设置、更改和检查上游的两个单独部分(branch.$branch.remote
和 branch.$branch.merge
部分),尽管使用 git branch
通常更好并且更方便。
1可能是因为 Git 2.0 默认值 push.default
。
假设我有一个名为 'my-local-changes' 的分支,它是一个本地分支,它是从一个名为 'some-remote-branch' 的分支创建的,它是一个远程分支。
我们还假设有第三个分支叫做'develop',它是代码从多个分支拉入的远程分支('some-remote-branch'是其中之一,我也有一个本地分支称为 'develop' 跟踪远程开发分支)
我的问题是如何设置 'my-local-changes' 来跟踪 'develop' 分支,但推送到分支 'some-remote-branch'?
对于那些好奇的人,至于我为什么要这样做,我希望能够 运行 git status 看看我是否落后于 'develop' 而没有切换到那个分支,仍然可以轻松地推送到 'some-remote-branch'
我目前的流程如下(我也很乐意提出任何改进建议)
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 反正你几乎已经自己回答了...)
你就快完成了:只需将push.default
配置为simple
或nothing
,这样你必须为此指定推送目标案例,然后对于您的最终命令,请使用:
git push origin my-local-branch:some-remote-branch
其工作方式是 git push
在 origin
(遥控器的名称)之后采用一系列 refspecs。 refspec 不是很复杂:它只是一对名称,如 master:master
,或 develop:develop
,或 develop:foo
,可选地带有前导加号 +
,并可选地省略名字或名字::foo
或 develop
.
Refspecs 变得稍微复杂一些,因为它们在 git fetch
和 git push
中的工作方式不同,当您省略这两个名称之一时。如果您每次都使用这两个名称,它们将保持简单:左侧的名称是 source 存储库中的名称,右侧的名称是 中的名称]目的地。对于 fetch
,源是远程,目标是您自己的存储库。对于 push
,源是您的存储库,目标是远程。
省略源名称仅适用于 push
,在本例中,这意味着 删除。因此 git push origin :foo
意味着 删除远程 origin
上的 foo
。 (这不是你想要的,所以请避免。)
省略目的地名称对 fetch
和 push
都有效,但对它们意味着不同的事情。让我们在这里忽略 fetch
。对于 push
,这意味着 在本地和远程上使用相同的名称。既然你不想要它,就不要在这里使用它。 (或者,对于您 需要的情况,请继续使用它。)
开头的 +
符号(如果存在)与 --force
的含义相同。 (实际上 --force
只是在所有内容上添加 +
。)
如果您 运行 git push origin
,或 git push
(甚至没有 remote
参数),Git 查找 push.default
以查看要推送的内容。将其设置为 nothing
意味着 只是失败/错误输出,因此我必须输入 refspec。设置为 simple
意味着 只将一个分支,即当前分支推送到当前分支的上游,但还要求上游名称匹配 。由于 my-local-branch
和 some-remote-branch
不匹配,对于 local branch foo
is tracking remote-tracking branch origin/develop
[=196] 的情况,这将失败=]: 名称 foo
和 develop
不匹配。
无论哪种方式,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 就可以配置。 (那么我不确定它可以采用什么值。我认为当前的 set-of-5 值可以追溯到 1.7.11,如果不是更早的话。)
为了完整起见,其他三个可能的值是:current
、upstream
和 matching
。 current
值表示使用当前分支的名称: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的术语有点乱。
A local branch (or just "a branch" or "a branch name"), like
master
, is a name inrefs/heads/
名字-space。它指向一个提交 ID。当您在该分支上进行新提交时,Git 读取提交 ID,使用该 ID 作为新提交的父项进行新提交,然后将新提交的 ID 写入分支名称,以便branch 现在指向新的提交(它又指向以前的分支提示,依此类推)。你可以
git checkout
一个本地分支,它会把你放在 "on the branch" 上,这样git status
就会说On branch master
。正如我在上面提到的那样,这会进行设置,以便新提交推进分支。A remote-tracking branch like
origin/master
是refs/remotes/
name-space中的一个名字。在refs/remotes/
之后,我们找到遥控器本身的名称,origin
,然后是另一个斜杠,最后是在该遥控器上看到的分支名称(当然没有refs/heads/
)。这些名称存储在本地,在您自己的存储库中:它们实际上根本不是远程的。当您的 Git 通过git fetch
和(在更有限的范围内)通过git push
.[=108 联系遥控器时,它们只是 自动更新 =]您可以
git checkout
远程跟踪分支,但如果您这样做,git checkout
会将您置于 "detached HEAD" 模式,因此git status
和git branch
声称你不在任何分支上(或者在 "no branch" 或类似的分支上,有时使用 "detached HEAD" 措辞)。当这种情况发生时,你实际上是在(单一的,特殊的)anonymous 分支上。当您回到正常分支时,您在匿名分支上所做的任何工作最终都会消失。 (所以如果你想保留工作,设置一个名字,这样它就不再是匿名的——或者在你做那项工作之前使用git checkout
回到常规分支。)本地分支可以跟踪另一个分支(本地或远程)。当本地分支B正在跟踪另一个分支U时,Git称其为本地分支的"upstream"。这个上游由两部分组成:远程名称,如
origin
,以及在远程上看到的分支名称,如master
。要跟踪本地分支作为分支 B 的上游,Git 只需将遥控器设置为.
。因此本地分支 B 正在跟踪上游 U 如果它配置了这两项。 U 本身通常是一个远程跟踪分支,它是一个本地实体(
refs/remotes/
名称-space 名称之一)。您必须git fetch
或git push
才能更新远程跟踪分支,之后git status
和git branch -vv
将报告正在跟踪远程跟踪分支的本地分支,领先 and/or 落后于同行。本地分支 B 可以改为跟踪另一个本地分支作为其上游。在这种情况下,由于所有内容都是本地更新的,因此
git status
和git branch -vv
将是最新的,而不需要任何git fetch
。A 本地分支 B 当然不需要跟踪任何东西。命令
git branch --set-upstream-to <em>upstream</em>
和git branch --unset-upstream
将设置或取消设置上游当前分支。您还可以使用git config
设置、更改和检查上游的两个单独部分(branch.$branch.remote
和branch.$branch.merge
部分),尽管使用git branch
通常更好并且更方便。
1可能是因为 Git 2.0 默认值 push.default
。