我想知道是否有可能显示两个提交之间的差异是什么之一?换句话说,git 是否将修改后的提交保存在某个地方的历史记录中?
2 回答
修改后的提交与任何其他提交没有什么不同。从这个意义上说,完全有可能区分“正常”提交和修改后的提交。
换句话说,git 是否将修改后的提交保存在某个地方的历史记录中?
没有一些列表包含所有已修改的提交,不。修改后的提交就像所有其他提交一样在历史记录中。
当您修改提交时,它基本上会被删除并被一个新提交(它也获得一个新的提交哈希)替换,该提交具有原始提交的更改+修改后的更改。
在中git reflog
您可以看到您最近的操作,这确实显示了提交的修改。来自那里的引用可用于例如撤消git commit --amend
. 另请参阅如何撤消“git commit --amend”而不是“git commit”以获取更多详细信息。
我不认为我理解这个问题,但我认为部分原因是因为我认为你对做什么有错误的想法git commit --amend
。
git 中的提交实际上无法更改。所做git commit --amend
的只是使用故意更改的父 ID 编写新提交。
让我们看一下进行新提交的正常过程。
在进行新的提交之前,您修改工作树中的一些文件,然后使用git add
暂存这些更改,以便提交文件的新版本。这git add
会将文件的新版本放入 git 的“索引”,即它的暂存区。
已经在上一次提交中的文件已经在暂存区域中。因此,您将进行的新提交将包含所有原始文件,除了您更改的任何内容然后git add
-ed 将是新版本而不是旧版本。
现在你运行git commit
(不带--amend
)并且 git 执行以下操作:
- 收集提交消息(来自
-m
、-F
或运行您的编辑器); - 获取您的姓名和电子邮件,以及当前时间;
- 获取当前提交的 SHA-1 ID(不是新的);
- 使用暂存区编写一个“树”对象:这是将与新提交关联的源树;
- 使用所有这些信息(作者+提交者、树、父 ID 和您的消息)创建一个提交对象——这个新的提交对象具有一个新的唯一 SHA-1 ID;
- 最后,将新的 ID 写入分支,使分支标签指向新的 ID,而不是过去最尖端的分支。
最后一步“增长分支”,所以如果你曾经有一些提交,像这样:
... <- E <- F <- G <-- master
你现在还有一个:
... <- E <- F <- G <- H <-- master
分支名称(master
或任何可能的名称)现在指向您的最新提交H
,并H
指向您过去的最新提交G
。
如果你使用git commit --amend
,git 只会稍微改变这个序列:git 不会让新的提交 ( H
) 指向当前的 ( G
),而是让新的提交 ( ) 指向当前的父级(在这种情况下,F
):
G
/
... <- E <- F <- H <-- master
现在master
(或您所在的任何分支)指向H
,指向F
,依此类推。
如果你运行git log
,git 从当前提交 ( H
) 开始并记录它,然后移动到它的父提交 ( ) 并记录F
它,依此类推。提交G
似乎消失了。
在“reflogs”中,SHA-1 IDG
仍然存在(默认为 30 天)。有一个 reflog HEAD
,一个用于您当前的分支。如果您在分支上master
并且刚刚完成H
,那么master@{1}
就是 的上一个提示master
,即 commit G
。或者,如果您将 SHA-1 ID 保存在屏幕上的某个位置,则可以剪切并粘贴它以查看 commit G
。
(该--amend
开关也可以修改合并提交。这与上面的工作方式完全相同,只是意味着 git 必须将所有父 ID 从旧分支提示复制到新分支。)