Saturday, 14 March 2026
I stopped using Magit with Emacs a few months ago. Initially this was just because Magit added a new dependency cond-let that was conflicting the upstream development of a macro by the same name, but I had already taken issue with the number of dependencies such as llama, and generally do not enjoy Transient-based user interfaces, so I ended up sticking with the descision.
First things first: The absence of Magit in my regular arsenal is noticeable and slightly annoying. There are things I have gotten so used to doing via Magit, that I had to look up how I could do them without. And it is about this experience that I want to write about here.
The first and most immediate difference is that when I have to perform some Git-action, I don’t call magit-status (which I had bound to C-c g instead of the default global binding C-x g). Instead I mostly use shell-command (M-!), or more specifically my “fork” shell-command+ that I had extended to always run certain commands asynchronously, such as git or even defer to the respective VC-mode commands. So M-! git diff RET actually calls vc-diff, instead of just spitting the output into “*Async Shell Command*” (even if in this specific case I’d usually invoke C-x v D (vc-root-diff)). Having the bash-completion package installed also helps to find the right flags for git subcommands.
In other operations I can now use VC-mode more effectively. As of Emacs 31, a number of useful features have been added (mostly by the now new Emacs maintainer Sean Whitton) such as the ability to edit previous commit messages by pressing e in the “*vc-changes-log*” buffer, which extends the previous capabilities to just amend an existing commit message more effectively. See etc/NEWS for more details.
But there are useful features in Magit that are actually composite commands. The ones I found missing the most were spinning of branches (creating a new branch and reverting the previous branch to the upstream position) and easy fixups of previous commits. When researching online, an idea I came up upon was to add git alii to my configuration. I have to admit that I was disinclined to do so, again not so much for necessarily technical reasons, but mostly because I associate the usage of a git alias with people who insist on saving time by writing git c instead of git commit (or worse yet, they add a shell alias gc). Instead, I recalled that any subcommand git foo checks if an executable git-foo is in PATH and can defer to that instead. So I wrote scripts for the most common use-cases that I ran into
git spinoff NEW-BRANCH-NAME, create a new branch NEW-BRANCH-NAME with the commits between HEAD and the upstream state of the current branch, and then reset the current branch to the upstream state.
git update, is basically just a shorthand for git pull --autostash --rebase.
git fixup COMMIT, tries to amend the changes in the staging area onto a COMMIT, and then rebase all subsequent commits onto the modified changes.
These are really basic scripts that I just invoke using M-!, no further magic involved.
Some Git commands require user input, which in a terminal would start a TUI editor like vi or GNU nano. As I am executing commands using M-!, this is an issue, since I am not emulating a proper terminal, and do not intend to do so. Magit handles this using the with-editor package, which I have been thinking about using as well, but for now I just set
(setenv "EDITOR" "ed")
in my init.el and have been running with it since. It is not ideal, but slightly funny, and 99% of the time all I have to do is write wq anyway.
All in all this was an interesting exercise, and for now it works well enough. I know I am more in the “integrating development environment” school of Emacs, so some of my practices might appears strange, but I hope some might also be intrigued. Finally, I have to clarify that this post is about how I work with Git, and is not a hit-piece on Magit or anyone working on Magit — the issues I take with Magit are due to my own preferences and requirements, and not normative statements on how everyone should use Git with Emacs.