How do I edit an incorrect commit message in Git without including any staged modifications?

StackOverflow https://stackoverflow.com/questions/20266734

  •  06-08-2022
  •  | 
  •  

Question

If I have staged some changes, and in the process notice an error in my previous (and un-pushed) commit message, is there a way to amend the commit without folding in my staged changes?

I see various options on the man page for git-commit that perform a related function, but no combination that seems to produce exactly the desired effect:

  • --amend
  • --all (automatically stage), but no '--none'
  • --message
  • --only (only the specified paths)
  • -- <no-more-options>...

The option --only with an empty file list (which I don't know how to specify), would almost be right, but that might in any case remove changes from the last commit (which I don't want).

The naïve method is to reset and then commit --amend, but that requires repeating the staging work. Alternatively, I could commit my staged changes, and edit the no-longer-latest commit message via a rebase, but that seems a to be awkward and overkill for just editing a message.

I don't think stash save can help either, as stash does not seem able to preserve the distinction between staged and unstaged changes. (Unless it's possible to stash only what has been staged? Again, I don't see how to do that.)

This question is related to How to modify existing, unpushed commits? where there's plenty of useful information amongst the answers, but this, slightly different question is not addressed.

Any hints gratefully received; thanks.

Was it helpful?

Solution

You can do that with git-commit-tree and git-reset:

git reset --soft `git commit-tree <tree-id> -m "new message" -p HEAD^`

<tree-id> is the root tree id of HEAD. You can get it by git cat-file -p HEAD

OTHER TIPS

I think stashing should remember what was staged and what's not, maybe you need to use --no-keep-index

git stash --no-keep-index

I wanted to put this as a comment to @npcode's answer, but couldn't get the formatting right. What follows is heavily based on that answer...

Here's a finer-grained explanation, and one that allows the original commit message to be edited:

(1) $ git cat-file -p HEAD | grep "^tree\b" | awk '{print $2}'

prints the root tree id of HEAD ${tree-id}, needed in step (4)

Optionally:

(2) $ git log -1 --format="%B" > ci.txt

dumps the old commit message in ci.txt, which can then be edited. Optionally and alternatively, and entirely new commit message file could be written.

(3) $ editci.txt

Then either

(4a) $ git commit-tree ${tree-id} -F ci.txt -p HEAD^

or

(4b) $ git commit-tree ${tree-id} -m "<new message>" -p HEAD^

to create a new commit object with commit message, respectively, from a file or directly on the command line. Either of these commands prints the id ${commit-id} of the new commit, needed in step (5)

(5) $ git reset --soft ${commit-id}

to set the new commit as the current HEAD.

@npcode and @Daniel combine steps (1), (4b) and (5).

You can just continue with your work and do an interactive rebase afterwards:

git rebase -i

in the list of commits you see replace pick with reword for all commits you want to reword.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top