假设我
git rebase -i HEAD~3
并在文本编辑器中打开以下内容:
pick ae27841 Commit 1
pick fd8a71e Commit 2
pick badd490 Commit 3
我想将这3个提交转换为1个提交,因此我可以将该提交推送到我的存储库,然后调用pull请求。我知道有两种方法可以解决这个问题:
我可以将一个提交保留为pick
并压缩另外两个提交。即
pick ae27841 Commit 1
s fd8a71e Commit 2
s badd490 Commit 3
我可以删除这3次提交中的2次。即。
pick ae27841 Commit 1
这两个命令有什么区别?据我了解,每次提交都是项目的不同版本。因此我的最新提交将是我的最新版本吗?所以我最近的提交就是我需要保留的一切。由于其他2个提交是项目的“旧”版本,我不需要它们,所以我可以删除它们。方法2
是否正确的方法将我的3个提交转换为一个?
如果是这样,我需要什么样的情况来压缩我的提交呢?
这里的正确方法是什么?压缩或删除提交?
答案 0 :(得分:1)
删除提交时,将删除它从历史记录中引入的所有更改,即从其后的所有提交中删除。 Squashing也会从历史记录中删除提交,但其更改将合并到生成的提交中。
答案 1 :(得分:0)
更新 - 从评论中看,误会似乎与问题有点不同,所以我在底部添加了一些注释
原始答案
压缩提交是将其更改添加到之前的提交中。删除提交是为了不执行更改。
所以,如果你有
A --- B --- C <--(master)
其中A
创建A.txt
,B
创建B.txt
,C
创建C.txt
,如果你压缩你提交的提交
ABC <--(master)
其中ABC
是一个创建A.txt
,B.txt
和C.txt
的提交,而如果您删除了B
和C
A <--(master)
并且只创建了A.txt
。
添加了备注
因此,git COMMIT
对象除了其他内容外,还有一个对TREE
对象的引用,表示当时的项目内容。 TREE
大致是一个目录列表,包含其他TREE
对象(子目录)和BLOB
对象(文件)的名称列表。
在内部(如果对象被打包),BLOB
可能表示为来自另一个BLOB
的增量 - 但当前版本通常是完整对象,其中delta用于构建旧版本的文件。
在任何一种情况下,在任何有效的仓库中,您可以重建项目的完整状态,因为它是从TREE
上的COMMIT
参考提交的; PARENT
用于历史记录跟踪,但不需要构建项目状态。
然而,当您在rebase期间pick
提交时,这并不意味着您正在复制该提交TREE
;相反,它意味着git将找出该提交的TREE
和该提交PARENT
的{{1}}之间的差异,并应用该组变化。
在TREE
和REBASE
操作期间,根据与父项的差异处理提交的这一想法非常重要。在某种程度上,即使提交是结构化的,它可以重现项目的快照,但通常认为它只是代表那组更改。
答案 2 :(得分:0)
在Git中,压缩和删除在技术上是相同的。他们创建新的提交,将一些现有的提交作为父级,并且不删除任何提交。
假设提交历史记录是ABCD。当压缩BCD时,创建新的提交E作为A的新子节点。新提交包括BCD的更改。 BCD仍在那里。然后,当前ref(例如,分支或HEAD)从A移动到E(压缩合并)或从D移动到E(交互式rebase)。如果裁判在D处并且现在在E处,那么BCD似乎已经丢失但实际上他们仍然存在。
至于&#34;删除&#34;通过樱桃挑选C到A,一个新的提交C&#39;是作为A. C&#39;的新孩子而创建的。具有C的等效变化(并不总是与C完全相同)。 BCD仍在那里。当前的ref将A移动到C&#39;。当您运行git reset
时,当前引用从一次提交移动到另一次提交。
另一个例子是git commit --amend
。当你为ABCD运行它时,新的提交D&#39;被创造为C的新生儿。 ref从D移动到D&#39;。现在D似乎被删除但它仍然存在。据说Amend修改并更新了最后一次提交,但实际上它创建了一个新的兄弟提交。
答案 3 :(得分:0)
首先,关于git的这个概念在这里是错误的:
据我了解,每次提交都是项目的不同版本。 因此,我的最新提交将是我的最新版本吗?
删除提交2和提交3时,提交1将更改。让我称之为(承诺1)&#39;。即使(承诺1)&#39;使用Commit 1保持相同的提交消息,与先前版本相比保持相同的修改,它们不是相同的版本。 (承诺1)&#39;和Commit 1有不同的版本哈希。
方法1
:这就是你想要的。保留最后一个版本的代码,保留最后一次提交消息。但是你应该注意HASH已经改变了。
方法2
:不是你想要的。提交2和提交3中提交的代码将丢失。