6

I know that I can use git commit --amend --file=path-to-my-new-message but this will amend staged changes, too. Of course, I could stash and later apply&drop the stash, but is there a quicker solution to change the HEAD commit message without committing the staged changes (and user interaction)?

Mot
  • 24,166
  • 22
  • 78
  • 117
  • This is a good question, and I bet there's a way to do it, but since it's such an infrequent operation I'm guessing I'd never remember the command line parameters to do it. Stash/amend/pop is probably a lot more practical. – Dan Breen Dec 27 '11 at 16:22

3 Answers3

7

You can write a new commit message to a file (say msg.txt) and use git commit-tree, e.g.

new_head=$(git commit-tree HEAD^{tree} -p HEAD^ <msg.txt)

git reset --soft $new_head

This assumes that the commit you are amending has one parent, if not you need to supply further -p HEAD^2 -p HEAD^3 ....

It's a bit ugly and low level. You might find it easier to stash your changes and use a straight "amend".

git stash
git commit --amend
git stash pop --index

As @Jefromi suggests, you could also use a temporary index file for the amend operation, e.g.

GIT_INDEX_FILE=.git/tmpidx git reset
GIT_INDEX_FILE=.git/tmpidx git commit --amend
rm .git/tmpidx
CB Bailey
  • 648,528
  • 94
  • 608
  • 638
  • You could also kludge around with GIT_INDEX_FILE, I bet! But this seems cleaner to me. – Cascabel Dec 27 '11 at 16:57
  • Instead of HEAD^, HEAD^2, ... can I use the SHA IDs of the parent commits of the existing HEAD commit? – Mot Dec 27 '11 at 19:26
  • @Mike L.: Well, yes but why would you? `HEAD^n` is going to be shorter to type and you aren't going to have to look it up. – CB Bailey Dec 27 '11 at 21:22
  • I have to look it up - at least to count the heads. – Mot Dec 28 '11 at 08:12
  • @Jefromi: Actually, I like your GIT_INDEX_FILE solution, it seems quite clean. – CB Bailey Dec 28 '11 at 15:11
  • @MikeL.: OK, but I suspect that 95% of the time it'll be a commit with one parent and you'll know this and 99% of the rest of the time it'll be a simple 2 parent merge. – CB Bailey Dec 28 '11 at 15:15
  • @MikeL: You could do it all at once: `git reset --soft $(git commit-tree $(git log -n 1 --pretty=%P | sed 's/\(^\| \)/&-p /g') < msg.txt)` (The %P format placeholder is expanded to the SHA1s of the parents, and git log by default starts from HEAD, giving you what you need.) – Cascabel Dec 28 '11 at 15:15
  • @Jefromi: You need a `-p` before each parent, though. – CB Bailey Dec 28 '11 at 15:17
  • @Charles: Oops, my bad. I'll fix it. (If you don't want to mess with stuff like that, I agree that you don't need to look up SHA1s - the commit message should be plenty to distinguish between simple commit, normal merge, and octopus merges - the default octopus merge message lists the branches in the subject just like the normal merge one does.) – Cascabel Dec 28 '11 at 15:18
2

According to the man page git commit --amend --only without any paths specified should do the job, however this doesn't work for me. As a work-around you may temporarily add a file and remove it again, amending two times:

touch tmp
git add tmp
git commit --amend -m "new message" tmp
git rm tmp
git commit --amend -m "new message" tmp
mstrap
  • 15,236
  • 6
  • 50
  • 77
0

You can git rebase -i HEAD^ and then change pick to reword in the editor opened by git-rebase. After this you will be prompted for a new commit message.

ThiefMaster
  • 285,213
  • 77
  • 557
  • 610
  • Interactive rebase is no option for me, because the command has to be run without user interaction. – Mot Dec 27 '11 at 19:27