如何在不阻塞主进程的情况下使用Magit提交
在使用pre-commit钩子提交时,完成需要一段时间,提交完成前我的屏幕会无响应。于是,我想让magit c c 在不阻塞主进程的情况下运行。但没有找到相关选项。
解决方案
我经常遇到这个问题,慢速的pre-commit钩子把Magit里的 c c 变成了一段痛苦的等待,Emacs就会卡死。
Magit没有内置的异步交互式提交选项,无法在保持消息编辑器的同时也尊重钩子失败。Git的 pre-commit本就设计为同步,而Magit会同步调用 git commit,这样它能立即知道提交是成功还是失败。
据我在近年的Magit讨论中看到的情况,直到2025/2026年,也没有任何改动能让交互式 c c 在正确运行钩子的同时真正实现非阻塞。
对大多数人真的有效的做法是:
- 当你有信心时走快速通道:
- 只需要执行
c -(会添加 --no-verify),然后c c—— 立刻跳过所有钩子。 - 或者
c -a,如果你还想把所有改动都暂存的话。这个非常快。
- 找出根本原因:让pre-commit更快:
- 只在其中保留快速检查(格式化、基本语法、简单的静态检查工具)。
- 将慢性任务(完整测试、深度扫描)移到提交后钩子或持续集成中。 这样pre-commit在几秒内就能完成,Emacs不会卡死,同时你还能稍后获得反馈。
- 如果你真的需要后台提交,快速的异步变通方法(有限制):
``` (defun my/magit-async-commit () "Commit in background with a simple message prompt." (interactive) (let ((msg (read-string "Commit message: "))) (magit-run-git-async "commit" "-m" msg)) (message "Async commit running — check magit-process buffer if needed"))
(with-eval-after-load 'magit (transient-append-suffix 'magit-commit "c" '("A" "Async commit (no editor)" my/magit-async-commit))) ```
取舍:没有提交信息缓冲区、没有amend/模板功能,钩子失败只会在进程缓冲区中显示。
- 小的用户体验改进
(setq magit-process-popup-time 0)
这会让进程缓冲区立即显示,让你至少能看到进度,尽管在钩子执行时仍然是阻塞的。