Using Emacs and Git with Magit 2.1

Did you know...? LWN.net is a subscriber-supported publication; we rely on subscribers to keep the entire operation going. Please help out by buying a subscription and keeping LWN on the net.

There is more than one way to mesh a Git workflow with the Emacs editor. As we saw in April, one option is the VC module for Emacs, which provides a common wrapper around many version-control systems. Some Emacs users, however, feel that the one-size-fits-all approach of VC can shortchange the version-control system in question—particularly when the system is Git. As a result, the dedicated Git-integration tool Magit has a loyal following in Emacs circles. The project is preparing to release version 2.1, a major update, so I decided to take a look.

The Magit team is scheduled to push out version 2.1 on "July 1th" (although, as of press time, the release has not yet occurred). The update will mark a major milestone; the previous release series was the 1.4 branch. Maintainer Jonas Bernoulli noted in the release schedule that using a .1 minor number may be confusing to some but that it is the same approach taken by Emacs (the next major release of which will be version 25.1).

Stable Magit releases can be downloaded and installed within Emacs using the built-in package system, if one adds the MELPA repository first. MELPA is a third-party repository that packages many more add-ons than the official, default package repository ELPA. Nevertheless, it has earned a reputation for stability and reliability over the years, and poses little risk of destabilizing one's system.

The 2.1 release of Magit should make its way to MELPA in relatively short order; in the meantime, it can be downloaded and installed from GitHub (using the "next" branch). The only significant dependency is on dash.el, which is also available through MELPA.

Welcome to the Magit kingdom

For those (like myself) who are new to Magit, the most significant feature of the package is that it provides an almost toolbar-like interface to Git's major features—coupled with a smart "dashboard" for tracking and exploring the status of one's code. This dashboard is an interactive Emacs buffer that, by default, takes up a small portion of the Emacs window. When the user opens a file in a Git repository, the buffer shows the current head and upstream branch, with the most recent commit listed for each.

As the user edits files, the status buffer updates to track staged and unstaged changes, untracked files, stashes, and more. Staging a change is as simple as moving the cursor over it in the "unstaged" list and hitting " s " (and unstaging a change can be done with " u "). Although by default, the staged and unstaged sections list files, hitting " TAB " opens a diff of the file, with insertions and deletions highlighted in green and pink, respectively. In this mode, the " s " and " u " keys can be used to stage or unstage individual hunks.

Typing " c " performs a commit, which triggers a small pop-up buffer to accept the user's commit message. A " p " initiates a push, while " l " opens up the current branch's log. The log is another interactive buffer: the user can navigate back to an earlier commit within the log and select it to perform any of several actions—such as rebasing or squashing. Typing " b " brings up the branch buffer, from which the user can create, delete, or checkout branches.

The majority of the time, users are likely to stick to this relatively small subset of Git's functionality, but Magit also provides interactive tools for bisecting bugs, displaying a blame , and performing more complex repository manipulations (like merging or cherry-picking).

There might be a lot to say just about the benefits of Magit's context-aware pop-ups. No matter what the situation, typing " h " pops up a cheat sheet of the available commands. That can be helpful for anyone who has yet to develop an instinctive grasp of all of Git's options. Similarly, the interactive commands (such as commit) pop up a buffer containing a list of the available options, each of which can be clicked with the mouse as if it was a button. But that buffer accepts keyboard input, too, which allows those users who prefer to work fast to simply keep typing.

But the more subtle benefits of Magit are how smoothly it integrates Git functionality with the normal Emacs editing environment. All of the normal Emacs navigation and editing commands work as they usually do, and a great deal of work has clearly gone into binding Git actions to Emacs hooks that can be called by Magit in the background as one works.

That is to say, Magit is far more than a series of pop-ups allowing one to enter an external Git command. Rather, Magit does "the right thing" behind the scenes as one works. To provide one simple example, users can highlight multiple files in the status buffer and stage or unstage them all at once. This is what an Emacs user would expect, since selecting text between the point and the mark works this way for general editing. If Magit simply displayed a list of files, without tracking the point and mark, such a feature would likely not work.

The 2.1 release

According to the release notes for 2.1, much of the work that went into this new Magit release was behind the scenes: implementing performance improvements and increasing consistency within the internal abstractions. Nevertheless, users who are familiar with Magit 1.4 will find a lot to like in the new release, too.

The biggest change is the addition of a new library named with-editor.el. This is a library that allows Git to call an Emacs client process whenever it needs an editor. Magit 2.1 uses this functionality internally for interacting with Git during rebases and commits, but it has another benefit, too. It allows Magit to connect to remote machines using the Emacs TRAMP (Transparent Remote (file) Access, Multiple Protocol) package.

Magit 2.1 also features a completely rewritten blame tool. The new implementation is interactive: the user can jump to the next (or previous) chunk belonging to the same commit, see the revision history for the chunk at the cursor point, and much more. For experienced Git users, there is now a preference to disable Magit's confirmation questions for "dangerous" commands. There are also new functions to insert cherry-picked commits, preview merges, and locate the commits that cause a merge conflict.

Several existing Magit features have had important bug fixes in this release. For example, in version 1.4.x, it was possible to create a snapshot or stash of the current state, including both staged and unstaged changes, but it was not possible to stash or snapshot just the staged changes. Now that limitation has been removed. Similarly, there had been some inconsistencies in earlier releases, wherein not every " git apply " variant (i.e., stage, unstage, discard, reverse, and "regular apply") would work on all of the possible content types (a single file, multiple files, hunks, etc.). Now all of the " apply " functions behave consistently.

The under-the-hood changes to Magit 2.1 pave the way for more substantial improvements in subsequent releases. A significant number of functions have been renamed so that they group into sensible categories by function-name prefix. Several utility libraries have been reorganized or combined, and a few removed in favor of existing Emacs libraries like dash.el.

The upshot of all of this refactoring work is that Bernoulli says he is now gearing up to work on some long-requested new features, like integration with code-hosting platforms and code-review utilities. He hopes to launch a fundraising drive to finance further work.

For someone (like myself) who uses Emacs yet rarely pushes Git to its limits, Magit definitely offers its advantages. It is certainly superior to jumping over to a terminal emulator and stepping through a series of Git commands. Users with more demanding Git workflows will probably find Magit 2.1 more to their liking (if they found the 1.4 series limiting), and it sounds like there is quite a bit more work still to come from the project.

