误用了 git commit -amend, git log 中的日期显示错误

2021-08-22 15:55:23 +08:00
 nowheretoseek

是这样,最近两次提交的 commit message 写的有些问题,所以想改一下,查了一下是用git commit -amend命令,于是进行了下面一系列操作(两次 commit 在下面分别称为最近一次上一次吧,最近一次就是刚才即 22 日下午,上一次是 20 日晚上):

1 、运行git commit -amend后打开了 vim,编辑了最近一次的 message,保存退出后运行git log查看发现一切 OK

2 、想修改上一次的 message,查了下上次 commit id 开头是 6b2c8b16,于是运行git commit --amend 6b2c8b16,报错提示error: 路径规格 '6b2c8b16' 未匹配任何 git 已知文件,简单搜了下尝试运行了git commit -c 6b2c8b16 --amend,打开了 vim,没仔细看后面#开头的文件变动列表(后来再次运行确认了是最近一次的文件变动列表),改完了保存退出

3 、运行git log确认修改结果,发现悲剧了,最近一次的 commit message 没有了,取而代之的是刚修改的上一次的 message,诡异的是 Date 行显示的也是上一次的提交日期,可是git status并查看代码发现最近一次的修改没有回滚,疑惑到底发生了什么

4 、安装了 sourcetree 打开项目,发现 commit 列表显示的最近一次的日期是刚才 vim 修改 message 的时间,即它跟 git log 中 Date 行显示的并不一样。而 source tree 的概况窗口显示如下:

提交:8882c410631f5418b0b7ed14c8bc7777fca9f312 [8882c41]
父级:6b2c8b16d5
日期:2021 年 8 月 20 日 23:05:02
提交时间:2021 年 8 月 22 日 15:05:21

我的问题是:

1 、步骤 3 中描述的问题该如何解决呢? git log 显示的日期不是实际 commit 的时间太别扭了。

2 、我运行的git commit -c 6b2c8b16 --amend导致的结果是设计中的吗,还是误用命令触发了 bug 什么的?

3 、修改之前的 commit message 的正确命令是什么?

1239 次点击
所在节点    问与答
6 条回复
ampedee
2021-08-22 17:10:31 +08:00
用 rebase
nowheretoseek
2021-08-22 17:45:29 +08:00
@ampedee 谢谢,参考 https://www.jianshu.com/p/0f1fbd50b4be 解决了问题,不过还是不大明白为什么会在步骤 3 中看到错误的 commit 时间,git 太深奥了……
secondwtq
2021-08-22 21:57:11 +08:00
> 发现 commit 列表显示的最近一次的日期是刚才 vim 修改 message 的时间,即它跟 git log 中 Date 行显示的并不一样。

根据发帖时间推算,你这个 “提交时间:2021 年 8 月 22 日 15:05:21” 对应的应该是你说的“刚才 vim 修改 message 的时间”,而“git log 中 Date 行”显示的应该是“日期:2021 年 8 月 20 日 23:05:02”,即“上一次的提交日期”。
Git 每个 commit 有两个日期,一个 AuthorDate,一个 CommitDate,git log 默认只显示 AuthorDate,用 git log --pretty=fuller 可以全部显示。你可能把这两个搞混了。

我没用过 git commit -c,但是 man 中对 git commit -c 的描述是:
> -C <commit>, --reuse-message=<commit>
> Take an existing commit object, and reuse the log message and the authorship information (including the timestamp) when creating the commit.
> -c <commit>, --reedit-message=<commit>
> Like -C, but with -c the editor is invoked, so that the user can further edit the commit message.
不知道你是怎么查到的,这个意思应该是你运行 git commit -c --amend 时,其实改的依然是 HEAD,只不过把 HEAD~1 的部分元数据搬了过来。

Git 和区块链一样都是类 Merkle Tree,也就是一个 commit 会递归地依赖于之前的所有 commit 。要想在 branch tip 之后的地方动刀子就必须重新生成中间的所有 commit ( commit message,author 和 commit 的元数据都会被放在一起做 hash )。所以直接改后面的 commit message 应该不太靠谱。
johnsona
2021-08-23 02:32:44 +08:00
git reflog
nowheretoseek
2021-08-24 20:18:11 +08:00
@secondwtq 谢谢!关于 Merkle Tree 的解释很有启发性,我当时简单 Google 怎么改之前的 commit message,看到一个条目预览里有-c 参数的用法,没点进去细看,想当然地认为-c 是指定 commit id 的;认为可以直接改前面 commit 的 message 也是因为不了解这个类区块链的存储机制(其实现在也不了解,不过知道跟常见的存储不一样,有很强的前向依赖)。
我运行`git commit -c 6b2c8b16 --amend`时应该是重用了上一次的 message,对最近一次的 message 进行了编辑,这样一来最近一次就记录了上一次的 author date,然后我又不知道 git log 默认显示的是 author date,以为是 commit date,所以会有上面的疑惑。
现在疑惑解开了,再次感谢!
nowheretoseek
2021-08-24 20:19:27 +08:00
@johnsona 用到了,上面贴的链接了介绍了 rebase 和 reflog 的用法,都上用了,对这俩命令大致有了点了解。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/797302

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX