当 git commit-msg hook 失败时如何恢复提交消息?

问题描述 投票:0回答:2

我正在使用 git 的钩子之一

commit-msg
来验证特定格式和内容的提交消息。

但是,每当提交消息未能通过挂钩时,我有时会丢失消息中的一段或更多文本。

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

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

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

git git-commit githooks
2个回答
21
投票

提交消息存储在

.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
代替。


3
投票

背景

如前所述,运行时

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

我认为重用消息不是默认行为,因为它可能 干扰

prepare-commit-msg
钩。 理想情况下,会有一个切换 默认情况下可以启用重用,以避免数据丢失。 这 下一个最好的事情是使用 git 别名覆盖 git 子命令, 但不幸的是,目前这是不可能的,那就是 不太可能改变。 所以我们只能为它创建一个自定义别名。 我使用了与已接受答案中的别名类似的别名:

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

也可以为git本身制作一个包装器并根据 关于参数(即:关于子命令),尽管这需要确保 所有后续对

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

新奇

最后,我刚刚了解到 使用不同的包装文件别名 名称是一个选项:

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

并且还要避免干扰,因为在外部使用时不会扩展别名 脚本

© www.soinside.com 2019 - 2024. All rights reserved.