Magit and Majutsu: discoverable version-control
quality 1/10 · low quality
0 net
AI Summary
Article reviews Magit, an Emacs Git interface with discoverable transient-window design, and Majutsu, a new Magit-style interface for Jujutsu version-control system. Both use context-sensitive keyboard shortcuts and in-editor command discovery to simplify version-control workflows compared to traditional CLI interfaces.
Entities
Magit
Majutsu
Jujutsu
Marius Vollmer
Jonas Bernoulli
Brandon Olivier
LWN.net
Magit and Majutsu: discoverable version-control [LWN.net] LWN .net News from the source Content Weekly Edition Archives Search Kernel Security Events calendar Unread comments LWN FAQ Write for us Edition Return to the Front page User: Password: | | Log in / Subscribe / Register Magit and Majutsu: discoverable version-control By Daroc Alden March 4, 2026 Jujutsu is an increasingly popular Git-compatible version-control system. It has a focus on simplifying Git's conceptual model to produce a smoother, clearer command-line experience. Some people already have a preferred replacement for Git's usual command-line interface, though: Magit , an Emacs package for working with Git repositories that also tries to make the interface more discoverable. Now, a handful of people are working to implement a Magit-style interface for Jujutsu: Majutsu . Magit was started by Marius Vollmer in 2008; over time, the project grew organically to cover the users' needs for an intuitive Git interface. The current version is v4.5.0, and new releases come every few months. The project's statistics page shows that a majority of the code at this point has been written by Jonas Bernoulli, but many authors have contributed improvements for their specific workflows and use cases. The result is a startlingly comprehensive feature set, which Bernoulli calls " essentially complete ", covering " about 90% of what can be done using git ". Majutsu is much younger: it was started in November 2025 by Brandon Olivier and has had six contributors so far, reaching version 0.6.0 on February 12. Its interface is already fairly comprehensive, however, owing both to Jujutsu's fewer corner cases and to the libraries written for Magit. Both projects are licensed under version 3 of the GPL, and Majutsu reuses Magit's interface design and libraries for handling transient windows. (Emacs predates most graphical interfaces, and calls the things everyone else calls windows "frames". It calls panels that subdivide a frame "windows".) Discoverable design Magit's transient windows are core of its semi-graphical interface, allowing the package to combine keyboard-driven actions with text-based status display. When Magit is started for the first time (by typing " C-x g " or " M-x magit ", depending on how good one is at remembering arcane Emacs incantations), it shows a status summary screen: From that status screen, there are a number of keyboard shortcuts that can be used to perform Git operations. Hitting " d ", for example, brings up the transient window for diffs, which lists all of the various things that can be done with diffs in Magit: Continuing to type the characters shown in green (on my theme, at least) applies possible command-line flags — which are saved until they are reset. For example, my --stat and --no-ext-diff flags (which generate a diffstat and turn off external diffing programs, respectively) are already turned on, and will be applied to all diff-related commands I use until I turn them off again. Actually choosing an operation to perform requires typing one of the un-prefixed letters shown at the bottom of the transient window (not shown here because they've scrolled off the screen). Typing the same letter again, however, is always bound to "do what I mean", and does a reasonable thing involving the current cursor position in the status buffer is. So, hitting " d " again (with my cursor in the status buffer on one of the listed recent commits) opens the diff associated with the chosen commit in a new window: Typing " q " will close any of Magit's temporary windows and return to the status buffer. Typing " ? " lists all of the keys that pop up a transient window to begin with, although they're mostly mnemonic, such as " l " for logs or " c " to commit. Magit commands like this are context-sensitive. If the cursor in the status buffer is on a commit identifier (branch, tag, or hash), hitting " d d " shows the diff associated with that commit. If the cursor is on a file with unstaged changes, hitting " dd " shows the diff of that file against the staging area. Within that diff, placing a cursor on a particular hunk and typing " s " stages it. Normal Emacs navigation, such as clicking or arrow keys, suffices to navigate to any Git object, such as a file, commit, hunk, or tree. Once the cursor is on it, the default contextual commands will do something useful. When updating something about Git's state using Emacs, such as staging or unstaging a hunk, all Magit's buffers remain automatically in sync. This includes editing a file in the repository with Emacs — saving the edited file will make Magit update the diffs if they are open in another window. If the repository is updated outside of Magit, typing " g " forces a manual refresh. This design makes the use of Magit pleasingly discoverable — performing simple operations is intuitive, and all of the text on the status screen can be interacted with. Performing a more complex operation involves opening the appropriate transient window and then turning on and off options and selecting the appropriate operation. It doesn't require going to the Magit manual or the Git manual , because there is a handy short reference guide right there in Emacs. By the same token, for all that Magit calls itself an alternate Git porcelain, one's existing knowledge of the Git command line is not obviated: Magit commands can use almost all of the same flags and Git subcommands as the normal command-line interface. Majutsu Despite operating on top of a different version-control system, Majutsu looks fairly similar at first glance: The main difference is that Jujutsu does away with the concept of a staging area: there is always a particular working commit (given the short name "@"), and one just edits that commit in-place, rather than staging changes and committing them only once they're finished. Consequently, Majutsu puts the graph of recent commits at the top, with expanded details about the state of the current working commit down below. The interface works exactly the same way as Magit, which is unsurprising since it reuses Magit's libraries: start typing, and a transient window will pop up to show possible completions of the command. Majutsu does have fewer transient windows (25 vs. Magit's 37), but that is partially a result of Jujutsu having fewer commands than Git. The Majutsu manual goes into more detail about the available transient windows. It does have an overall more bare-bones feel than Magit, which is somewhat to be expected with many fewer years of contributions. The graph in the main status window shows some differences from Git's model — for example, it shows commit identifiers (on the left side, starting with a pink or purple letter) instead of commit hashes. Jujutsu commit identifiers are stable through rebases and other history-modification operations, so they can be used to refer unambiguously to a commit even in the middle of a rebase. The colored letters at the beginning highlight the minimum prefix needed to refer to them unambiguously: Jujutsu will understand "r" to refer to commit "rkrmpkzv", at least until the repository gets another commit ID starting with "r". Jujutsu commits do still have cryptographic hashes — for signing, and for interoperability with Git — which can be seen at the bottom of the status window, starting with blue letters. These names, while normally quite helpful at the Jujutsu command-line, are less helpful in Majutsu, because commits are typically referred to by placing the cursor on them instead of referring to them by name. An example of that is Majutsu's rebase interface, which is simplified compared to Magit's interface. In Magit, a rebase is started using " r r ", whereupon one will have to select a starting revision, and go through Git's normal interactive-rebase workflow. In Majutsu, the experience is more visual. A rebase starts with " r ", but then one can select which revisions should be picked, squashed, or rebased onto directly in the main status window or in the detailed log window. Once the correct commits have been selected pressing return actually performs the rebase. The procedure is greatly streamlined compared to Magit, which makes sense given that Jujutsu's design encourages rebasing more frequently than Git does. There are some rough edges with Majutsu. Using it to clone a new Git repository (with " M-x majutsu-git-clone ") was a bit confusing — it warned me about being used outside a Jujutsu repository, and asked if I wanted to create one. When I did so and then cloned my target repository, it checked it out into a subdirectory, leaving me with two nested repositories. That's a fairly minor detail, however. More annoying is the fact that Jujutsu's log command (and therefore Majutsu's status buffer) doesn't show commits from before importing a Git repository. This is despite the fact that Jujutsu supports operating colocated with Git, using both in the same repository. Subsequent commits made with Git in a colocated repository are shown, but it makes for an awkward transition. Other operations, such as committing and moving bookmarks (the equivalent of Git's tags) around, went smoothly. Jujutsu is an interesting experiment in building a version-control system with a simplified design. After years of using Git, it can feel uncomfortable — but Majutsu makes it easy to explore. For a version-control system that has to wrestle with Git's dominance, having a discoverable interface feels like an important step toward making it easier for inveterate Git users to migrate. Majutsu has a ways to go before it reaches Magit's level of polish, but it's more than ready to help people curious about Jujutsu experiment without leaving the comfortable embrace of Emacs. to post comments Less needed than magit Posted Mar 4, 2026 16:52 UTC (Wed) by marcH (subscriber, #57642) [ Link ] (3 responses) I sincerely wish majutsu as much success as magit and I bet I will use it someday but I'm afraid it's needed nowhere near as much. Before I learned JJ, I used to find magit indispensable to massively speed up "instant fixups", interactive rebases etc. compared to using the (still pretty horrible) git command line. But JJ's command line is a joy to use and automates away the vast majority of git's tediousness for history management. > After years of using Git, it [JJ] can feel uncomfortable — but Majutsu makes it easy to explore. For a version-control system that has to wrestle with Git's dominance, having a discoverable interface feels like an important step toward making it easier for inveterate Git users to migrate. "We can solve any problem by introducing an extra level of indirection" and that's exactly what magit did for me for years. But JJ simply got rid of all these user interface issues, by design. For instance, interactive "rebases" have become much less frequent because many of them happen automatically. The only JJ road bumps and confusion I've experienced were related to its interaction with git, especially with git branches and remotes. I wouldn't have wanted "too many indirections" obscuring and restricting things then. Moreover, there are several outstanding JJ tutorials available and they all teach JJ "directly". My 2 cents, sorry to disagree. Less needed than magit Posted Mar 4, 2026 17:52 UTC (Wed) by daroc (editor, #160859) [ Link ] Disagreement is great! I think Jujutsu has an interesting design, so I wanted to take the chance to explore Majutsu when the topic came up in our planned topics list, but I haven't had the chance to use it much. It's good to hear from an actual Magit and Jujutsu user about their experience. Less needed than magit Posted Mar 5, 2026 8:00 UTC (Thu) by gasche (subscriber, #74946) [ Link ] (1 responses) I understand the general idea -- I also see the need for rich non-standard tooling on top of the VCS as a sign of weakness or at least missing features in the underlying, standard tools. Specifically for interactive rebases, I have been missing an easy way to reorder commits in jj. Good news, 0.39 which was just rebased comes with `jj arrange`, which offers an interactive-rebase-like TUI for reordering commits. Less needed than magit Posted Mar 5, 2026 15:26 UTC (Thu) by marcH (subscriber, #57642) [ Link ] Interactive rebases was probably the top reason why I used magit so much. Now I very rarely tell jj to move more than one or two commits at a time because: - many rebases come "for free". For instance: when editing a commit which is not last (not "HEAD"). - jj absorb and "mega" merges mean I don't need to re-order before pushing https://v5.chriskrycho.com/journal/jujutsu-megamerges-and... Even before "jj arrange" it was already possible to move several commits at once using the command line. Only to a single destination. "jj arrange" looks useful and very nice to have but it won't be used as much as "git rebase [-i]" which was required for almost everything related to history rewrites. Universality Posted Mar 4, 2026 18:17 UTC (Wed) by quotemstr (subscriber, #45331) [ Link ] (4 responses) Would it be so hard to fold some of this functionality into the built-in SCM-agnostic vc facilities? (Well, you'd have to get over core resistance to Just Doing Things, but that's a separate matter.) Have we, as an industry, just lost a sense for building one thing that abstracts over N things instead of building the same interface N times? Is it mobile-app culture leaking into dev tooling? Universality Posted Mar 4, 2026 20:48 UTC (Wed) by nix (subscriber, #2304) [ Link ] (2 responses) Honestly, the problem really is that vc's UI is so different from magit's transient-mode-based one that you'd need to completely rewrite vc's user interface, or throw away what makes magit's so usable -- and both of these would face severe resistance from one camp or the other. Breaking compatibility and existing user workflows like that is very much not the Emacs way. I think magit's UI is far superior and more discoverable, but then of course it is: it's decades newer and written with the benefit of a lot more experience with various sorts of Emacsy UIs than the old, old vc, which was originally built for RCS and thus has a massive impedance mismatch with modern VCSes to overcome as well. Universality Posted Mar 4, 2026 21:12 UTC (Wed) by quotemstr (subscriber, #45331) [ Link ] (1 responses) Perhaps you're right about magit vs. vc, but is jj so different from git that we need to have a magit for magit? Universality Posted Mar 5, 2026 14:48 UTC (Thu) by nix (subscriber, #2304) [ Link ] Probably not, but again it might be quite difficult to make magit selectively ignore the staging area in its UI, etc -- after all, one rationale for having a magit in the first place was that it didn't need piles of complexity and compromises induced by needing to abstract over differences between multiple version-control systems. We already have one of those -- vc -- and as a direct result it's rather anaemic. Universality Posted Mar 5, 2026 16:31 UTC (Thu) by spacefrogg (subscriber, #119608) [ Link ] There is a vc-jj package. Git CLI extension via aliases Posted Mar 8, 2026 15:01 UTC (Sun) by jo42 (subscriber, #59640) [ Link ] (1 responses) For me, the CLI is the preferred way to interact with git, because it's very extensible with aliases. These aliases proved to be valuable for me: [alias] r = rebase --interactive --rebase-merges rsh = rebase --show-current-patch reword = !"set -efuC; f() { for i; do git ci --fixup=reword:\"$i\"; done; }; f" fixup-last = !"set -efuC; \ l=$(git diff -U0 -- "$1" |sed '/^@@/!d; s/^@@ *-//; s/[, ].*//; s/^0$/1/; q'); \ test -n "$l" || f=$1; \ git ci --fixup=$(\ git log -1 --no-patch --format=%H ${l:+-L$l,+1:$1} @{u}.. -- ${f:-} \ ) --" fixup-last-all = !"set -efuC; git status --porcelain |sed '/^[DMR]\\|^.M/!d' |while read -r mode file _ f2; do git fixup-last "$file" ${f2:+"$f2"}; done" lr = !"set -f; test $# -eq 0 || { b=$1; shift; }; exec git -c diff.noPrefix=true log --reverse \"@{u}..${b:+@^{/^Merge.* '$b\\}^2}\" \"$@\" # ignore appended args" lro = !"set -f; test $# -eq 0 || { b=$1; shift; }; exec git lr \"${b:-}\" --oneline \"$@\" # ignore appended args" And I'm using magit's rebase mode and added functions like (defun git-rebase-push-label () "Insert a `git push` for the label at point" (interactive) (save-excursion (beginning-of-line) (when (looking-at-p "label ") (let ((inhibit-read-only t)) (insert "exec git push github --force-with-lease HEAD:refs/heads/" (let ((lbl (buffer-substring (+ 6 (point)) (pos-eol)))) (if (string-prefix-p "github-" lbl) (substring lbl 7) (concat "jo-" lbl))) "\n" ))) )) Git CLI extension via aliases Posted Mar 8, 2026 22:29 UTC (Sun) by riking (subscriber, #95706) [ Link ] I'm pretty sure that 'fixup-last-all' is exactly 'jj absorb' from the other comment chain here! It's unclear what 'git ci' is but your rebase aliases are also rolled into normal operation of jj. Copyright © 2026, Eklektix, Inc. This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license Comments and public postings are copyrighted by their creators. Linux is a registered trademark of Linus Torvalds