这https://git-scm.com/book/en/v2/Git-Internals-The-Refspec说
The + tells Git to update the reference even if it isn’t a fast-forward.
这是什么意思?
正如Raymond Chen在评论中指出的那样,你必须把几个部分放在一起:
+
设置"力";标志,即即使操作不是快进,也要进行更新;和- afast-forward是名称更新的属性。
第一部分非常简单,但第二部分可能有点晦涩。这有点像《福尔摩斯与舞男历险记》的前几段。
一个名称,或ref或reference在Git中,例如分支名称refs/heads/develop
,包含一个哈希ID,通常是提交的哈希ID。快速转发的概念只对那些标识提交的refs有意义,所以从这里开始,我们将这样假设。
在Git中,提交生成一个有向无环图(DAG),因为每个提交都存储其父提交的原始哈希id。例如,我们可以对单个提交应用一个简单的传递闭包算法来找到这个图。这意味着图中中的每一对节点都可以有"前导"。(数学符号≺
,一种弯曲小于)关系:X
同样,如果PP是p的父元素-箭头在Git中为一分pkp一分p一分C,因为它们指向向后而不是向前-那么PP C也是。这里页是祖父母C。
因为Git查找的方式是从某个标签指向的提交开始,然后反向工作,如果我们取任意一组提交:
... ⟵PP ⟵P ⟵C ...
并有一些名称,如develop
指向PP,并将该名称"向前"移动-反对内部箭头的方向-指向C,我们仍然可以使用该名称查找PP。我们现在从C开始,这次向后转两跳。
这样的动作,一个名字过去查找某个提交,现在查找该提交的后代,这是一个快进操作。所产生的名称移动不会"丢失"。任何提交:它只是添加所有的后代。即使名称运动相当复杂,也是如此。例如,假设我们这样做,其中每轮o
是一个提交,两个name
是分支名称:
o--o--o--o--o
/
...--o--o <--name1 o <--name2
/
o--o--o--o--o
我们现在建议Git将名称name1
移动到与名称name2
指向相同的提交,给出:
o--o--o--o--o
/
...--o--o o <--name1, name2
/
o--o--o--o--o
左-中间的所有提交仍然可以从名称name1
访问;它只需要遍历顶部或底部行。
在数学上,如果:
- name标识提交X现在;
- 我们要求Git更改name来标识commitY;和 X≺Y
- ("X先于Y")
则此名称运动为快进。为了简化起见,如果我们要求Git"移动";从X到X(或者等价地,设置Y=X), Git实际上测试了X tmd,但是现在应该很清楚了。因此,由git push
或git fetch
进行的引用更新将在分支上工作,如果:
- 更新是快进的,或者
- 更新是强制。
因此,+
强制非快进更新。
"…再过五分钟,你就会说这一切都简单得可笑"