Search code examples
gitgit-filter-branch

How to reword any commit's message given the following message format?


I need to modify a commit's message given the commit id without changing any other commit info. However, the commit message should accept line breaks,etc similar to how it is done using the git commit command.

For example, consider the following commit

commit <id>
Author: <user-name> <user-email.com>
Date:   ...

    Hello World

I want to reword the commit message to this

    Hello World

    Text after line break1
    More text

The normal method would be to rebase interactively, and then edit the commit using git commit --amend or perform a reword operation on that commit. However, this will modify commit info such as committer email, time etc.

(Check the update section for rebase)

Filter-branch in git will allow to rewrite the commit by only changing the commit message and ids as shown in this answer.

But, how do I reword a commit with the above commit message format using filter-branch ?

Update:

Here's an example for interactive rebase.

  • Create a test repository with 2 commits
    test@ubuntu:~/temp_git$ git init
    Initialized empty Git repository in /home/test/temp_git/.git/
    test@ubuntu:~/temp_git$ touch file1
    test@ubuntu:~/temp_git$ git add .
    test@ubuntu:~/temp_git$ git -c "user.name=A" -c "user.email=a@xyz.com" commit -am "Add File1" --author="B <b@xyz.com>"
    [master (root-commit) f122a34] Add File1
     Author: B <b@xyz.com>
     1 file changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 file1
    test@ubuntu:~/temp_git$ touch file2
    test@ubuntu:~/temp_git$ git add .
    test@ubuntu:~/temp_git$ git -c "user.name=B" -c "user.email=b@xyz.com" commit -am "Add File2" --author="B <b@xyz.com>"
    [master 3b023cf] Add File2
     1 file changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 file2
    
  • Commits created above have different author and committer. The complete log is as follows :

    test@ubuntu:~/temp_git$ git log --format="fuller"
    commit 3b023cf256ae3498fbaf740329d94842143a5e4a (HEAD -> master)
    Author:     B <b@xyz.com>
    AuthorDate: Tue Oct 15 08:28:07 2019 +0530
    Commit:     B <b@xyz.com>
    CommitDate: Tue Oct 15 08:28:07 2019 +0530
    
        Add File2
    
    commit f122a341e31691f3170207c9a452ff18846fe120
    Author:     B <b@xyz.com>
    AuthorDate: Tue Oct 15 08:27:22 2019 +0530
    Commit:     A <a@xyz.com>
    CommitDate: Tue Oct 15 08:27:22 2019 +0530
    
        Add File1
    
  • Performing interactive rebase as user A and rewording the root commit

    test@ubuntu:~/temp_git$ git -c "user.name=A" -c "user.email=a@xyz.com" rebase -i --root
    [detached HEAD 228b423] Add File1 (test)
     Author: B <b@xyz.com>
     Date: Tue Oct 15 08:27:22 2019 +0530
     1 file changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 file1
    Successfully rebased and updated refs/heads/master.
    
  • Updated log with the changes in committer info

    test@ubuntu:~/temp_git$ git log --format="fuller"
    commit 0d5e6a5fed5b22fc5f8e310c6e98b1e6b8a821b8 (HEAD -> master)
    Author:     B <b@xyz.com>
    AuthorDate: Tue Oct 15 08:28:07 2019 +0530
    Commit:     A <a@xyz.com>
    CommitDate: Tue Oct 15 08:31:41 2019 +0530
    
        Add File2
    
    commit 228b423e3e511c5954823e42df51a6f6acae91cf
    Author:     B <b@xyz.com>
    AuthorDate: Tue Oct 15 08:27:22 2019 +0530
    Commit:     A <a@xyz.com>
    CommitDate: Tue Oct 15 08:31:28 2019 +0530
    
        Add File1 (test)
    

Solution

  • As answered here, the following script can be used to reword the commit using filter branch:

    #! /bin/bash
    REV=$1
    MESSAGE=$2
    FILTER="test $(echo '$GIT_COMMIT') = $(git rev-parse $REV) && echo $MESSAGE || cat"
    git filter-branch --msg-filter "$FILTER" -- --all
    

    usage: ./script_name.sh <commit-id> "commit message"

    However to add line breaks to the new commit message, I had to modify the commit message to this: "$(echo -e 'summary_line\n\nmessage\nmore_message')" as answered here. The above command adds two line breaks after the summary_line as per the general convention for commits.

    Furthermore, the script had to be modified due to the escape sequence characters as mentioned in the comments here:

    $MESSAGE in this line $(git rev-parse $REV) && echo $MESSAGE is changed to \"$MESSAGE\"

    So the final command if the script name were reword-commit.sh, (to be run inside the git repository)

    ./reword-commit.sh <commit-id> "$(echo -e 'Hello World\n\nText after line break1\nMore Text')"