Git 可以跟踪祖先分支以及它自己的分支吗?
Can Git track an ancestor branch as well as its own branch?
抱歉,如果这是一个菜鸟问题,但我已经搜索了一个多小时,但无法得到明确的答案。
我想做的是:
- 检查远程分支
git checkout origin/feature
- 根据该分支创建一个本地分支
git checkout -b feature_my_tweak
- 所以现在我有一个名为
feature_my_tweak
的 feature
的本地副本,我可以使用它
- 进行一些更改
commit -m "added my tweak"
所以现在我的本地 feature_my_tweak
已经不同于 feature
- 现在执行
git push --set-upstream origin feature_my_tweak
将我的本地分支推送到远程服务器
- 现在同事将更改推送到远程服务器上的
feature
在这一点上,我希望能够 git pull
并让 git 看到 feature
有变化并拉取它 (fetch/merge)进入我当地的 feature_my_tweak
分支机构。有没有办法自动做到这一点?或者我是否必须手动执行 git merge feature
才能将所有更改从该分支获取到我的本地 feature_my_tweaks
分支?我想我认为有一种方法可以让一个分支跟踪另一个分支。
另一部分是我仍然希望能够对 feature_my_tweaks
进行本地更改并且仍然能够 git push
并且只将其推送到远程 origin/feature_my_tweak
分支并且不污染 origin/feature
分支。
有办法做到这一切吗?据我所知,似乎如果任何 branch_A 正在跟踪远程 branch_B,任何推送都会转到 branch_B,这是我不想要的。
我希望这是有道理的。
TL;DR
答案的简短版本归结为否,但没关系,不用担心,只需手动完成即可;很简单。如果你有一个特定的 b运行ch,你经常用它来做这个,写一个脚本或一个 Git 别名来做它。
中
手动执行此操作,对于你的 b运行ch B,你想知道 origin/feature
上是否有新内容,与你自己的 b 运行ch 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
或 git checkout feature_my_tweaks; git merge origin/feature
.
是否以及何时使用 git rebase
由您决定,但在 rebase 之后,您将需要 git push --force origin feature_my_tweaks
(或 git push --force-with-lease origin feature_my_tweaks
)来获得 Git在 origin
丢弃你的 git rebase
将你的提交复制到 new-and-improved 提交时丢弃的旧提交。
长
这里最大的问题可能是术语。 tracking 这个词对您来说意味着什么? Git 至少以三种不同的方式使用这个词,1 因此最多其中一种可以与您想到的匹配。 (可能 none 它们完全匹配,具体取决于您的想法。)
不管你使用哪个词,下面是正确的思考方式:
重要的是提交。每个提交都有一个唯一的哈希 ID。每个 Git 无处不在 - 这个存储库的每个克隆 - 使用 that 哈希 ID 用于该提交。如果您有一个带有 that 哈希 ID 的提交,则它是同一个提交。如果你不这样做,你就没有那个提交。
Names in Git 有很多形式。每个名称都有一个哈希 ID——只有一个!
您使用的三种形式是:
B运行ch 名称: master
、develop
、feature
或 feature/one
,等等。这些都是你的,想怎么用就怎么用。 (不过,您可能希望自己的名字与其他人的名字相匹配,至少在不同的时候是这样。)
标签名称: v2.1
等等。虽然你的是你的,但你的 Git 会尝试 与其他 Git 存储库共享 它们:如果你的 Git 发现他们的 v2.1
而你不这样做,你的 Git 很可能会将他们的复制到你的。
Remote-tracking 姓名: origin/master
, origin/feature
, 等等。 Git 称这些 remote-tracking b运行ch names 有些人将其缩短为 remote-tracking b运行ch,但它们不太像 b运行ch 名称。您的 Git 将这些从属于其他 Git 的 b运行ch 名称。您让 Git 调用他们的 Git 并从他们那里获得任何 新提交 。然后你的 Git 更新你的 remote-tracking 名字,使它们与他们的名字相匹配。
remote-tracking 名称是通过将 remote 名称(在本例中为 origin
)粘贴在 b运行ch 名称,用斜线将它们分开。这就是为什么你的 origin/master
"tracks" 他们的 master
,每次你 运行 git fetch origin
.2[=78= 都会更新的原因]
所有这些名称的作用都相似。它们都有长形式:refs/heads/master
是 master
的完整拼写,例如,refs/remotes/origin/master
是 origin/master
的完整拼写。这就是 Git 知道哪个是哪种名称的方式。 Git 通常然后 缩短 显示给你的名字,去掉 b运行ch 名字的 refs/heads/
部分,或者 refs/remotes/
remote-tracking 个名字的一部分。
请注意 git fetch
与 git push
的对立面非常接近。看起来这些应该是 push
和 pull
,但由于历史事故 3 它是 push
和 fetch
。 pull just 表示:运行 fetch,然后运行第二个Git命令,默认git merge
,与当前b运行合并ch 的上游。
获取和推送非常相似,但有两个主要区别:
获取获取东西。你告诉你的 Git: 调出 Git 的 URL 你存储在名称 origin
下的 origin
在这里使用)。您的 Git 调用位于 URL 的服务器,它必须作为 Git 存储库响应。该服务器然后告诉您它的 b运行ch 名称和它们的提交,并且您的 Git 检查您是否有这些提交。如果没有,您的 Git 会向他们的 Git 询问这些提交,如果您没有他们的 parent 提交,以及 parent 的 parent如果需要,等等。他们给你所有他们有的提交,你没有,你的 Git 需要完成这些。
有得到提交,git fetch
然后更新你的 remote-tracking names 通过重命名他们的 b运行ches.
推送发送东西。和以前一样,您的 Git 通过远程名称 origin
调用另一个 Git。然后你的 Git 给他们提交,而不是从他们那里得到提交。但在这里,情况略有不同:
您的 Git 提交是您正在推动的任何 b运行 的 提示提交 。 (如果您只是推送一个 b运行ch,那只是一次提交。)如果他们没有这些提交,您的 Git 必须提供这些提示提交的 parents。 (大多数提交只有一个 parent,所以这又是一个提交。)如果他们没有 那些 ,你的 Git 必须提供更多 parents,等等。通过这个过程,你的 Git 找到他们的 Git 需要的所有提交,需要有你发送的 tip 提交的完整图片:它的所有历史。
当你取货时,他们提供了所有他们的b运行ches。不同点:你只推你指定的 b运行ches。
在您的 Git 发送了您拥有的任何提交之后,他们没有,他们需要完成 b运行ch 的提示提交(es) 你在推动,你的 Git 礼貌地请求他们设置他们的 b运行ch 名称。
当您获取时,您的 Git 设置了您的 remote-tracking 名称。您现在要求他们设置 b运行ch 名称。
总结这些要点:
- fetch gets(所有,默认情况下,除非你限制它)从他们那里提交和 b运行ches 并将他们的 b运行ches 重命名为你的remote-tracking名字
- push sends(一个,默认情况下)4 branch-tip 提交(及其祖先 if/as 需要) 然后要求他们设置他们的 b运行ch name(s)
您可以让git push
要求他们设置一个与您select不同的名称] 要发送的提交。例如:
git push origin test-xyz:new-feature
发送您的 test-xyz
b运行ch(及其 parents 和其他需要的祖先 if/as)的提示提交,但要求他们设置或创建他们的b运行频道名new-feature
.
所以:
... it seems that if any branch_A is tracking a remote branch_B, any pushes will go to branch_B ...
这是完全错误的,至少在默认情况下是这样。 (但是 push.default
的设置 确实 实现了这一点。)
这里还有很多东西需要了解,特别是 git rev-list --left-right --count
正在做什么以及提交 "on" 或更准确地说 可访问意味着什么from—一个 b运行ch 的名字,但我有点 运行 没时间了,在这个答案中 space,在这一点上。
1特别是,文件可以 tracked 或 untracked,一些名称是 remote-tracking names,而带有上游集的 b运行ch 据说是 tracking 其上游。动词(现在分词形式)变成形容词,在前两种情况下修饰 name 或 file。
2有一些方法可以 运行 有限的 git fetch
不会 更新您所有的 remote-tracking 名字。例如,使用 git pull
有时会这样做。我更喜欢将 git fetch
和其他命令分开,而不是使用 git pull
fetch-then-run-another-Git-command 命令。
3抓取之后想要整合你抓取的内容是很常见的,所以一开始,git fetch
是一个back-end "plumbing" 命令,并不意味着用户要 运行,然后 git pull
运行 git fetch
,然后 git merge
。这是在 remotes 作为一个概念存在之前,因此在 remote-tracking 名称存在之前,所以用户没有任何理由 运行 git fetch
.
随着时间的推移,Git 增加了遥控器和 remote-tracking 名称,现在 pull
之间的区别 - 获取和组合 - 只是 fetch
没有组合(或在至少,不这样做 yet) 变得既有用又重要。但是 name pull
已经被用来表示 fetch and combine,因此这个特殊的历史事故。
4也就是说,这是 Git 2.0 及更高版本中的默认设置。可以改成push.default
,Git 2.0以前的版本默认为matching
.
当使用 matching
时,你的 Git 询问他们的 Git 关于他们的 b运行ch 名字,匹配你匹配的 b运行ch 名字,并默认从您的匹配名称推送到他们的匹配名称。
如果您将此设置更改为 upstream
,您的 Git 会要求他们的 Git 根据您的 b[= 的上游设置设置他们的 b运行ch 399=]ch,这是你在问题中假设的。
现代默认设置是simple
,这要求上游设置为b运行ch同名,因此如果您的上游设置为他们一方的不同名称,那么您这边的 git push
会立即失败。但是,您可以通过输入 git push origin <em>b运行ch</em>
轻松覆盖它,这意味着同样的事情作为 git 推送原点 <em>b运行ch</em>:<em>b运行ch</em>
:要求他们的 Git 使用与您在 Git.
中使用的相同的 b运行ch 名称
抱歉,如果这是一个菜鸟问题,但我已经搜索了一个多小时,但无法得到明确的答案。
我想做的是:
- 检查远程分支
git checkout origin/feature
- 根据该分支创建一个本地分支
git checkout -b feature_my_tweak
- 所以现在我有一个名为
feature_my_tweak
的feature
的本地副本,我可以使用它 - 进行一些更改
commit -m "added my tweak"
所以现在我的本地feature_my_tweak
已经不同于feature
- 现在执行
git push --set-upstream origin feature_my_tweak
将我的本地分支推送到远程服务器 - 现在同事将更改推送到远程服务器上的
feature
在这一点上,我希望能够 git pull
并让 git 看到 feature
有变化并拉取它 (fetch/merge)进入我当地的 feature_my_tweak
分支机构。有没有办法自动做到这一点?或者我是否必须手动执行 git merge feature
才能将所有更改从该分支获取到我的本地 feature_my_tweaks
分支?我想我认为有一种方法可以让一个分支跟踪另一个分支。
另一部分是我仍然希望能够对 feature_my_tweaks
进行本地更改并且仍然能够 git push
并且只将其推送到远程 origin/feature_my_tweak
分支并且不污染 origin/feature
分支。
有办法做到这一切吗?据我所知,似乎如果任何 branch_A 正在跟踪远程 branch_B,任何推送都会转到 branch_B,这是我不想要的。
我希望这是有道理的。
TL;DR
答案的简短版本归结为否,但没关系,不用担心,只需手动完成即可;很简单。如果你有一个特定的 b运行ch,你经常用它来做这个,写一个脚本或一个 Git 别名来做它。
中
手动执行此操作,对于你的 b运行ch B,你想知道 origin/feature
上是否有新内容,与你自己的 b 运行ch 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
或 git checkout feature_my_tweaks; git merge origin/feature
.
是否以及何时使用 git rebase
由您决定,但在 rebase 之后,您将需要 git push --force origin feature_my_tweaks
(或 git push --force-with-lease origin feature_my_tweaks
)来获得 Git在 origin
丢弃你的 git rebase
将你的提交复制到 new-and-improved 提交时丢弃的旧提交。
长
这里最大的问题可能是术语。 tracking 这个词对您来说意味着什么? Git 至少以三种不同的方式使用这个词,1 因此最多其中一种可以与您想到的匹配。 (可能 none 它们完全匹配,具体取决于您的想法。)
不管你使用哪个词,下面是正确的思考方式:
重要的是提交。每个提交都有一个唯一的哈希 ID。每个 Git 无处不在 - 这个存储库的每个克隆 - 使用 that 哈希 ID 用于该提交。如果您有一个带有 that 哈希 ID 的提交,则它是同一个提交。如果你不这样做,你就没有那个提交。
Names in Git 有很多形式。每个名称都有一个哈希 ID——只有一个!
您使用的三种形式是:
B运行ch 名称:
master
、develop
、feature
或feature/one
,等等。这些都是你的,想怎么用就怎么用。 (不过,您可能希望自己的名字与其他人的名字相匹配,至少在不同的时候是这样。)标签名称:
v2.1
等等。虽然你的是你的,但你的 Git 会尝试 与其他 Git 存储库共享 它们:如果你的 Git 发现他们的v2.1
而你不这样做,你的 Git 很可能会将他们的复制到你的。Remote-tracking 姓名:
origin/master
,origin/feature
, 等等。 Git 称这些 remote-tracking b运行ch names 有些人将其缩短为 remote-tracking b运行ch,但它们不太像 b运行ch 名称。您的 Git 将这些从属于其他 Git 的 b运行ch 名称。您让 Git 调用他们的 Git 并从他们那里获得任何 新提交 。然后你的 Git 更新你的 remote-tracking 名字,使它们与他们的名字相匹配。remote-tracking 名称是通过将 remote 名称(在本例中为
origin
)粘贴在 b运行ch 名称,用斜线将它们分开。这就是为什么你的origin/master
"tracks" 他们的master
,每次你 运行git fetch origin
.2[=78= 都会更新的原因]
所有这些名称的作用都相似。它们都有长形式:refs/heads/master
是master
的完整拼写,例如,refs/remotes/origin/master
是origin/master
的完整拼写。这就是 Git 知道哪个是哪种名称的方式。 Git 通常然后 缩短 显示给你的名字,去掉 b运行ch 名字的refs/heads/
部分,或者refs/remotes/
remote-tracking 个名字的一部分。
请注意 git fetch
与 git push
的对立面非常接近。看起来这些应该是 push
和 pull
,但由于历史事故 3 它是 push
和 fetch
。 pull just 表示:运行 fetch,然后运行第二个Git命令,默认git merge
,与当前b运行合并ch 的上游。
获取和推送非常相似,但有两个主要区别:
获取获取东西。你告诉你的 Git: 调出 Git 的 URL 你存储在名称
origin
下的origin
在这里使用)。您的 Git 调用位于 URL 的服务器,它必须作为 Git 存储库响应。该服务器然后告诉您它的 b运行ch 名称和它们的提交,并且您的 Git 检查您是否有这些提交。如果没有,您的 Git 会向他们的 Git 询问这些提交,如果您没有他们的 parent 提交,以及 parent 的 parent如果需要,等等。他们给你所有他们有的提交,你没有,你的 Git 需要完成这些。有得到提交,
git fetch
然后更新你的 remote-tracking names 通过重命名他们的 b运行ches.推送发送东西。和以前一样,您的 Git 通过远程名称
origin
调用另一个 Git。然后你的 Git 给他们提交,而不是从他们那里得到提交。但在这里,情况略有不同:您的 Git 提交是您正在推动的任何 b运行 的 提示提交 。 (如果您只是推送一个 b运行ch,那只是一次提交。)如果他们没有这些提交,您的 Git 必须提供这些提示提交的 parents。 (大多数提交只有一个 parent,所以这又是一个提交。)如果他们没有 那些 ,你的 Git 必须提供更多 parents,等等。通过这个过程,你的 Git 找到他们的 Git 需要的所有提交,需要有你发送的 tip 提交的完整图片:它的所有历史。
当你取货时,他们提供了所有他们的b运行ches。不同点:你只推你指定的 b运行ches。
在您的 Git 发送了您拥有的任何提交之后,他们没有,他们需要完成 b运行ch 的提示提交(es) 你在推动,你的 Git 礼貌地请求他们设置他们的 b运行ch 名称。
当您获取时,您的 Git 设置了您的 remote-tracking 名称。您现在要求他们设置 b运行ch 名称。
总结这些要点:
- fetch gets(所有,默认情况下,除非你限制它)从他们那里提交和 b运行ches 并将他们的 b运行ches 重命名为你的remote-tracking名字
- push sends(一个,默认情况下)4 branch-tip 提交(及其祖先 if/as 需要) 然后要求他们设置他们的 b运行ch name(s)
您可以让git push
要求他们设置一个与您select不同的名称] 要发送的提交。例如:
git push origin test-xyz:new-feature
发送您的 test-xyz
b运行ch(及其 parents 和其他需要的祖先 if/as)的提示提交,但要求他们设置或创建他们的b运行频道名new-feature
.
所以:
... it seems that if any branch_A is tracking a remote branch_B, any pushes will go to branch_B ...
这是完全错误的,至少在默认情况下是这样。 (但是 push.default
的设置 确实 实现了这一点。)
这里还有很多东西需要了解,特别是 git rev-list --left-right --count
正在做什么以及提交 "on" 或更准确地说 可访问意味着什么from—一个 b运行ch 的名字,但我有点 运行 没时间了,在这个答案中 space,在这一点上。
1特别是,文件可以 tracked 或 untracked,一些名称是 remote-tracking names,而带有上游集的 b运行ch 据说是 tracking 其上游。动词(现在分词形式)变成形容词,在前两种情况下修饰 name 或 file。
2有一些方法可以 运行 有限的 git fetch
不会 更新您所有的 remote-tracking 名字。例如,使用 git pull
有时会这样做。我更喜欢将 git fetch
和其他命令分开,而不是使用 git pull
fetch-then-run-another-Git-command 命令。
3抓取之后想要整合你抓取的内容是很常见的,所以一开始,git fetch
是一个back-end "plumbing" 命令,并不意味着用户要 运行,然后 git pull
运行 git fetch
,然后 git merge
。这是在 remotes 作为一个概念存在之前,因此在 remote-tracking 名称存在之前,所以用户没有任何理由 运行 git fetch
.
随着时间的推移,Git 增加了遥控器和 remote-tracking 名称,现在 pull
之间的区别 - 获取和组合 - 只是 fetch
没有组合(或在至少,不这样做 yet) 变得既有用又重要。但是 name pull
已经被用来表示 fetch and combine,因此这个特殊的历史事故。
4也就是说,这是 Git 2.0 及更高版本中的默认设置。可以改成push.default
,Git 2.0以前的版本默认为matching
.
当使用 matching
时,你的 Git 询问他们的 Git 关于他们的 b运行ch 名字,匹配你匹配的 b运行ch 名字,并默认从您的匹配名称推送到他们的匹配名称。
如果您将此设置更改为 upstream
,您的 Git 会要求他们的 Git 根据您的 b[= 的上游设置设置他们的 b运行ch 399=]ch,这是你在问题中假设的。
现代默认设置是simple
,这要求上游设置为b运行ch同名,因此如果您的上游设置为他们一方的不同名称,那么您这边的 git push
会立即失败。但是,您可以通过输入 git push origin <em>b运行ch</em>
轻松覆盖它,这意味着同样的事情作为 git 推送原点 <em>b运行ch</em>:<em>b运行ch</em>
:要求他们的 Git 使用与您在 Git.