4

假设我这样做

git rebase -i HEAD~3

并在文本编辑器中打开以下内容:

pick ae27841 Commit 1 
pick fd8a71e Commit 2
pick badd490 Commit 3

我想将这 3 个提交转换为 1 个提交,以便我可以将该提交推送到我的存储库,然后调用拉取请求。我知道有两种方法可以解决这个问题:

  1. 我可以留下一个提交pick并压缩另外两个。IE

    pick ae27841 Commit 1 
    s fd8a71e Commit 2
    s badd490 Commit 3
    
  2. 我可以删除这 3 个提交中的 2 个。IE

    pick ae27841 Commit 1 
    

这两个命令有什么区别?据我了解,每次提交都是项目的不同版本。因此,我的最新提交将是我的最新版本,对吗?所以我最新的提交就是我需要保留的所有内容。由于其他 2 个提交是项目的“旧”版本,因此我不需要它们,因此我可以删除它们。那么方法2是将我的 3 个提交转换为一个的正确方法吗?如果是这样,我需要什么样的情况来压缩我的提交?

这里的正确方法是什么?压缩或删除提交?

4

4 回答 4

1

更新- 从评论看来,误解与问题有点不同,所以我在底部添加了一些注释


原始答案

压缩提交是将其更改添加到之前的提交中。删除提交就是不执行其更改。

所以如果你有

A --- B --- C <--(master)

如果你压缩你得到的提交,在哪里A创建A.txtB创建B.txtC创建C.txt

ABC <--(master)

哪里ABC是创建A.txt,B.txt和的单个提交,C.txt而如果你删除B并且C你得到

A <--(master)

并且只会A.txt被创建。


添加注释

因此,一个 gitCOMMIT对象除其他外,还具有对TREE代表您当时项目内容的对象的引用。ATREE大致是一个目录列表,包含其他TREE对象(子目录)和BLOB对象(文件)的名称列表。

在内部(如果对象被打包),aBLOB可能表示为另一个的增量BLOB- 但当前版本通常是完整的对象,增量用于构造文件的旧版本。

在任何一种情况下,在任何有效的 repo 中,您都可以重建项目的完整状态,因为它是从 ; 上的TREE引用提交的COMMIT。用于PARENT历史跟踪,但不需要用于构建项目状态。

但是,当您pick在变基期间提交时,这并不意味着您正在复制该提交的TREE; 相反,这意味着 git 将找出该提交TREE和该提交之间PARENT的差异TREE,并应用该组更改。

这种根据提交与父项的差异来处理提交的想法在REBASEMERGE操作期间都很重要。在某种程度上,即使提交是结构化的,因此它可以重现项目的快照,但将其视为仅代表一组更改通常很有用。

于 2017-05-31T16:05:42.340 回答
0

删除提交时,您会从历史记录中删除它引入的所有更改,即从它后面的所有提交中删除。挤压也会从历史记录中删除提交,但其更改会合并到生成的提交中。

于 2017-05-31T16:03:02.170 回答
-1

在 Git 中,压缩和删除在技术上是相同的。他们创建新的提交,将一些现有的提交作为父提交,并且没有删除任何提交。

假设提交历史是 ABCD。压缩 BCD 时,会创建一个新的提交 E 作为 A 的新子级。新提交包括 BCD 的更改。BCD 仍然存在。当前 ref(例如分支或 HEAD)然后从 A 移动到 E(壁球合并)或从 D 移动到 E(交互式变基)。如果 ref 位于 D 而现在位于 E,则 BCD 似乎丢失了,但实际上它们仍然存在。

至于通过cherry-pick C对A的“删除”,新的提交C'被创建为A的新子级。C'具有C的等效更改(并不总是与C完全相同)。BCD 仍然存在。当前参考将 A 移动到 C'。当您运行git reset时,当前 ref 从一个提交移动到另一个提交。

另一个例子是git commit --amend。当您为 ABCD 运行它时,会创建一个新的提交 D' 作为 C 的新子级。参考从 D 移动到 D'。现在 D 似乎已删除,但它仍然存在。据说 Amend 会修改和更新最后一次提交,但实际上它会创建一个新的同级提交。

于 2017-05-31T23:40:55.090 回答
-1

起初,这个关于 git 的概念在这里是错误的:

据我了解,每次提交都是项目的不同版本。因此,我的最新提交将是我的最新版本,对吗?

当你删除 Commit 2 和 Commit 3 时,Commit 1 会改变。让我称之为(提交 1)'。即使 (Commit 1)' 与 Commit 1 保持相同的提交消息,与以前的版本相比保持相同的修改,它们不是相同的版本。(Commit 1)' 和 Commit 1 具有不同的版本哈希。

方法1:这就是你想要的。保留最新版本的代码,保留最后的提交信息。但是你应该注意 HASH 已经改变了。

方法2:不是你想要的。在 Commit 2 和 Commit 3 中提交的代码将丢失。

于 2017-06-01T03:41:20.983 回答