一般来说,合并步骤是将远程跟踪分支合并到master还是当前分支?
这两个是相同的:master
是您当前的分支。远程跟踪分支是origin/master
.
(Where origin
只是用于远程的默认名称,而不是任何特殊的 Git“关键字”,并且master
是默认分支。实际场景中的实际名称可能有所不同。)
的目标是rebase
or merge
操作(产生的更改将去往的位置)是当前分支。
如果你尝试做一些愚蠢的事情,比如checkout origin/master
尝试使跟踪分支成为当前分支。
所以,合并的目标是master
。问题是,合并什么?如果您提取一些新的上游材料,您可能最终会遇到(例如)这种情况:
YOURS (master)
*
\ UPSTREAM (origin/master)
* *
\ /
* <--- "git merge-base master origin/master"
|
*
master
and origin/master
已经分歧,并且分别有 2 个和 1 个新提交。
With git rebase
,下面的两个本地提交YOURS
在 UPSTREAM 之上重写:
YOURS (master)
* <-- rewritten: SHA changes
\
ghost of YOURS * <-- rewritten: SHA changes
* ---- * \
\ * UPSTREAM (origin/master)
\ /
*
|
现在的情况是“当地分行master
领先于origin/master
2 次提交”。你准备好(尝试)git push
.
您原来的未重写提交仍然存在(在 ASCII 图中用“ghost of YOURS”表示)。它们在git reflog
。当它们从那里过期或被手动清除时,它们就变成垃圾,最终被垃圾收集。
With git merge
你做了其他事情:你的更改将被合并origin/master
并且创建了一个新的提交,它有两个父项:
* YOURS-merged (master)
/ \
YOURS / \
* |
\ | UPSTREAM (origin/master)
* *
\ /
* <--- "git merge-base master origin/master"
|
*
现在你的master
领先于origin/master
通过 1 次提交。如果您现在推送成功,远程存储库的master
也将呈现上述形状,双父提交沿着一条路径进行更改,而上一个上游提交则沿着另一条路径。不存在“你的幽灵”:你的更改从未被重写。
为什么合并是“快进合并”?
快进合并或变基发生在两种情况下。其一是origin/master
没有任何并行更改:
YOURS (master)
*
\
*
\
* UPSTREAM (origin/master)
|
*
在上述情况下,无需执行任何操作:一切都是最新的,并且您领先于origin/master
通过两次提交。因此,这不是“快进任何事情”;而是“快进”。 Agit merge
or git rebase
只会什么也不做。你可以尝试git push
如果您对这些承诺感到满意。
当您没有任何本地更改时,就会发生真正的快进场景:
* UPSTREAM (origin/master)
/
YOURS (master) *
|
*
在这种情况下,如果您执行git rebase
or git merge
,那么默认情况下,您的master
HEAD
指针只是“向前滑动”以指向相同的提交origin/master
,这张幻灯片是“快进”:
YOURS (master) * UPSTREAM (origin/master)
/
* <- master slid forward from here
|
*
“快进”术语可能指的是这样的想法:只有HEAD
指针移动(同时重写本地文件系统树以匹配)。无需编写或重写新的提交。
在不同的场景中快进是不可能的(除非您放弃本地更改)。必须生成新的合并提交,或者变基必须重写一些更改。在这些操作之前,不存在任何提交master
可以直接向前滑动。
有些人以某种方式使用 Git,他们希望合并所有本地工作的提交。当上游没有新的工作可供合并时,您可以强制 Git 无论如何进行合并提交git merge --no-ff
(无快进)。从这个开始:
YOURS (master)
*
\
*
\
* UPSTREAM (origin/master)
|
*
你会得到这样的东西:
----* YOURS-merge (master)
YOURS / |
* |
\ |
* |
\ |
* UPSTREAM (origin/master)
|
*
这个想法是,在历史的主线路径上,这两种变化似乎浓缩为一步。可以跟随另一个父级来查看多次提交的详细血统。
为什么引用说“您的本地跟踪分支”而不是当前分支?
这是个错误。涉及的所有分支都是本地的(在您的存储库中)。有工作分支(比如master
),及其远程跟踪分支(如origin/master
)。两者都是本地人。
您工作的分支不称为跟踪分支;而是称为跟踪分支。它不跟踪任何东西。
一些本地分支未与远程跟踪分支配对。存储库中没有远程的所有分支(例如由git init
)纯粹是本地的。任何本地创建的分支都是纯本地的,除非推送到远程存储库。
远程跟踪分支是一个与本地分支配对的类似分支的对象。它跟踪上游正在做什么。每次你做一个git fetch
,它可能会被重写以指向一些不同的提交。当地分行不受影响。两者可能会出现分歧,这可以通过变基或合并来解决。当你做一个git push
,本地分支更新实际远程上游仓库中的一个。当此操作成功(未被远程端拒绝)时,本地跟踪分支也会更新为指向同一提交,因此它们保持同步。
一般情况下,纯本地操作不会改变origin/master
:它跟踪远程存储库中相应分支的状态。