Git 我可以快进合并整个分支链到主节点吗?

Git 我可以快进合并整个分支链到主节点吗?,git,Git,如果我有一个分支链 master->branchA->branchB->branchC->branchD 是否可以在一个git命令中将分支D以及它与master(A、B和C)之间的链中的所有分支快速合并到master中?答案是一种临时的是 这里的诀窍是认识到Git并不真正关心分支。Git非常关心提交。当你谈论“分支链”时,你谈论的是一种视错觉:你看到的是Git没有看到的东西 为了准确起见,我们必须定义分支这个术语。当我们尝试时,我们发现这是一个大问题。不同的人使用这个词的方式不同,一个人甚至会以

如果我有一个分支链

master->branchA->branchB->branchC->branchD


是否可以在一个git命令中将分支D以及它与master(A、B和C)之间的链中的所有分支快速合并到master中?

答案是一种临时的是

这里的诀窍是认识到Git并不真正关心分支。Git非常关心提交。当你谈论“分支链”时,你谈论的是一种视错觉:你看到的是Git没有看到的东西

为了准确起见,我们必须定义分支这个术语。当我们尝试时,我们发现这是一个大问题。不同的人使用这个词的方式不同,一个人甚至会以多种方式使用这个词,也许是在同一个句子中。(请参阅)但如果我们有意识地退一步,尽量避免使用“分支”这个词,看看提交工作的方式,这一切就开始有意义了

每个提交都有一个数字。但是,这些数字不是很好的1、2、3样式的序列号:它们是随机的散列ID,比如
AE46588BE0CD730430DDED4491246DFB4EAC55557
。(它们显然不是随机的:它们是每个提交内容的校验和,因此每个Git都将为相同的提交位计算相同的哈希ID。这是Git的关键魔法,真的。)没有简单的方法从ID中知道哪个提交是哪个

因此,Git所做的是:无论何时进行新的提交,都是从某个现有的提交中进行的。1因此,现有的提交是新提交的父级。Git在提交的元数据中存储新提交父级的哈希ID。这意味着我们始终可以从最后一次提交开始,并向后工作:

... <-F <-G <-H
as在一行中提交所有内容,假设名称
master
指向提交
C
,名称
功能
指向提交
F
,名称
hack
指向提交
H
,名称
last
指向提交
L

                 __feature
                .
A--B--C--D--E--F--G--H--I--J--K--L   <-- last
       .              .
        ---master      --hack
(通过使用分支名称签出提交会将特殊名称
HEAD
附加到分支名称,这就是我在上面添加
HEAD
的原因。)

回到你最初的问题,我们现在需要定义“快进”一词。在Git中,快进操作意味着我们有一些现有的提交链,使用任何名称都可以使用的名称,尽管分支名称是这里讨论的通常类型的名称,指向其中一个,但是在该名称之后还有一些提交,如下所示:

          V   <-- option1
         /
...--T--U   <-- name
         \
          W--X--Y--Z   <-- option2
现在我们已经这样做了,但是,如果我们要求Git移动
name
,使它指向
W
X
Y
、或
Z
,Git必须首先从
V
向后移动到
U
,然后再向前移动。这意味着这项行动不是快进的

快进不仅仅来自合并 虽然
git merge
命令可以执行快进操作,并且在可以的时候会自动执行,但这并不是git中寻找快进操作的唯一部分。特别是,
git fetch
git push
都可以调整名称。名称
git fetch
adjusts通常是远程跟踪名称,而不是分支名称,但是与
git push
一起使用的名称通常会告诉其他一些git存储库调整其分支名称,这些名称也会首先检查快进性

结论 最后,这一切都归结于您的提交链,以及您所说的“分支”的确切含义。如果您可以按照我们使用上面的
master
feature
hack
last
绘制分支,那么您可以要求Git向前移动名称
master

A--B--C   <-- master (HEAD)
       \
        D--E--F   <-- feature
               \
                G--H   <-- hack
                    \
                     I--J--K--L   <-- last
这确实会失败。但是
--ff only
在这里并不完美。例如,考虑一下 如果我们有:

A--B--C   <-- master (HEAD)
       \
        D--E--F--NEW   <-- feature
               \
                G--H   <-- hack
                    \
                     I--J--K--L   <-- last

但是
feature
master
之前仍然有一个commit,因为commit
NEW
-指向
F
-只有从
feature
开始并向后操作才能使用。

答案是一种临时的肯定

这里的诀窍是认识到Git并不真正关心分支。Git非常关心提交。当你谈论“分支链”时,你谈论的是一种视错觉:你看到的是Git没有看到的东西

为了准确起见,我们必须定义分支这个术语。当我们尝试时,我们发现这是一个大问题。不同的人使用这个词的方式不同,一个人甚至会以多种方式使用这个词,也许是在同一个句子中。(请参阅)但如果我们有意识地退一步,尽量避免使用“分支”这个词,看看提交工作的方式,这一切就开始有意义了

每个提交都有一个数字。但是,这些数字不是很好的1、2、3样式的序列号:它们是随机的散列ID,比如
AE46588BE0CD730430DDED4491246DFB4EAC55557
。(它们显然不是随机的:它们是每个提交内容的校验和,因此每个Git都将为相同的提交位计算相同的哈希ID。这是Git的关键魔法,真的。)没有简单的方法从ID中知道哪个提交是哪个

因此,Git所做的是:无论何时进行新的提交,都是从某个现有的提交中进行的。1因此,现有的提交是新提交的父级。Git在提交的元数据中存储新提交父级的哈希ID。这意味着我们始终可以从最后一次提交开始,并向后工作:

... <-F <-G <-H
as在一行中提交所有内容,假设名称
master
指向提交
C
,名称
功能
指向提交
F
,名称
hack
指向提交
H
,名称
last
指向提交
          V   <-- name, option1
         /
...--T--U
         \
          W--X--Y--Z   <-- option2
A--B--C   <-- master (HEAD)
       \
        D--E--F   <-- feature
               \
                G--H   <-- hack
                    \
                     I--J--K--L   <-- last
A--B--C--D--NEW   <-- master
          \
           E--...--L   <-- last
A--B--C   <-- master (HEAD)
       \
        D--E--F--NEW   <-- feature
               \
                G--H   <-- hack
                    \
                     I--J--K--L   <-- last
A--B--C--D--E--F--NEW   <-- feature
                \
                 G--H   <-- hack
                     \
                      I--J--K--L   <-- last, master (HEAD)