git`inco –squash`不会添加“Merge”标头来提交

git `merge --squash` does not add “Merge” header to commit

在我在提交中找到一个"合并"头之前,我一直在想所有工具如何知道哪些分支/提交是合并的。

我的问题是:为什么git merge --squash不添加头,而git merge不添加头?

换言之:为什么我在与git merge合并时看到合并边,而与git merge --squash没有边?

谢谢您。

一些修订信息:

"合并头"是指合并后git log中的第二行:

1
2
3
4
commit 7777777
Merge: 0123456 9876543
Author: Some Body <...>
Date:   Fri ....

…虽然git merge --squash不会产生该行,但我的假设是GitGUI工具读取头以便能够绘制"合并边缘",请参见下图。

我的问题又是一样的,见上文。


铊;博士:git merge --squashmerges(动词),但并不做一个merge(名词)。

"merge头,"你不值得一提的是,在这commits细胞形态。而不是,它是某个东西的那git log打印时,它是一项跨merge承诺。这个主意真的水泥,咱们看在什么得以不啦"的merge"均值作为一个动词和一个merge是什么。更恰当的,让我们看看什么是A s at merge承诺是,还是什么"merge"均值作为一adjective修饰的词"承诺"。我们是懒惰的,像‘出去好的用户,不过,和shorten它从"merge承诺"的"a merge",使它的一名。

/好的。 作为一名merge

我们的面貌,在使用的第一名,因为这是simpler页。在‘出去,一merge承诺是简的承诺与至少两commits亲子。这是它真的很简单。每一个承诺有一些号码的父母。一根有父母的承诺(零库和最有只有一个根的承诺,这是第一个承诺过的机制,这obviously不能有父母,有一个承诺)。最普通的一个commits有好的父母,和所有其他commits有两个或更多的parents1和是因此merge commits。。。。。。。然后,我们shorten的说法。"merge承诺"到"是一merge",改变"merge"从一adjective(修饰"承诺"(名词)的意思,"A merge承诺")。

/好的。

如果一个merge承诺是一个承诺,与双父母,然后git merge必须让merge commits,和对merge均应该"让一merge承诺"和它的不,但有时只读的。我们将看到,当和更多的importantly,那么很快。

/好的。

1other vcses可能停止在两个。mercurial不好的方法,例如:Hg的承诺永远有两个以上的父母。‘出去,然而,允许任何承诺有任何数的父母。A NEA承诺与三个或更多的父母是被称为一merge章鱼,和normally这些commits是制造使用git merge -s octopus或等效的,例如,git merge topic1 topic2 topic3:奔跑的git merge与额外的承诺implies -s octopus说明符。这些做什么,不能做的是用一系列的双亲子merges,即‘出去’s章鱼merges不给它更多的功率比mercurial merges章鱼,但有时是convenient,和很好的通断的表现你的‘出去"。:-)

/好的。 作为一个动词的merge

的动词形态的merge是更多更复杂的或至少,它是在‘出去。我们可以区分之间的两大形式得以AS:有好的法案得以源代码的变化,才有"法案得以分支。(这brings的问题"什么是一个分支"。有一批下载到这个问题比你认为的可能,所以,看我们做什么exactly均用"分"???????)许多NEA commands可以做动词类学院并入,包括git cherry-pickgit revert两部,基本上这是一种形态git apply -3.2 git merge当然是最obvious通做它,当它不,你得到的动词形态得以发生变化。

/好的。 合并更改

合并源更改更恰当地称为"三方合并"。关于这方面的更多信息,请参阅维基百科第3篇或VONC的回答,为什么3路合并比2路合并更有利?细节可能会变得相当复杂,但这个合并过程的目标已经足够简单了:我们希望将对某些公共基础所做的更改合并在一起,即,给定一些起点B,我们找到更改c1和c2并将它们合并以进行单个新更改c3,然后添加该c更改为基础B以获取新版本。好的。

在Git中,合并三方合并源的行为本身使用Git的索引,也称为"临时区域"。通常,对于将进入下一次提交的每个文件,索引只有一个条目。当您git add一个文件时,您告诉Git更新该文件的分阶段版本,替换当前索引中的版本,或者如果该文件以前是"未跟踪的",则将该文件添加到索引中,以便现在对其进行跟踪,并为下一次提交进行分阶段。但是,在合并过程中,每个文件的索引最多有三个条目:一个来自合并基本版本,一个用于文件版本的条目被视为更改1(也称为"我们的"),一个用于更改2("他们的")。如果Git能够自己组合这些更改,那么它会将三个条目替换为一个常规(分段提交)条目。否则,它将以冲突停止,并将冲突标记在文件的工作树版本中。您必须自己解决冲突(可能是在过程中编辑文件),并使用git add将三个特殊的冲突合并索引版本替换为一个正常的阶段版本。好的。

一旦所有冲突都解决了,Git将能够进行新的提交。好的。进行合并提交

使git merge正常进行合并的最后一件事是使合并提交。同样,如果没有冲突,Git可以自己做:git merge合并更改,git add的每个合并结果更新阶段文件,并为您运行git commit。或者,如果有冲突,您可以修复它们,运行git add,运行git commit。在所有情况下,实际上是git commit,而不是git merge,使得合并提交。好的。

最后一部分实际上非常简单,因为索引/临时区域都已经设置好了。Git只是像往常一样提交,除了不将当前(HEADcommit的id作为它的单亲,而是至少提供两个父commit id:第一个是HEADcommit,其余的来自git merge留下的一个文件(.git/MERGE。好的。

2the -3git apply -3,这可以spelled门诊AS --3way,directs git apply的使用index柱在git diff产出的构造一个merge基地,如果需要。当这样做,与git cherry-pickgit revert转弯,到他们的热情merges(去大学的straightforward补丁),NEA储蓄上使用COMMIT亲子的樱桃reverted屈体或承诺。它的价值,也不在这里noting‘出去,这是一个只读的每个文件的基础上,对处理后的补丁是作为一个简单的补丁已经失败。使用父母承诺的文件作为一个数据库的版本为一个三通merge将normally help if是只读的承诺是一个祖先的电流(头)的承诺。如果这不是真的这样的祖先,在不同的浅淡"生从"基地"的头与补丁被应用probably helpful是诺特。当然,NEA会做为一fallback。。。。。。。

/好的。

当旧的方法,维基百科,我发现一些小inaccuracies在它是的,现在的设计实例,它的可能有两个以上的DAG LCAS,但是没有时间到工作是它,和它不是一个坏的概述。

/好的。

4often,它永远不会让bothers的conflicted条目中的第一位。NEA会的,如果可能,简捷消失在夜的git diff相。我们设计的实例,对基地的承诺有四个文件在它的u.txt是unchanged从基地在either承诺,one.txt是变了,从基地到HEAD但不是从基地到其他承诺,two.txt是变了,从基地到其他承诺但不是从基地到HEAD,和three.txt变了,都是对的。NEA会简单的拷贝u.txt直通,把one.txtHEAD,取two.txt从对方的承诺,和只读打扰到杠杆的差别,然后尝试到merge算计,three.txt方法。这是相当快速,但不均,如果你有你自己的特殊的三通- merge程序的方法,这些档案,它永远不会得到u.txt运行的方法,one.txt,和two.txt,只为three.txt。。。。。。。

/好的。

我是不会断手是否让‘出去的多指标的条目之前,attempting得以在大学的差异时,或在attempting和失败的。它不会,但是,要使全三维的条目在奔跑中的自定义merge司机。

/好的。 非merge"merges"

在以上序列检查出一些承诺(通常一支尖),另一个是运行git mergeCommit(通常有其他的店头),找到一种针对适合merge基地,使两个集合中的差异时,combine的差异和承诺的结果是正常的merges如何工作和如何使merge commits‘出去。我们merge(作为一个动词)的变化,和做一个merge(adjective)承诺(或"做一个merge",名词)。但是,作为我们noted简慢,git merge并不总是做这个。

/好的。 快进

有时,git merge说它"正在进行一次快速的合并"。这有点用词不当,因为在Git中,"快速转发"更准确地被视为分支标签更改的属性。使用此属性的其他两个命令是git fetchgit push,用于区分正常(或"快进")分支更新和"强制"更新。正确讨论快速转发需要了解提交图的细节,所以这里我要说的是,当您将分支标签从commit o(old)移动到commit n(new)时,就会发生这种情况,commit n将commit o作为祖先。好的。

git merge检测到合并参数是HEAD是另一个提交的祖先的情况之一时,它通常会调用这个快进操作。在这种情况下,Git只使用您告诉它合并的提交。根本没有新的提交,只是重新使用了一些现有的提交。Git不进行合并提交,也不进行任何合并为动词。它只是将您改为新的提交,几乎就像是由git reset --hard所做的:移动当前的分支标签并更新工作树。好的。

您可以使用--no-ff来抑制这种快进操作。5在这种情况下,git merge将进行新的合并提交,即使可能进行快进。您没有得到merge-a s-a-verb操作(没有工作要做),但是您得到了一个新的merge-commit,并且git更新了您的工作树来匹配。好的。挤压合并不是合并

请注意,我们在这里涵盖了三种情况中的两种:好的。

  • 动词形式加形容词/名词形式:一个普通的合并
  • 形容词/名词形式的合并,但没有动词:一个合并,是快进的,但你运行git merge --no-ff

缺少的第三个例子是动词不带名词:我们如何得到合并的动作,组合变化,不带名词/形容词形式的合并承诺?这就是"壁球合并"的由来。运行git merge --squash 命令git照常执行合并操作,但不要记录另一个分支/提交ID,以便最终的git commit执行正常的、非合并的单亲提交。好的。

就是这样,就是这样!它只是在最后进行一个正常的、非合并提交。奇怪的是,它强迫你做出承诺,而不是自己去做。(没有根本的理由必须这样做,我不知道为什么Git的作者选择让它这样做。)但这些都是机制,而不是政策:它们告诉你如何做出各种承诺,但不是你应该做什么,什么时候做,或者最重要的原因。好的。

5你可以告诉git merge,只有它能快速前进,它才能前进:git merge --ff-only。如果新的提交是可快速转发的,那么git merge将更新它。否则就是失败了。我做了一个别名,git mff,这样做了,因为通常我想要git fetch,然后看看我是否需要合并,重新组合,完全创建一个新的分支,或者其他什么。如果我能快速前进,我不需要做任何其他事情,所以如果git mff工作,我就完了。好的。什么样的合并可以使用,什么时候,为什么

为什么这个问题很难回答,就像所有哲学问题一样,没有一个正确的答案(但肯定是一堆错误的答案)。考虑一下这个事实:每次使用git merge时,您都可以做一些不同的事情,并使用相同的源代码来进行最新的提交。一个git merge有三个成功的结果(也就是说,一个合并,你不是git merge --abort来结束它,而是成功地结束它):好的。

  • 快进:没有新的提交;源代码是现有提交的源代码。
  • 真正的合并:新提交;源是合并的源。
  • 挤压合并:新提交;源是合并的源。

这三者之间的唯一区别(除了第一个明显的"根本没有新提交"之外)是它们在提交图中留下的记录。6快速前进显然没有留下任何记录:图与以前保持不变,因为您没有添加任何内容。如果这是你想要的,那就是你应该使用的。在一个你在跟踪别人的工作而从不做你自己的事情的存储库中,这可能是你想要的。这也是默认情况下你将得到的,而Git将"只为你工作"。好的。

如果进行常规合并,则会留下合并记录。所有现有的提交都保持原样,Git添加了一个新的提交,有两个8个家长。以后来的人会看到谁做了什么,什么时候,怎么做,等等。如果这是你想要的,这就是你应该做的。当然,一些工具(如git log将显示谁做了什么,什么时候做了什么,等等),通过显示所有历史的完整图片,可能会用所有的小细节掩盖大局视图。换言之,这是上边和下边。好的。

如果进行挤压合并,则不会留下合并记录。您可以创建一个新的commit来获取每个merge-as-a-verb动作,但新的commit不是merge-as-a-noun。以后来的人都会看到所有的工作,但不是从哪里来的。像git log这样的工具无法显示小细节,您和其他人只能看到一个大画面。同样地,这是上边和下边。但不利的一面可能更大一点,因为如果你发现你以后需要这些细节,它们就不存在了。他们不仅在git log的观点中存在,而且在未来的git merge的观点中也不存在。好的。

如果你以后再也不打算做一个被压扁的变化的git merge,这可能不是问题。如果你打算完全删除这个分支,放弃所有的个人变化,只保留单一的集体挤压合并变化,那么做git merge --squash的"坏"部分基本上是零"坏"值。但是,如果您打算继续处理这个分支,并在稍后再次合并它,那么这个特殊的不良值会大幅增加。好的。

如果您进行挤压合并是为了使git log输出"看起来更好"(显示更大的图片而不是用太多的细节掩盖它),请注意,有各种git log选项设计用于选择要显示的提交内容。特别是,--first-commit避免了完全遍历合并的分支,只显示合并本身,然后继续沿着提交图的"主线"。例如,您还可以使用--simplify-by-decoration忽略除标记的提交之外的所有提交。好的。

当然,在你的反应中也是如此;但是你的反应是私有的,最终会失效,所以我们将忽略它们。好的。

7这假设不管"他们"是谁,都不会通过重新调整或删除已发布的提交来"倒带"提交图。如果它们确实删除了已发布的提交,那么在默认情况下,您的Git将把这些提交合并回,就像它们是您自己的工作一样。这是任何发布Git存储库的人都应该认真考虑"倒带"这种提交的一个原因。好的。

8不允许任何奇特的章鱼融合。好的。好啊。


git merge-如果主服务器中不存在这些提交,将合并从分支到主服务器的所有提交[保留提交顺序]。它还添加了一个新的提交ID,显示http://repo name的合并分支'branch name'到"master"

现在git merge——squash——找到所有不同于master的文件,并将它们标记为modified。现在,当您提交这些代码时,它们将使用您提供的消息(就像正常提交一样)进入一个新的提交ID。