【问题标题】:How can I recover the commit message when the git commit-msg hook fails?当 git commit-msg 挂钩失败时,如何恢复提交消息?
【发布时间】:2018-10-24 17:44:53
【问题描述】:

我正在使用 git 的一个钩子 commit-msg 来验证特定格式和内容的提交消息。

但是,每当提交消息失败时,我有时会丢失消息中的一段或更多文本。

我曾尝试将其保存在某个地方,但我不确定如何在用户尝试修复失败的提交消息时将其恢复给用户,只显示最后一条好的提交消息。

以前有没有其他人处理过这个问题?你是怎么解决的?

信息:我正在使用 python 脚本进行验证。

【问题讨论】:

    标签: python git githooks


    【解决方案1】:

    提交消息存储在.git/COMMIT_EDITMSG。在“失败”的提交尝试之后,您可以运行:

    git commit --edit --file=.git/COMMIT_EDITMSG
    

    或更短,例如:

    git commit -eF .git/COMMIT_EDITMSG
    

    它将在您的$EDITOR(或您在 Git 配置中设置的编辑器)中加载错误的提交消息,以便您可以尝试修复提交消息。您还可以为上述设置一个别名:

    git config --global alias.fix-commit 'commit --edit --file=.git/COMMIT_EDITMSG'
    

    然后改用git fix-commit

    【讨论】:

    • 非常感谢!将此别名集成到我的脚本中,并将说明集成到错误消息中。这就像一个魅力。
    • @MaggieS。我建议不要在脚本中使用别名本身,以保持脚本的可移植性和尽可能“抽象” - 在那里使用完整的命令。像这样的别名更适合交互使用。
    【解决方案2】:

    背景

    As stated,当运行git commit时,git启动你的编辑器指向 $GIT_DIR/COMMIT_EDITMSG 文件。除非有问题的 commit-msg 钩子 移动/删除/损坏文件,消息应该仍然存在。

    我认为重用消息不是默认行为,因为它可能 干扰prepare-commit-msg 钩子。理想情况下,会有一个切换 可用于默认启用重用,以避免数据丢失。这 下一个最好的事情是override a git sub-command with a git alias, 但不幸的是,目前这是不可能的,那就是 unlikely to change。所以我们要为它创建一个自定义别名。 我使用了一个类似于已接受答案中的别名:

    git config alias.recommit \
    '!git commit -F "$(git rev-parse --git-dir)/COMMIT_EDITMSG" --edit'
    

    然后,在运行git recommit 时,被拒绝的提交消息的内容应该 出现在编辑器中。

    加法

    请注意,对于存储库中的第一次提交,两个别名都会失败,因为 COMMIT_EDITMSG 文件尚未创建。为了使它也适用于 这种情况下,看起来有点复杂:

    git config alias.recommit \
    '!test -f "$(git rev-parse --git-dir)/COMMIT_EDITMSG" &&
    git commit -F "$(git rev-parse --git-dir)/COMMIT_EDITMSG" --edit ||
    git commit'
    

    可以简写为:

    git config alias.recommit \
    '!cm="$(git rev-parse --git-dir)/COMMIT_EDITMSG" &&
    test -f "$cm" && git commit -F "$cm" --edit || git commit'
    

    无论哪种方式,考虑到增加的安全性,对于交互式使用,您甚至可以 默认使用上述别名之一,而不是 git commit

    也可以 make a wrapper for git itself 并根据 关于论点(即:关于子命令),尽管这需要确保 对git 的所有后续调用都引用原始二进制文件,以免它们 导致无限递归:

    git () {
        cm="$(git rev-parse --git-dir)/COMMIT_EDITMSG"
    
        case "$1" in
        commit)
            shift
            test -f "$cm" && command git commit -F "$cm" --edit "$@" ||
            command git commit "$@"
            ;;
        *)
            command git "$@";;
        esac
    }
    

    请注意,如果将以上内容添加到您的 rc 文件中(例如:~/.bashrc),那么每个 调用其中的git 将引用包装器,除非您将它们放在前面 还有command

    新奇

    最后,我刚刚得知aliasing to a wrapper file with a different name 是一个选项:

    PATH="$HOME/bin:$PATH"
    export PATH
    alias git='my-git'
    

    所以包装器(例如:~/bin/my-git)可以简单得多:

    #!/bin/sh
    cm="$(git rev-parse --git-dir)/COMMIT_EDITMSG"
    
    case "$1" in
    commit)
        shift
        test -f "$cm" && git commit -F "$cm" --edit "$@" ||
        git commit "$@"
        ;;
    *)
        git "$@";;
    esac
    

    同时也避免干扰,如aliases are not expanded when used in external scripts

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-11
      • 2013-10-16
      • 1970-01-01
      • 2021-10-03
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多