Magit Introduction on Spacemacs

Here is a quick tutorial on how to do a bunch of different. We will be talking about how to commit changes, use diff to look at changes between branches, how to checkout new and existing branches, and even how to speed it up so it isn’t so slow.

What is Magit

From the Magit repository:

Magit is an interface to the version control system Git, implemented as an Emacs package.

Basically, Magit is a way to use git without having to leave Spacemacs. It handles all of the git workflows that I use every day and it has me forgetting how to use the commands under the hood (not really but it is an amazing tool).

If you are using Spacemacs and git, you are in luck.

How to Pronounce Magit

There is an issue on GitHub that asks this question. The conclusion was that you can pronounce Magit in two different ways:

"MA-jit" (like 'magic' with a 't' at the end) "MAH-git" ('maggot')

Getting Started

To add Magit to Spacemacs:

  1. Open up your ~/.Spacemacs dotfile using SPC f e d
  2. Add git to your dotSpacemacs-configuration-layers
  3. Reload your config with SPC f e R
dotSpacemacs-configuration-layers
'( 
  ;; All your other layers like ruby, elixir, javascript
  git
)

It’s that easy. Now you are ready to get to work with Magit.

Magit Status

Now that you have everything install it is time to open the Magit status window. You can open the status window in any window just make sure that you are in a git repository. You can open the window by using the following command:

SPC g s

As with everything in Spacemacs, this is mnemonic and very easy to remember. All of our git commands are going to be slotted under g for git. If you type SPC g, you can see all the options that you have at your disposal.

When you first open the status window, you will notice that you are given a lot of useful information about the git state of the world. You will notice which branch you are currently on, the HEAD and tag that you are currently on. It is an easy way to see the staged/unstaged changes, stashes, and even recent commits. All of this just by pressing a few keystrokes.

The status window will be your central hub for a lot of different git actions. To see all the different commands that you can perform from here, you can pull up a handy list by typing ?. What I love about Spacemacs is how easy it is to find new functionality. Everything you do in the Spacemacs ecosystem has a helper menu for what each key does while you are typing. Magit is no different.

Staging changes

The first thing you will likely want to do from the Magit status window is to make a commit but we can’t commit something without staging a file. I started my engineering career using subversion and staging files wasn’t necessary. I’m lucky the industry standard switched to git.

There are a few different ways to stage a file. I am going to go through all of the ones that I use. There are probably more ways to do this. As the old saying goes, there are multiple ways to stage a change.

Stage a single files - You can stage an individual file by moving your cursor to the individual file and hitting s for stage. If you would like to unstage that change, just type u.

Stage all the changed files - Very similar before but you can stage all the changed files by moving your cursor to the Unstaged changes(2) and typing s.

Staging hunks - Say you have made a lot of changes but you haven’t been consistent with committing your changes. Happens to the best of us. Sometimes you are too in the zone to break for a commit (Stick in there though. Magit will change that for you.) You can mold your git commit history into a methodical work of art and here is how:

  • SPC d u - This is to see the diff for unstaged changes. More on this in a few sections.
  • Shift v - This puts you in visual line mode. You an also use Ctr v for visual mode.
  • Highlight the lines that you want to stage
  • s to stage those changes

Stashing changes

Another important aspect of git that Magit handles well is stashing. I stash a lot. Sometimes I am working on the wrong branch and I need to move my changes. Sometimes what I was trying didn’t work and I just want a clean slate without creating a new branch. All of the stash actions are available from the Magit status window under the key z.

Stash Changes - Say you have made some changes that you would like to stash. To do this you can type z z from the Magit status window. Magit will then prompt you to type a name of the stash that you are creating. This makes it helpful to remember what you were working on.

Applying the Stashed Changes without Losing the Stash - If you would like to git stash apply your changes, you can access that with z a. This is a nice option if you don’t want to lose the history of your stash.

Popping the Staged Changes - This is the same as apply but you remove the stash as well. Use z p to pop a stash.

Deleting a Stash - Sometimes you get a little carried away with all the stashes. You have stashes from two years ago on a class that has been removed from your repo. You have stashes from three api versions ago that you need to just let go. The keys z x will help you with that.

Creating Commits

After you have staged some changes that you want to commit (or stashed some that you did not), you are ready to make your first commit using Magit. To create a commit using Magit, you need to type c c. This will bring up your commit message prompt that you have seen before in other git flows. The nice part is that it brings it up directly in Spacemacs so no need to break your flow. After you use the vim (or emacs) keybindings to type up your commit message, you have to hit Ctr-c Ctr-c to create the commit.

All of the commit actions are under c for commit and are available only on the Magit status window. You have a few other options that are available to you:

Amend a commit - c a

Reword a commit - c w

Log of commits

It is also really helpful to see a log of commits. On the status window, you can see a small list of the last ten commits. This is helpful to see what has happened recently but doesn’t give you a true look at the history.

You can see a more detailed log by using l l on the Magit status window complete with author, commit date, and even a simple view of the branching and merging.

Pushing Commits to origin

Now that you have created a few commits and have things moving smoothly, you probably want to push this up to origin so that others can see your hard work. There are a few different push actions you can take and they all start with p. Magit allows you to push the remote repository of your choosing. Pushing to remote -p pThis pushes to the remote that you have set up. Normally this is the same asgit push origin.

Pushing upstream - p u If you would like to set up another remote to be an upstream repository, this is an easy way to push your commits up to that branch.

Pushing elsewhere - p e I use this the most when pushing to something like heroku where you have multiple different remotes for development and staging environments.

Force Push - p -f p I use this command quite a bit. Whenever I am working on a feature branch and want to update that commit, I will use force push. I like to keep my pull requests to a single commit and amend the commit as I continue to develop.

Fetching and pulling changes

Another important part of a git workflow is pulling down the code that others have written. Within Magit status window, you can fetch and pull from remote, upstream, and really anywhere.

Fetching from remote - f p This command is your basic git fetch origin.

Pulling from remote - P p This command is very similar to push but just remember that to pull down the changes to use a captial P.

Branching

All the branching functionality is packed under b for branching.

Creating a new branch - b s This creates a spin-off branch from the current branch. It is helpful if you are developing on master and then realized that you needed to branch off.

Switching branches - b b This pops up a helm window with all the different branches that you can checkout.

Branch and Checkout - b c Want to checkout a different branch from origin, this command is for you.

Magithub Integration

Magithub is an integration with github that allows you to create pull requests, create issues, and a lot more. My current workflow is to create a pull request for every feature and bug. Magithub significantly speeds up the time for me to create a pull request and review other pull requests. My goal is to never have to leave emacs and Magithub helps with that. I rarely find myself visiting github because all the functionality I need is baked right into my editor. For more information about Magithub, check out Magithub’s github.

Speeding up

One of the downsides about using the current version of Magit is the speed that it takes to start. Luckily the start up cost is only paid once per session and after you open the first Magit status window, you won’t have to worry about the load times. There are a few different ways to speed this up however.

The development branch of Spacemacs is currently much faster than what exists right now. You can go to your ~/.emacs.d and change your branch to development to get a sneak preview of all the changes that are coming up in the next release. With the faster environment, I will also warn you that this means development and your environment can be unstable. If you don’t want the headache of dealing with fixing a few small issues every once in a while, I’d stick to the master branch. If you want the speed and new features, life on the development branch can be very rewarding.

Another way to increase the speed is to start up Spacemacs in daemon mode when you log into your computer. Here is a link to set that up in a few different environments. I highly recommend this as you will never notice that Spacemacs is lagging because it does all the work for you in the background.

Conclusion

Hopefully I have convinced you to give Magit a try. It is an awesome tool for a developer that is using git. My goal with switching from vim to Spacemacs was to reduce the number of tools that I needed to use. Magit helps with everything I need to do in git. I never find myself resorting the the command line just to checkout a branch.