TL;博士
答案的简短版本归结为否,但没关系,不用担心,只需手动完成;这很容易。如果您有一个经常使用的特定分支,请编写脚本或 Git 别名来执行此操作。
中等的
要手动执行此操作,对于您想知道是否有新内容的分支Borigin/feature
,与您自己feature_my_tweaks
的上游设置为的分支相比origin/feature_my_tweaks
,只需运行:
git rev-list --count --left-right feature_my_tweaks...origin/feature
这会打印出两个数字。左边的数字feature_my_tweaks
是不属于origin/feature
. 右边的数字是你的提交数量,origin/feature
而不是你的提交数量feature_my_tweaks
。
如果第二个数字不为零,并且您想要,您现在可以运行git checkout feature_my_tweaks; git rebase origin/feature
or git checkout feature_my_tweaks; git merge origin/feature
。
是否使用以及何时使用git rebase
取决于您,但是在变基之后,您将需要git push --force origin feature_my_tweaks
(或git push --force-with-lease origin feature_my_tweaks
)让 Git放弃旧的提交,当它将您的提交复制到新的和改进的提交时origin
丢弃这些旧提交。git rebase
长
可能这里最大的问题是术语。跟踪这个词对您意味着什么?Git以至少三种不同的方式使用这个词,其中一种最多可以与您正在考虑的那个匹配。(可能没有一个完全匹配,这取决于您在这里的想法。)
无论您使用哪个词,以下是正确的思考方式:
重要的是提交。每个提交都有一个唯一的哈希 ID。任何地方的每一个 Git——这个存储库的每一个克隆——都使用那个哈希 ID 来进行那个提交。如果您有一个具有该哈希 ID 的提交,则它是相同的提交。如果你不这样做,你就没有那个提交。
Git 中的名称有多种形式。每个名称都有一个哈希 ID——只有一个!
您使用的三种形式是:
分支名称: master
、或develop
,等等。这些是你的,随你的便。(不过,您可能希望自己的名字与其他人的名字相匹配,至少在不同的时候。)feature
feature/one
标签名称: v2.1
等等。虽然你是你的,但你的 Git 会尝试与其他 Git 存储库共享它们:如果你的 Git 看到他们的有 av2.1
而你没有,你的 Git 很可能会将他们的复制到你的。
远程跟踪名称: origin/master
、origin/feature
等。Git 调用这些远程跟踪分支名称,有些人将其缩短为远程跟踪分支,但它们不太像分支名称。您的 Git 将这些从属于其他 Git 的分支名称。你让你的 Git 调用他们的 Git 并从他们那里获得任何新的提交。然后,您的 Git 会更新您的远程跟踪名称,使其与他们的名称匹配。
远程跟踪名称是通过将远程名称(在本例中为 )粘贴在它们的分支origin
名称前面来构建的,并用斜线将它们分开。这就是为什么您的“跟踪”它们的原因,每次运行时都会更新。2origin/master
master
git fetch origin
所有这些名称的工作方式都类似。它们都有长形式:refs/heads/master
是 的完整拼写master
,例如,vs refs/remotes/origin/master
for origin/master
。这就是 Git 知道哪个是哪个名称的方式。Git 通常会缩短名称以显示给您,去掉refs/heads/
分支名称的refs/remotes/
部分或远程跟踪名称的部分。
请注意,git fetch
它与 的对立面一样接近git push
。看起来这些应该是push
and pull
,但由于历史事故3它是push
and fetch
。拉只是意味着:运行 fetch,然后运行第二个 Git 命令,git merge
默认情况下,与当前分支的上游合并。
Fetch 和 push 非常相似,但有两个关键区别:
Fetch得到东西。你告诉你的 Git:调用你存储在该名称下的 URLorigin
(或您在此处使用的任何远程名称)的 Git。您的 Git 在该 URL 处调用服务器,该服务器必须作为 Git 存储库进行响应。然后,该服务器会告诉你它的分支名称和它们的提交,你的 Git 会检查你是否有这些提交。如果没有,您的 Git 会向他们的 Git 询问这些提交,如果您没有提交,则向其父级提交,如果需要,则向其父级提交,依此类推。他们给你所有他们有的提交,你没有,你的 Git 需要完成这些。
获得提交后,然后通过重命名其分支来git fetch
更新您的远程跟踪名称。
Push发送东西。和以前一样,您的 Git 调用另一个 Git,其远程名称如origin
. 然后你的 Git 给他们提交,而不是从他们那里得到提交。但在这里,情况略有不同:
您的 Git 提供的提交是您正在推送的任何分支的提示提交。(如果你只是推送一个分支,那只是一个提交。)如果他们没有这些提交,你的 Git 必须提供这些提示提交的父级。(大多数提交只有一个父级,所以这是多一个提交。)如果他们没有这些,你的 Git 必须提供更多的父级,依此类推。通过这个过程,您的 Git 会找到他们的 Git 需要的所有提交,以完整了解您发送的提示提交:所有历史记录。
你取的时候,他们把所有的树枝都献上了。不同之处:你只推你指定的任何分支。
在你的 Git 发送了你有的任何提交之后,他们没有,他们需要为你正在推送的分支完成提示提交,你的 Git 会发送一个礼貌的请求,让他们设置他们的分支姓名。
当您获取数据时,您的 Git 设置了您的远程跟踪名称。您现在要求他们设置他们的分支名称。
总结一下这些关键点:
- fetch获取(所有,默认情况下,除非你限制它)提交和分支,并将它们的分支重命名为您的远程跟踪名称
- push发送(一个,默认情况下)4个分支提示提交(以及它的祖先,如果/根据需要),然后要求他们设置他们的分支名称
您可以要求git push
他们设置一个与您用于选择要发送的提交的名称不同的名称。例如:
git push origin test-xyz:new-feature
发送您的分支的提示提交test-xyz
(以及它的父母和其他祖先,如果/根据需要),但要求他们设置或创建他们的分支名称new-feature
。
所以:
...似乎如果任何 branch_A 正在跟踪远程 branch_B,则任何推送都将转到 branch_B ...
这是完全错误的,至少在默认情况下是这样。(不过,有一个设置push.default
确实可以做到这一点。)
这里还有很多东西要知道,特别是,git rev-list --left-right --count
它在做什么以及提交“开启”意味着什么——或者更准确地说,可以从一个分支名称访问,但我有点没时间了在这一点上,这个答案中的空间。
1特别是,文件可以被跟踪或不被跟踪,一些名称是远程跟踪名称,并且具有上游集的分支被称为跟踪其上游。在前两种情况下,动词(以其现在分词形式)变成形容词,修饰名称或文件。
2有一些方法可以运行git fetch
不会更新所有远程跟踪名称的限制。例如,使用git pull
有时会这样做。我更喜欢将我git fetch
的命令和其他命令分开,而不是使用git pull
fetch-then-run-another-Git-command 命令。
3 fetch 之后想要整合你fetch 的东西是很常见的,所以一开始git fetch
是一个后端“管道”命令,不是为了让用户运行,然后git pull
运行。这是在远程作为一个概念存在之前,因此在远程跟踪名称存在之前,因此用户没有任何理由运行.git fetch
git merge
git fetch
随着时间的推移,Git 增加了 remotes 和 remote-tracking 的名称,现在pull
——fetch 和 combine——和只是fetch
不结合(或者至少,还没有结合)之间的区别变得既有用又重要。但是这个名字 pull
已经被用来表示fetch 和 combine,因此这个特殊的历史事故。
4也就是说,这是 Git 2.0 及更高版本中的默认设置。您可以使用 更改它push.default
,并且低于 2.0 的 Git 版本默认为matching
.
使用 时matching
,您的 Git 会向他们的 Git 询问他们的分支名称,匹配您匹配的分支名称,并默认从您的匹配名称推送到它们的匹配名称。
如果您将此设置更改为upstream
,您的 Git 会要求他们的 Git 根据您的分支的上游设置来设置他们的分支,这就是您在问题中所假设的。
现代默认设置是simple
,它要求上游被设置为同名的分支,这样git push
如果你的上游被设置为他们一方的不同名称,你的一端就会立即失败。但是,您可以通过输入 轻松覆盖它,这与以下含义相同:要求他们的 Git 使用与您在 Git 中使用的相同的分支名称。git push origin branch
git push origin branch:branch