V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
nowheretoseek
V2EX  ›  问与答

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

  •  
  •   nowheretoseek · 2021-08-22 15:55:23 +08:00 · 1196 次点击
    这是一个创建于 1217 天前的主题,其中的信息可能已经有所发展或是发生改变。

    是这样,最近两次提交的 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 的正确命令是什么?

    6 条回复    2021-08-24 20:19:27 +08:00
    ampedee
        1
    ampedee  
       2021-08-22 17:10:31 +08:00 via Android
    用 rebase
    nowheretoseek
        2
    nowheretoseek  
    OP
       2021-08-22 17:45:29 +08:00
    @ampedee 谢谢,参考 https://www.jianshu.com/p/0f1fbd50b4be 解决了问题,不过还是不大明白为什么会在步骤 3 中看到错误的 commit 时间,git 太深奥了……
    secondwtq
        3
    secondwtq  
       2021-08-22 21:57:11 +08:00   ❤️ 1
    > 发现 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
        4
    johnsona  
       2021-08-23 02:32:44 +08:00 via iPhone
    git reflog
    nowheretoseek
        5
    nowheretoseek  
    OP
       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
        6
    nowheretoseek  
    OP
       2021-08-24 20:19:27 +08:00
    @johnsona 用到了,上面贴的链接了介绍了 rebase 和 reflog 的用法,都上用了,对这俩命令大致有了点了解。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2561 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 04:08 · PVG 12:08 · LAX 20:08 · JFK 23:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.