我有这种状况,我想了解。
at T1 Local | at T1 Remote:
------------------------------------------------------------------------
E--F featureOne | E--F featureOne
/ | /
A--B--C--D branchOne | A--B--C--D branchOne
------------------------------------------------------------------------
at T2 Local | at T2 Remote:
------------------------------------------------------------------------
merged branchOne into featureOne: |
E------F featureOne | E--F featureOne
/ \ | /
/ G | A--B--C--D branchOne
/ / |
A--B--C----D branchOne |
------------------------------------------------------------------------
at T3 Local | at T3 Remote:
------------------------------------------------------------------------
merged featureOne into branchOne |
after git pull branchOne |
from Remote: |
E------F | E--F featureOne
/ \ | /
/ G-. featureOne | A--B--C--D branchOne
/ / \ |
A--B--C----D-----H branchOne |
------------------------------------------------------------------------
local中的H是featureOne的G和branchOne的D之间的提交的合并。因为在远程我们没有G,如果我将branchOne从本地推送到远程(origin / branchOne),在T4会发生什么?会合并吗?不幸的是,我无法尝试此操作,因为我先将G从本地featureOne推送到远程featureOne,然后将H从本地branchOne推送到远程branchOne。
git push
的作用是将您的commits(您所拥有的一些或全部(有时不提供),而其他一些Git则没有)发送给有问题的其他Git,然后询问其他Git来将它们的名称中的一些设置为某些提交哈希ID。
因此,如果您有:
E--F--G____ / \ \ A--B--C--D--H
在您的存储库中-无论您的分支names指向何处-并且您告诉Git将提交H
发送到其他Git,您的Git都会调用另一个Git并提供其提交[C0 ]。
((注:我假设这里的提交H
是G
和F
的合并。您的问题描述清楚了是这种情况。我自己绘制图的方式有所不同;请参见下文。)
((如果您明确要求您的Git向他们发送提交D
,则同样的道理也适用,但在这种情况下,您的Git必须在提供G
并让他们接受后提供G
,所以我们将只是在这里担心H
。此外,您还问过H
,名字git push branchOne
指向提交branchOne
。)
如果他们提交了H
,则完成H
的这一部分。在这种情况下,它们没有提交git push
,因此您的Git将提供提交H
和G
,因为它们是D
的父母。如果它们具有这些提交,则完成H
的这一部分:Git发送提交git push
(仅)。如果他们缺少一个或多个提交,您的Git会提供H
和/或G
的[剩余]父母,即D
和F
。如果他们有这些提交,则完成C
的这一部分:您的Git发送了提交git push
,并根据需要发送了提交H
和/或G
。
所以,让我们看一下它们有什么:
D
[这里,他们确实已经提交了 E--F <-- featureOne
/
A--B--C--D <-- branchOne
和F
。因此,您的Git提供D
并且他们接受;您的Git提供H
并且他们接受;您的Git提供G
,他们说不,谢谢,我已经有那个;,而您的Git提供了commit D
,他们说不,谢谢,我已经有那个。然后,您的Git向他们发送提交F
和G
,它们将它们插入到他们的图形中。此时,它们现有的分支名称仍分别指向提交H
(F
)和featureOne
(D
)。
[此时,您的Git进入branchOne
的最后阶段,这是要求他们将其名称的某些集合设置为某些提交。这是您为git push
命令提供的内容的精确拼写形式:
git push
这不是正确的拼写,必须是:
git push branchOne
git push origin branchOne
部分是如何告诉Git调用其他Git的方法。名称部分origin
是此备用拼写的缩写:
branchOne
冒号git push origin branchOne:branchOne
字符的左侧是您的Git如何找到要提供的起始commit的方式。在这种情况下,您的名称:
指向您的提交branchOne
,这就是您的Git开始提供的提交。
冒号H
字符的右侧提供了分支名称,您在其Git存储库中要求them到set。通过在此处使用:
,您最终将要求他们设置名称branchOne
以指向提交branchOne
。
它将合并吗?
H
命令从不引起任何合并。它只是发送您已有的,没有的现有提交,然后要求它们设置一些名称(通常是分支名称)。由他们的Git决定是否接受设置分支名称的请求。
[如果您要推送到GitHub,并且有人在GitHub上Git存储库中的分支名称git push
上启用了“受保护的分支”模式,由于该分支是受保护的,他们将拒绝这种更改名称的尝试。] >
但是,在大多数情况下,他们会接受此更改名称的请求。他们当前的名称为branchOne
,用于标识提交branchOne
。提交D
具有提交H
作为祖先(实际上是直接父辈)的功能,因此此操作是fast-forward
请注意,此不
要求他们完全设置名称D
。它们的名称featureOne
将继续指向之前指向的任何位置,例如提交featureOne
。为了StackOverflow发布的目的,我将其绘制为:F
例如。 (我已将
E------F <-- featureOne / \ / G-. / / \ A--B--C----D-----H <-- branchOne
向前移动,因为它显然是G
和D
的合并,而您绘制它的方式看起来像F
是D
和C
的合并G
。)
如果使用冒号语法:
,则必须拼出全名:git push origin <commit-specifier>:<name>
您可以在左侧使用任何任意的提交说明符。这可以是分支名称,标签名称,名称
HEAD
,相对名称(例如master~3
,引用条目(例如develop@{yesterday}
),甚至是原始哈希ID)。如果您使用左侧的原始哈希ID,并且希望另一个Git创建一个新的branch name
git push origin a123456:refs/heads/new-branch
缩写如:
Git将名称git push origin a123456:existing-branch
依赖their
existing-branch
匹配到其现有分支名称之一。如果使用无冒号格式,则必须
使用一个名称,因为该名称需要发送到另一个Git。您一次可以git push
超过一件事:
git push origin master dev feature
或:
,因此我们期望这会创建一个新的标签名称。git push origin master~3:refs/heads/new-temp-branch dev a123456:refs/tags/v1.2
假设名称
new-temp-branch
在Git的origin
中尚不存在,则此最新版本使用一个相对名称(master~3
)创建一个名为new-temp-branch
的新分支。它使用一个无冒号表达式来发送本地dev
分支的提示提交,并请求它们相应地创建或更新其分支名称dev
。并且,它使用原始哈希ID(a123456
)来请求他们创建或更新其标记名v1.2
。通常禁止标签名称更新,1
1
Git版本中的一个错误,直到1.8.2或1.8.4都意外地允许使用与分支名称更新相同的规则来进行非强制标记名称更新。