Driving Git With Emacs - Pure Magic With Magit - Part One

Getting to grips with Git was not to much of a learning curve, although I found it quicker to work on the command line than using graphical tools. Using git status and git log made it easy to keep a handle on my code changes.

As I do most of my Clojure development in Emacs, it was great to discover I could drive git from Emacs using Magit. What follows is a flow through the first steps with Magit.

In part two I look at Git logs with Magit

I use Emacs Live from Sam Aaron as my Emacs configuration (Emacs 24 from Emacs for MacOSX), so the packages and key-bindings mentioned here are all available in this configuration unless otherwise stated.

Getting started

I start a new Clojure project using Leiningen, using the command line to do so. Instead of having a seperate terminal window for this, I can open up a command line shell window in Emacs

M-x eshell

I then navigate to my projects folder using `cd ~/projects/clojure and then create a new Clojure project using Leiningen, the build automation tool for Clojure.

lein new project-name

I could continue to use the terminal to manage the git repository, although once I got used to magit then using git inside Emacs seems more natural.

Using eshell, you can also easily open files using find-filefilenameand see all the files and folders usingdired folder`. So lets see what Leiningen has created for us

dired project-name

You can use the mouse or cursor to open any file listed, or navigate to sub-folders. In this case lets select the Leiningen project configuration file, project.clj.

Initialising a repository in git

Now I have a Clojure project, I can put that project under git version control

M-x magit-init

The emacs mini-buffer will prompt you for the top level folder of the files you want to version with git. If you are still in the top level project folder in the shell, magit-init will pick up the path, saving you some typing.

You will now be able to see the .git folder inside your project directory.

Git Status in Emacs

The most commonly used git command is git status - showing you what files have changes, which are staged, untracked files, pending commits and remote updates. To see the git status of your project in Emacs

M-x magit-status

Short-cut key-binding: C-x g

Keyboard shortcuts are defined in ~/emacs.d/packs/dev/bindings-pack/config/default-bindings.el

(global-set-key (kbd "C-x g") 'magit-status)

You will be prompted for the location of the git repository (the one you just created). Magit does a good job of guessing the folder assuming you already have a file open that is somewhere in a folder hierachy that has a .git folder in it.

With a newly versioned project then there will not be that much to see, except all the files not yet put under version control (untracked files).

The Local: line show the branch you are working on (master) and location of your project.

The Head: line shows you the last commit you made to your repository.

Staging changes

To version control your files you need to tell git about them. This is done by staging the files using the git add command. You can add individual files or all files that are untracked. Using magit, this is even easier.

In the magit-status buffer in Emacs, you can use the following key shortcuts to stage and unstage files

s - stage a specific untracked file highlighted by cursor (stage all untracked files when cursor over Untracked files title)

k - delete a specific untracked file highlighted by cursor (delete all untracked files when cursor over “Untracked files” title). See Delete really deletes section below.

i - add file to the project .gitignore file

u - unstage a specific staged change highlighted by cursor

C-u s - stages everything - tracked and untracked changes (Note: this failed when I tried it)

Under the hood

Using the $ key opens another buffer that shows you the command happening when you press keys in the magit-status window. Its a handy way to learn the command syntax and confirm magit is doing what you expected.

Note: All the files matching pattern in the project .gitignore or personal ~/.gitignore_global files will not be shown as untracked files.Delete really deletes

Using the k command in magit-status really deletes the local file, so be sure that is what you want. You get a prompt in the mini-buffer to confirm the delete though.

Testing this delete out, I noticed that not only was the file deleted but so was the folder that contained the file. As you can see in the dired my-project buffer, the doc folder has gone. If you delete files then this buffer may need a refresh, using g.

Committing your changes

Before you make too many changes you should commit them to your local repository. The more commits you make the smaller and easier they will be to mange.

On the command line you would run git commit -m "useful commit message", from the magit-status buffer its much easier:


This pops up another buffer for you to type in your commit message. Once you have typed your message then C-c C-c commits all the changes to your local repository. C-c C-k cancels the commit.

Now all our staged files have been added as a commit to our local repository. We can see this by looking at the Head: line in the magit-status window. We can also see that there are no changes (tracked or otherwise) shown.

Working with a remote Github repository

Assuming we have created a repository on Github it can be added as a remote source very easily

M-x magit-add-remote

You are prompted for the name you want to give the remote, origin, upstream or github are common names depending on your context. The name acts as an alias for the address of the Github repository, so keep it short but meaningful.

Now you are prompted for the Internet address of your repository. On the Github website your repository name is shown at the top of the page. Use the SSH version of the address, the one that starts git@github:....

Magit will now add the remote name and address to the project .git/config file.

You can now push your local commits up to Github using the key: P

The first time you press P the push menu appears.

Pressing P again pushes to the remote repository.

And there is more magit

There is a lot more you can do with magit, next up is Git logs with Magit.

If you are really keen you can have a look at the Magit documentation, or if you know what you want to do then the Magit cheet sheet may be more useful.

Magit not cutting the mustard ?

For situations when Magit doesn’t do everything you need, you can run raw Git commands using : (colon). This will prompt for a Git command, run it, and refresh the status buffer. The output can be viewed by typing $.

Thank you.