Tinkerers, makers, and engineers tend to obsess over their workspaces. In addition to inventing things for the rest of the world, we are continually reinventing our own environments, devising better and better ways to keep important tools close at hand so that they can be reached without even looking.
Magit is the holy grail of workspace tools, allowing Git users to handle all aspects of source control directly from within Emacs. But rather than merely lauding Magit and asking you the reader to take my recommendation at face value, I'd like to share a couple of recent events that reminded me why Magit is such a powerful tool.
Exhibit A: Adam Savage of Star Wars and Mythbusters.
I recently saw Mr. Savage give the keynote speech at the Strange Loop conference. He spent a good chunk of time describing the absurd lengths he goes to make it easier to find his stuff without interrupting his flow. His talk reminded me of my own quest as a software engineer to minimize the extent to which my tools derail my train of thought.
Why do we obsess over our tools and environment in this way? Because "context switches" are harmful to both Makers and Software Engineers.
Exhibit B: Joel Spolsky of Fog Creek.
Joel Spolsky offers us a great example of how context switching is harmful to productivity. In this oft-cited article, Mr. Spolsky describes the effects longer-term context switches, such as vacations, but the same phenomenon occurs at a smaller scale, even when switching from one application to another.
Any software project involves a large number of details that the engineer needs to bring to bear quickly, and this works best when the details are close at hand in the shortest-term area of memory. Any context switch, no matter how small, inevitably takes some mental effort; and in the course of that effort some of the little details you had in the front of your mind slip away.
To lessen the mental strain, my favorite "software toolbox hack," perhaps the equivalent of Mr. Savage's Scissor Lifts, is Magit.
The Goal: Git mastery
At MojoTech, we are very good at using Git. It's one of the things that makes me proud to work here, in fact! When a new engineer joins our team, he or she spends some serious "quality time" summiting Git's learning curve. Furthermore, to the extent that we can, we help our client organizations to do the same thing.
When everyone on a project can reliably produce a history of exclusively atomic commits, some good things happen:
- Code review becomes less time consuming and more effective.
- Bugs are more easily discovered and more easily fixed.
- Engineers get better at reading their own code and more easily spot flaws on their own.
(If you'd like to learn more about the style of Git usage we employ at MojoTech, check this out.)
Getting good at Git
If you're serious about advancing the state of your engineering craft, you need to make sure that you're able to produce this type of intelligent commit history. Your commits should be atomic. Where possible, refactors should be presented as separate, independently reviewable changes.
In order to produce an intelligible history, you'll need to interact with Git constructs at a very fine-grained level. It's not nearly good enough to add and remove whole files. You're going to need to quickly be able to move hunks (groups of nearby changed lines) and even individual lines in and out of commits that contain logically related changes.
Here's the catch: Not only do you need to be able to do this, you also need to be able to do it in a reasonable amount of time.
You have to be able to continue to finish your sprints and make your deadlines while leaving nice history behind at the same time. Transcribing line numbers from your editor to the command line over dozens of times as you contemplate your commit history is just not going to cut it.
Git itself, over time, has come out with more and more ways to streamline this process of managing detailed aspects of commit history. For our simple example of selecting individual lines and hunks to add to a forthcoming commit, to avoid manually transmitting line number, you can use Git stage -i to enter interactive mode: https://git-scm.com/book/en/v2/Git-Tools-Interactive-Staging.
Building on that, the open source community has developed many sophisticated programs over the years that make using Git even more elegant, for example, tig.
Your editor is your comfort zone
Any software engineer worth his salt will be using a sophisticated, dedicated software editor to wrangle source code. Emacs is such an editor, and if you're reading this article, chances are, there's a decent chance you're already using it!
After a certain amount of time, engineers develop deep attachments to their editors. They come to see their editors almost as an extension of their own bodies. They get so familiar with the keystrokes needed to invoke certain sequences that they do things without even thinking.
But here's the thing: If, when wanting to deal with Git, you're leaving your editor, and going to some external program, however nice, you're still interrupting your thought processes.
You're temporarily abandoning the beautiful comfort zone you've built for yourself. You're moving to a new window, with different hotkeys and different interface paradigms. If your editor is an extension of your body, you could call this an "out of body experience."
How good is Magit?
Magit is the way to reduce the size of the context switch to the point where it is barely noticeable. Whatever you're trying to do with Git:
- You will see your progress in an Emacs buffer
- All your keybindings still work
- The text is rendered and syntax-highlighted exactly the way it is when you're coding.
- You can interact with Git in some ways without even leaving the buffer you already had open. For example, you can see toggle multiple levels of blame information for the lines in any file, and it's integrated into your normal editor window for the file.
In general, I'm in awe of the care that the Magit developers have taken in making it easy to execute rather complex Git operations with relatively few, intuitively organized keystrokes.
Git commands are divided into "top-level actions," with sub-actions and modifiers to those actions, each of which can normally be applied with a single keystroke.
For example, if I find myself wanting to do a
git rebase -- onto, throwing away some of the history of my branch and applying a subset of my commits onto another branch, the sequence is simple:
- Lowercase "r" tells Magit that I want to do some sort of rebase.
- This opens a submenu allowing me to pick which sort of rebase I want to do.
- Lowercase "s" (for "Subset") steers me into
git rebase -- ontoterritory.
- Magit prompts for the "destination" of the rebase — what ref do I want to start adding my commits to? This will be an autocomplete list, and Emacs will endeavor to make the most likely choices (based on your history of Git operations) easiest to pick.
- Once a target has been chosen, Magit shows its standard "commit history chooser" for me to pick the first commit that I want to apply
That's it. With practice, I can probably do the whole thing in a few seconds, with a high degree of precision, and without really needing to think about it.
Thanks to Magit, I'm a Git power user who never has to leave my editor to do Git stuff anymore. Everything that I ever want to do with Git, I can do more quickly, and more naturally, using Magit than with the command line. This makes me very happy. If you put in the time to become a Magit master, it'll make you happy too!