Stacked Git logo

Stacked Git

Emacs stgit-mode Guide

StGit comes with an Emacs mode, stgit-mode, supporting Emacs versions 22 and later.

To start using it, add the stgit/contrib directory to your Emacs load-path and run (require 'stgit). For example, you can add the following to your .emacs file:

(add-to-list 'load-path "/path/to/stgit/contrib")
(require 'stgit)

Start stgit-mode using M-x stgit and select the directory where the source code you want to use StGit on can be found. If StGit has not been initialized in this directory yet, you will need to run M-x stgit-init before you continue.

The stgit-mode buffer (usually named *stgit*) has the following layout:

Branch: name-of-branch

+ The first applied patch
+ Another applied patch
> The topmost patch
  Index
    <no files>
  Work Tree
    <no files>
- An unapplied patch
- Another unapplied patch
--

The above means that the active branch name is name-of-branch and it contains five patches, three of which are applied. The git index and working tree contain no (modified) files.

Basic Commands

To get help, press h. This opens a new buffer which lists all commands supported in stgit-mode. Also, if you have the menu bar enabled (toggled using M-x menu-bar-mode), a new menu entry called StGit will appear, from which you can run several StGit commands. As the menu should be self-explanatory, the rest of this tutorial will focus on available keyboard commands.

Move the point (cursor) between lines using C-p and C-n, or between patches using p and n.

You can undo and redo StGit commands using C-/ and C-c C-/, respectively.

Creating New Patches

If you want to create a new patch, first make some changes that should go into it. As you save a file which is Git-controlled, it will appear as a modification in the Work Tree section:

  Work Tree
    Modified       foo.txt

To create a new patch based on the changes in the index or, if it contains no changes, the working tree, press c. This opens a new buffer where you can enter the patch description. When you are done, press C-c C-c. Your new patch will now show up in the *stgit* buffer, and the working tree will no longer contain any modifications:

+ The topmost patch
> First line of your new description
  Index
    <no files>
  Work Tree
    <no files>

As you make additional changes in your files, and want to include them in the topmost patch, press r, which runs stg refresh. If you want to add the changes to a patch which is not topmost, move the point to the line of that patch and press C-u r.

Inspecting Patches

To see what a particular patch contains, you can move the point (cursor) to the line of that patch, and press RET (Enter). This will “expand” the patch and show which files it changes:

+ My patch
    Modified       foo.txt
    Deleted        bar.c

You can press =, which will show the diff of that patch or file in a new buffer. With a prefix argument (C-u =), the diff will not show changes in whitespace.

To visit (open) a modified file in another Emacs window, press o on that line. RET will visit it in the current window.

Changing the Patch Series

You can push and pop patches using > (pushes the topmost unapplied patch onto the stack) and < (pops the topmost applied patch off the stack).

By moving the point to a particular patch and pressing P (S-p) you either (if it already was applied) pop that patch off the stack, or (if it was unapplied) push it onto the stack.

You can move patches by first marking one or more using m. Then, move the point to where in the series you want these patches to move, and press M. Use DEL or u to remove a mark.

You can also combine (squash) two or more patches by marking them and pressing S (S-s). This will open a new buffer where you can edit the patch description of the new, combined, patch. When done, press C-c C-c, and the topmost of the marked patches will be replaced in the stack by one combined patch.

You can delete a patch by moving to its line and pressing D. If you press C-u D, the contents of the patch will be spilled to the index.

To edit the description of a patch, press e. This opens the patch description in a new buffer. Press C-c C-c when you are done editing the patch.

These operations may result in merge conflicts; more about that later.

Patch Names

By default, the patch description is shown but not the patch names. You can toggle showing the names using t n. To rename a patch, press C-c C-r.

Showing Committed Patches

Sometimes it is convenient to be able to investigate already committed patches. Toggle showing these using t h. With a prefix argument, you can set how many to show; e.g., 7 t h will show seven already committed patches.

Using the Index and Working Tree

You can move a changed file between the index and the working tree using i. This is useful if your working tree contains a number of changes and you want to create or refresh a patch using only some of the changed files. Once you have the correct set of files in the index, use c to create or r to refresh patches using only the files in the index.

If you want to revert a change in either the index or the working tree, move the point to that line and press U. If you press U on the Index or Work Tree lines, all the changes in the index or working tree will be reverted.

Branches

You can switch to another branch by pressing B. If you type the name of a branch that does not exist, you will be asked whether to create one. The new branch will be based off the current HEAD.

Use C-c C-b to rebase the current branch. It will default to rebasing to the git config setting for branch.<branch>.stgit.parentbranch.

Merge Conflicts

If an operation resulted in a merge conflict, the files with conflicts will show as Unmerged in the *stgit* buffer.

To handle the conflicts, you can undo the operation that caused the conflict using C-u C-/. Note the C-u prefix, which will tell the undo operation to continue despite the index or working tree containing changes.

If you instead want to resolve the changes, you must first edit the files with conflicts to make sure they are in the correct state. Once you have done this, press R on the line of that file, which will remove the Unmerged flag. Once all conflicts have been resolved, you can continue working as normal, for example by refreshing the patch that had the conflict.

To investigate the reason of conflicts, you can use the d b, d o, and d t commands to, respectively, show the diffs against the merge base, our branch, or their branch. d c shows a combined diff. See git-diff(1) for more information about these commands.

A more powerful tool to resolve conflicts is the Emacs smerge-mode. To start using it to resolve a conflict, press d m. It is outside the scope of this tutorial to explain how to use it, but press q to leave smerge-mode.