Git quick start guide for Emacs Developers

Emacs uses Git as its version control system.

If you are an Emacs contributor without experience using Git in particular and Distributed Version Control Systems (dVCS) in general, this document tells you how to use Git in a simple, CVS-like way.

The “workflow” described in this document allows you to:

There is a separate document, GitForEmacsDevs, that describes several slightly more complex, but also more flexible workflows that take advantage of the Git’s advanced features. Such workflows are particularly useful if you are frequently making substantial changes to Emacs. You are encouraged to use the workflows described there.

Conventions and basic info


We start by telling Git who you are. This is used for recording the author of the commits. You will need to run two commands, one to set your name among humans and the other to set your email address:

git config --global "Your Name Here"
git config --global ""

You should also run this command to turn on strict integrity checking:

git config --global transfer.fsckObjects true

(See the thread "Recommend these .gitconfig settings for git integrity." for why.)

Next, you need to clone a copy of the Emacs repository:

This will take a couple of minutes even on a fast connection; it downloads a few hundreds of megabytes of data. It could take 15 or even 30 minutes on slower connections.

Daily work

If you’re using the command-line:

(The git add command is needed only if you added new files that are not yet registered with Git.)

We recommend invoking git status and git diff to view the changes which will be committed, before invoking git commit -a.

You can also commit using VC-dir:

It is a good idea to review your commit after doing it, by means of the git show command. In particularly, make sure you got the log message right and without mistakes. This is because fixing a mistake in the last local commit is easy. (If you spot mistakes, the next section explains how to fix them.)

To push your commits to the upstream Emacs repository on Savannah, you will need to type the git push command from the shell prompt, even if you use VC, as VC doesn’t yet support a push command.

Before pushing, we recommend examining what you are about to push, because fixing mistakes before pushing is much easier (see the next section). To do that, use the command git show origin/master.. (note the 2 dots: they are important). If you only have one local commit you want to push, just git show is enough.

If you made a mistake

If you want to discard your changes to a single file, the command git checkout FILE will overwrite the named FILE with its version as of the last pull from upstream.

If you commit something by mistake, or forgot to commit a file, or want to fix a stupid typo in the commit log message, all is not lost. Be sure to catch these problems before you git push, then the error was not yet propagated upstream, and you can easily fix it.

To fix the last commit log message, use git commit --amend. To re-do the commit from scratch, use git reset HEAD^ (which undoes the commit, but leaves your local changes intact), then fix whatever needs fixing, and commit again.

If you caught your mistake only after git push, the only way to fix it is to push another commit. Try to avoid that, as log messages cannot be fixed this way.

If pushing fails

Before pushing, not just the files you are committing but all your local source files must be up to date with upstream. So if somebody else pushes to upstream between your git pull and the git push commands, your push will be rejected. If that happens, you’ll need to resync with the upstream repository:

Dealing with conflicts

The git pull command performs a merge between any local changes you have and the changes pushed by others to the upstream repository since your last pull. This merge could fail due to conflicts between your changes and changes by others in the same portions of the same files. The conflicts could be in changes you have already committed locally, or in uncommitted changes.

Conflicts in uncommitted changes

If the conflicts are in uncommitted changes, Git will say something like this:

error: Your local changes to the following files would be overwritten by merge:
Please, commit your changes or stash them before you can merge.

To fix this, commit the offending files with

and then issue git pull again. Now you may have conflicts due to local committed changes, described below.

Alternatively, you could use git stash save file1 to move the uncommitted changes out of the tree, then git pull again, and finally git stash pop to restore your uncommitted changes.

Conflicts in committed changes

For conflicts in changes committed locally, Git will say something like this:

CONFLICT (content): Merge conflict in file1
Automatic merge failed; fix conflicts and then commit the result.

The conflicts discovered by Git are marked by conflict markers similar to other VCSes. To fix this, visit the files with conflicts in Emacs. This turns on the smerge-mode which has special commands for handling conflicts. In addition, saving any file whose conflicts were completely resolved (i.e., no conflict markers remain in it) invokes the git add command on that file, which prepares the file for merging and committing. Now review all the conflict markers and resolve the conflicts by editing the relevant portions of the file.

When you are done with resolving all the conflicts in all the files, commit them, either from the vc-dir buffer or by typing git commit from the shell prompt.

Commit the entire changeset

With Git you shouldn’t commit the changed files one at a time if they belong to the same logical change. So, if you made a change in some Lisp code and also modified the documentation to be consistent with the change, please don’t do:

but instead do

or just

if you want to commit all the changed files.

This is very important because every commit creates a changeset, which is a discrete step on the history of the code base. A changeset should correspond to one well-defined purpose which is completely achieved with the corresponding commit as, for instance, “Fix bug #342” or “Implement feature Foo”.

More branches

If you work on other branches besides master, just cd into your repository and

git checkout branch_name

Other commands

Git has status, log, annotate, etc. They do pretty much what you would expect from CVS and Bazaar experience.

git revert, on the other hand, behaves a bit differently than you might expect. You may want to use git reset instead. Read the documentation for both to decide.

Use VC-Dir

VC-Dir works fine with this setup. It doesn’t support all features of more advanced Git setups, though.

That's it

You know enough to continue your Emacs hacking. Furthermore, you have the initial elements for turning your current setup into a more advanced setup once you learn enough to do so. You will not need to download all the history from upstream again.

What you have, what you are missing

You have in your disk a copy of the entire repository as of the last git pull. Hence, Git does not need to contact a server upstream for displaying logs, reverting edited files, annotating, etc. This is useful for working off-line.

Git makes possible to commit changes off-line to your local history and send them upstream in one batch. There are several options with associated trade-offs for doing this, so read GitForEmacsDevs or ask on the emacs-devel mailing list if you are interested on that possibility.

Git allows you to work as if you had your own personal CVS branch in your machine and communicate changes with other developers, not only with upstream. What’s considered “upstream” is just an agreement among the developers who participate on the same project. That is the essence of Distributed Version Control. Your current setup can be easily adapted for this, but you need to master the necessary Git concepts before embarking on that practices.

Git makes it very easy to create as many private branches as you wish.

Further reading