3

We prefix all git commits with ticket numbers. Sometimes I need to batch rename the ticket number for a range of commits. For example, I want to rename change all JIRA-1111 occurrences in commit messages to JIRA-2222 in all commits from between origin/master and master. So this git history:

* JIRA-1111 commit message 5 (master)
* JIRA-1111 commit message 4
* JIRA-42   commit message 3
* JIRA-2222 commit message 2
* JIRA-1111 commit message 1 (origin/master)

would be changed to:

* JIRA-2222 commit message 5 (master) # <- renamed from 1111 to 2222
* JIRA-2222 commit message 4          # <- renamed from 1111 to 2222
* JIRA-42   commit message 3
* JIRA-2222 commit message 2
* JIRA-1111 commit message 1 (origin/master)

I know how to change the commit messages for individual commits using either --amend, or interactive rebase and editing each commit message manually. But my question is:

How can I modify the commit message for a range of commits in batch without manually editing each commit message?


(If you wonder why I need this: The commit dialog in IntelliJ IDEA shows the last commit message which contains the ticket number I'm working on. But sometimes (if not all files are committed), it doesn't remember the last message and shows an older one. When this older message contains a different ticket number, we often end up committing under the wrong ticket number.)

Mifeet
  • 12,949
  • 5
  • 60
  • 108
  • Any reason why one issue has multiple commits? Why are you not squashing your commits? – iveqy Mar 13 '16 at 14:07
  • 1
    Because it would make the code review difficult. Is is easier to understand the changes in small steps than in a single large squashed commit. – Mifeet Mar 13 '16 at 14:08
  • Note that all subsequent commits get new hashes when you edit the message in a previous commit (which of course causes that commit to have a new hash). Other than that, it sounds like the IDE you're using is actively harmful, rather than helpful. IDEs always seem to do this, which is why I avoid them. :-) – torek Mar 13 '16 at 21:47
  • Related: [What's the fastest way to edit hundreds of Git commit messages?](https://stackoverflow.com/q/14332551/711006) – Melebius Apr 24 '23 at 12:14

1 Answers1

4

Running git rebase -i opens an editor where the commit messages can be changed. Git documentation states that:

By default, Git uses whatever you’ve set as your default text editor ($VISUAL or $EDITOR) or else falls back to the vi editor to create and edit your commit and tag messages. To change that default to something else, you can use the core.editor setting

Replacing the editor with, e.g., a sed command that changes the commit messages will do the trick:

FROM=JIRA-1111
TO=JIRA-2222
export EDITOR="sed -e 's/^${FROM}/${TO}/' -e 's/^pick /reword /' -i ''"

The first -e option changes the commit messages appropriately, the second -e changes the pick keyword to reword, and -i forces sed to edit the file in place without a backup copy.

Once the EDITOR variable is exported, run git rebase for the required range of commits:

git rebase -i origin/master master

Edit: as suggested by @torek, the export EDITOR=... part can be changed to

export GIT_SEQUENCE_EDITOR="sed -e 's/^pick /reword /' -i ''"
export EDITOR="sed -e 's/^${FROM}/${TO}/' -i ''"
Mifeet
  • 12,949
  • 5
  • 60
  • 108
  • 2
    It would be a bit safer to use two separate editor scripts (both can use sed of course), one in `$GIT_SEQUENCE_EDITOR` to edit the pick commands and the other in `$GIT_EDITOR` or `$EDITOR` or `$VISUAL` to edit the messages. – torek Mar 13 '16 at 21:45
  • 3
    The named export commands are not working correctly. The `-i ''` switch results in Git error messages `sed: can't read : No such file or directory` `Could not execute editor`. Moreover, if one wants to change only the first line of a commit message (e. g. for adding a commit message prefix instead of only changing it), the `sed` expression needs to be extended to `1 s/.../.../`. The working export commands are (omitted optional `-e`): `export GIT_SEQUENCE_EDITOR="sed 's/^pick /reword /' -i"` and `export GIT_EDITOR="sed '1 s/^${FROM}/${TO}/' -i"`. – Michael Fiedler Oct 03 '16 at 12:51
  • @MichaelFiedler, the `...sed 1...` doesnt work for me (in git bash on win7) – elonderin Jul 23 '18 at 04:53