离开 Magit 后的 Emacs
摘要
作者讲述了他们离开 Emacs 的 Magit Git 界面,转而采用 VC-mode 和自定义 Git 脚本等替代方案的经历,重点介绍了其中的调整和所学到的经验教训。
<p><a href="https://lobste.rs/s/b4vpj6/emacs_after_magit">评论</a></p>
查看缓存全文
缓存时间: 2026/05/20 02:23
# 告别 Magit 后的 Emacs
来源:https://sdf.org/~pkal/blog/emacs/sans-magit.html
几个月前,我停止了在 Emacs 中使用 Magit(https://magit.vc/)。起初只是因为 Magit 添加了一个新的依赖 `cond-let`(https://elpa.nongnu.org/nongnu/cond-let.html),与上游同名的宏开发产生了冲突。但我也早已对其依赖数量(比如 `llama`(https://elpa.nongnu.org/nongnu/llama.html))感到不满,而且总体上不喜欢基于 Transient(https://www.gnu.org/software/emacs/manual/html_mono/transient.html)的用户界面,所以最终坚持了这个决定。
首先得说:日常工具里少了 Magit 是明显的,也有点烦人。有些操作我已经太习惯用 Magit 完成,以至于不得不去查如何在没有它的情况下实现。而本文正是想记录这种体验。
第一个最直接的变化是:当需要执行某个 Git 操作时,我不再调用 `magit-status`(我将其绑定到 `C-c g`,而非默认的全局绑定 `C-x g`)。取而代之的是,我主要使用 `shell-command`(`M-!`),或者更明确地说,是我“改造过”的 `shell-command+`(https://elpa.gnu.org/packages/shell-command+.html)——我对其进行了扩展,让它始终异步执行某些命令(例如 `git`),或者干脆转而调用相应的 VC-mode 命令。因此,`M-! git diff RET` 实际上会调用 `vc-diff`,而不是仅仅将输出丢到“*Async Shell Command*”缓冲区(尽管在这种特定情况下,我通常会用 `C-x v D`(`vc-root-diff`))。同时,安装了 bash-completion(https://elpa.nongnu.org/nongnu/bash-completion.html)包也帮助我更快地找到 git 子命令的正确选项。
在其他操作中,我现在能更有效地使用 VC-mode。从 Emacs 31 开始,增加了一些有用的功能(主要由新任 Emacs 维护者 Sean Whitton(https://spwhitton.name/)贡献),例如在“*vc-changes-log*”缓冲区中按 `e` 键可以编辑之前的提交信息,这扩展了之前仅能更有效地修改已有提交信息的能力。详情请参阅 `etc/NEWS`。
但 Magit 中还有一些有用的复合命令特性。我发现最缺少的是:分离分支(创建一个新分支并将原分支重置到上游位置)以及轻松修正之前的提交。在网上搜索时,我想到了一个主意:在配置中添加 git 别名。我必须承认,我原本不太愿意这么做——同样不完全是技术原因,而主要是因为我将使用 git 别名与那些坚持用 `git c` 代替 `git commit`(或者更糟,添加 shell 别名 `gc`)来节省时间的人联系在一起。不过,我记起任何子命令 `git foo` 都会检查 `PATH` 中是否存在可执行文件 `git-foo`,并可以转而调用它。于是我为最常见的用例写了几个脚本:
- `git spinoff NEW-BRANCH-NAME`(https://sdf.org/~pkal/src+etc/git-spinoff),创建一个名为 `NEW-BRANCH-NAME` 的新分支,包含 HEAD 与当前分支上游状态之间的提交,然后将当前分支重置到上游状态。
- `git update`(https://sdf.org/~pkal/src+etc/git-update),基本上就是 `git pull --autostash --rebase` 的简写。
- `git fixup COMMIT`(https://sdf.org/~pkal/src+etc/git-fixup),尝试将暂存区中的更改合并到 `COMMIT` 上,然后将所有后续提交变基到修改后的更改之上。
这些都是非常基础的脚本,我只需用 `M-!` 调用,无需更多“魔法”。
有些 Git 命令需要用户输入,在终端中会启动一个 TUI 编辑器(如 vi 或 GNU nano)。由于我用 `M-!` 执行命令,这会成为问题——因为我并没有模拟一个真正的终端,也不打算这样做。Magit 使用 with-editor(https://elpa.nongnu.org/nongnu/with-editor.html)包来处理这个问题,我本来也考虑过使用它,但目前只是在 `init.el` 中设置了:
``
(setenv "EDITOR" "ed")
``
然后一直这样用。这不理想,但有点有趣,而且 99% 的情况下我只需要输入 `wq` 而已。
总的来说,这是一次有趣的尝试,目前效果还不错。我知道自己更属于 Emacs 的“集成(https://research.swtch.com/acme)开发环境”流派,所以有些做法可能看起来奇怪,但我希望也能引起一些人的兴趣。最后,必须澄清:本文是关于我如何使用 Git 的,*不是*对 Magit 或其开发者的攻击——我对 Magit 的看法完全出于个人偏好和需求,*并非*规范性陈述,不强求人人都该用 Emacs 操作 Git。
相似文章
还有人用 Emacs 吗?
作者对与 Emacs 数十年关系的个人反思,包括转向 VSCode 和 IntelliJ,最终因其独特功能回归 Emacs。
Magit 4.6 发布
Magit 4.6,Emacs 上流行的 Git 界面,已发布,改进了浏览 blob 的缓冲区,并在差异中增加了实验性的语法高亮。
Emacs 与 Bzr 的坎坷往事
文章回顾了 2008 年 GNU Emacs 开发者决定采用 Bazaar 而非 Git 作为版本控制系统的决策过程,重点强调了性能方面的顾虑,以及 Richard Stallman 坚持使用 GNU 软件包的立场,尽管技术基准测试显示 Git 更具优势。
软件界的Emacs化
作者讲述了在终端中阅读 Markdown 的烦恼,并描述了如何使用 Claude 快速构建一个自定义的 macOS Markdown 查看器(MDV.app),展示了 AI 如何让人能够迅速创建个人软件工具。
Git history 命令值得更多关注
文章重点介绍了新的 `git history` 命令及其 `fixup`、`reword` 和 `split` 子命令,这些命令提供了原子化且感知分支的提交历史编辑功能,带来了类似 jj 的益处,而无需切换版本控制系统。