How to Include Diff into Git Commit Message

De facto, git is a standard version control system now. Not surprisingly that I use it for my projects. Working on a project, I often face with a situation when I have made a number of changes, and I need to describe them in a commit message. Of course, I try following the line when every change results in a new commit, however, on practice, sometime I face with the situation when I need to describe a number of changes in one commit message. If there are a number of changes (or peculiarities), mentioning all of them could be a challenge. Of course, you can open an additional terminal and do diffing, however, it would be great if this information is included in the commit message.

I searched Internet for the information how to solve this issue but I did not manage to find a good approach at first. In the beginning, I came across a solution proposing to modify git commit message template. Unfortunately, templates can be used only to include static information, therefore, I instantly abandoned it. Then, I found a method that provides the required functionality using vim and its autocmd plugin. So as I use VSCode, I looked for a similar plugin for this text editor, however, the closest one I managed to find, auto-run-command, did not fit my needs.

Luckily, I remembered about git hooks that I had used in one of my projects. I read about them, and found that one of them, prepare-commit-msg, perfectly fits my requirements:

The prepare-commit-msg hook is run before the commit message editor is fired up but after the default message is created. It lets you edit the default message before the commit author sees it.

So, let me show on a test repository how to use this hook to include a list of made changes into a commit message:

  1. Create a new test repository:

    $ git init git_test
    Initialized empty git repository in ~/tmp/git_test/.git/
    
  2. Go to git_test/.git/hooks and copy prepare-commit-msg.sample file:

    $ cd git_test/.git/hooks
    $ cp prepare-commit-msg.sample prepare-commit-msg
    
  3. Modify prepare-commit-msg with the following content (you can find the script in the accompanying Github directory):

    #!/bin/bash
    
    COMMIT_MSG_FILE=$1
    COMMIT_SOURCE=$2
    SHA1=$3
    
    RESULT="# Differences to be committed:"
    while IFS= read -r line
    do
      RESULT+="$IFS#	$line"
    done <<< $(git diff --staged)
    
    echo "$RESULT" >> $COMMIT_MSG_FILE
    

Now, when you try to commit something to this repository, the tail of the commit message will contain information about all the changes you have done in the staged files, i.e., it will contain commented output of the git diff --staged command. Note that every line of the diff is commented, thus they will not appear in the final commit message.

The advantage of this solution is that it is editor independent: every editor can be used to show the changes and to modify commit messages. Moreover, you do not need to install any additional plugins into your system.

If you need to include some dynamic information based on your commit message, for instance, substitute some variables with actual content, you can do this modifying the commit-msg hook. For instance, this hook can be used to expand automatically the message with the list of modified files.

Related