Skip to main content

6.5.2 Editing Commit Messages

After initiating a commit as described in the previous section, two new buffers appear. One shows the changes that are about to be committed, while the other is used to write the message.

Commit messages are edited in an edit session - in the background git is waiting for the editor, in our case emacsclient, to save the commit message in a file (in most cases .git/COMMIT_EDITMSG) and then return. If the editor returns with a non-zero exit status then git does not create the commit. So the most important commands are those for finishing and aborting the commit.

C-c C-c     (with-editor-finish)

Finish the current editing session by returning with exit code 0. Git then creates the commit using the message it finds in the file.

C-c C-k     (with-editor-cancel)

Cancel the current editing session by returning with exit code 1. Git then cancels the commit, but leaves the file untouched.

In addition to being used by git commit, messages may also be stored in a ring that persists until Emacs is closed. By default the message is stored at the beginning and the end of an edit session (regardless of whether the session is finished successfully or was canceled). It is sometimes useful to bring back messages from that ring.

C-c M-s     (git-commit-save-message)

Save the current buffer content to the commit message ring.

M-p     (git-commit-prev-message)

Cycle backward through the commit message ring, after saving the current message to the ring. With a numeric prefix ARG, go back ARG comments.

M-n     (git-commit-next-message)

Cycle forward through the commit message ring, after saving the current message to the ring. With a numeric prefix ARG, go back ARG comments.

By default the diff for the changes that are about to be committed are automatically shown when invoking the commit. To prevent that, remove magit-commit-diff from server-switch-hook.

When amending to an existing commit it may be useful to show either the changes that are about to be added to that commit or to show those changes alongside those that have already been committed.

C-c C-d     (magit-diff-while-committing)

While committing, show the changes that are about to be committed. While amending, invoking the command again toggles between showing just the new changes or all the changes that will be committed.

Using the Revision Stack:  
Commit Pseudo Headers:  
Commit Mode and Hooks:  
Commit Message Conventions:  

Using the Revision Stack

C-c C-w     (magit-pop-revision-stack)

This command inserts a representation of a revision into the current buffer. It can be used inside buffers used to write commit messages but also in other buffers such as buffers used to edit emails or ChangeLog files.

By default this command pops the revision which was last added to the magit-revision-stack and inserts it into the current buffer according to magit-pop-revision-stack-format. Revisions can be put on the stack using magit-copy-section-value and magit-copy-buffer-revision.

If the stack is empty or with a prefix argument it instead reads a revision in the minibuffer. By using the minibuffer history this allows selecting an item which was popped earlier or to insert an arbitrary reference or revision without first pushing it onto the stack.

When reading the revision from the minibuffer, then it might not be possible to guess the correct repository. When this command is called inside a repository (e.g. while composing a commit message), then that repository is used. Otherwise (e.g. while composing an email) then the repository recorded for the top element of the stack is used (even though we insert another revision). If not called inside a repository and with an empty stack, or with two prefix arguments, then read the repository in the minibuffer too.

user option magit-pop-revision-stack-format

This option controls how the command magit-pop-revision-stack inserts a revision into the current buffer.

The entries on the stack have the format (HASH TOPLEVEL) and this option has the format (POINT-FORMAT EOB-FORMAT INDEX-REGEXP), all of which may be nil or a string (though either one of EOB-FORMAT or POINT-FORMAT should be a string, and if INDEX-REGEXP is non-nil, then the two formats should be too).

First INDEX-REGEXP is used to find the previously inserted entry, by searching backward from point. The first submatch must match the index number. That number is incremented by one, and becomes the index number of the entry to be inserted. If you don’t want to number the inserted revisions, then use nil for INDEX-REGEXP.

If INDEX-REGEXP is non-nil then both POINT-FORMAT and EOB-FORMAT should contain \"%N\", which is replaced with the number that was determined in the previous step.

Both formats, if non-nil and after removing %N, are then expanded using git show --format=FORMAT ... inside TOPLEVEL.

The expansion of POINT-FORMAT is inserted at point, and the expansion of EOB-FORMAT is inserted at the end of the buffer (if the buffer ends with a comment, then it is inserted right before that).

Commit Pseudo Headers

Some projects use pseudo headers in commit messages. Magit colorizes such headers and provides some commands to insert such headers.

user option git-commit-known-pseudo-headers

A list of Git pseudo headers to be highlighted.

C-c C-i     (git-commit-insert-pseudo-header)

Insert a commit message pseudo header.

C-c C-a     (git-commit-ack)

Insert a header acknowledging that you have looked at the commit.

C-c C-r     (git-commit-review)

Insert a header acknowledging that you have reviewed the commit.

C-c C-s     (git-commit-signoff)

Insert a header to sign off the commit.

C-c C-t     (git-commit-test)

Insert a header acknowledging that you have tested the commit.

C-c C-o     (git-commit-cc)

Insert a header mentioning someone who might be interested.

C-c C-p     (git-commit-reported)

Insert a header mentioning the person who reported the issue being fixed by the commit.

C-c M-i     (git-commit-suggested)

Insert a header mentioning the person who suggested the change.

Commit Mode and Hooks

git-commit-mode is a minor mode that is only used to establish certain key bindings. This makes it possible to use an arbitrary major mode in buffers used to edit commit messages. It is even possible to use different major modes in different repositories, which is useful when different projects impose different commit message conventions.

user option git-commit-major-mode

The value of this option is the major mode used to edit Git commit messages.

Because git-commit-mode is a minor mode, we don’t use its mode hook to setup the buffer, except for the key bindings. All other setup happens in the function git-commit-setup, which among other things runs the hook git-commit-setup-hook.

user option git-commit-setup-hook

Hook run at the end of git-commit-setup.

The following functions are suitable for this hook:

function git-commit-save-message

Save the current buffer content to the commit message ring.

function git-commit-setup-changelog-support

After this function is called, ChangeLog entries are treated as paragraphs.

function git-commit-turn-on-auto-fill

Turn on auto-fill-mode and set fill-column to the value of git-commit-fill-column.

function git-commit-turn-on-flyspell

Turn on Flyspell mode. Also prevent comments from being checked and finally check current non-comment text.

function git-commit-propertize-diff

Propertize the diff shown inside the commit message buffer. Git inserts such diffs into the commit message template when the --verbose argument is used. magit-commit by default does not offer that argument because the diff that is shown in a separate buffer is more useful. But some users disagree, which is why this function exists.

function bug-reference-mode

Hyperlink bug references in the buffer.

function with-editor-usage-message

Show usage information in the echo area.

user option git-commit-setup-hook

Hook run after the user finished writing a commit message.

This hook is only run after pressing C-c C-c in a buffer used to edit a commit message. If a commit is created without the user typing a message into a buffer, then this hook is not run.

This hook is not run until the new commit has been created. If doing so takes Git longer than one second, then this hook isn’t run at all. For certain commands such as magit-rebase-continue this hook is never run because doing so would lead to a race condition.

This hook is only run if magit is available.

Also see magit-post-commit-hook.

Commit Message Conventions

Git-Commit highlights certain violations of commonly accepted commit message conventions. Certain violations even cause Git-Commit to ask you to confirm that you really want to do that. This nagging can of course be turned off, but the result of doing that usually is that instead of some code it’s now the human who is reviewing your commits who has to waste some time telling you to fix your commits.

user option git-commit-summary-max-length

The intended maximal length of the summary line of commit messages. Characters beyond this column are colorized to indicate that this preference has been violated.

user option git-commit-fill-column

Column beyond which automatic line-wrapping should happen in commit message buffers.

user option git-commit-finish-query-functions

List of functions called to query before performing commit.

The commit message buffer is current while the functions are called. If any of them returns nil, then the commit is not performed and the buffer is not killed. The user should then fix the issue and try again.

The functions are called with one argument. If it is non-nil then that indicates that the user used a prefix argument to force finishing the session despite issues. Functions should usually honor this wish and return non-nil.

By default the only member is git-commit-check-style-conventions.

function git-commit-check-style-conventions

This function checks for violations of certain basic style conventions. For each violation it asks users if they want to proceed anyway.

user option git-commit-style-convention-checks

This option controls what conventions the function by the same name tries to enforce. The value is a list of self-explanatory symbols identifying certain conventions; non-empty-second-line and overlong-summary-line.