views:

76

answers:

2

Let's say I have 3 unpushed commits. Now I want to change the commit message of the first or second commit (changing them for the third one is simple using git commit --amend). How to do that?

+4  A: 

This is a job for the powerful git rebase -i command. Also, see the Interactive Rebasing section of the Git book.

Greg Hewgill
Maybe a stupid question, but can `git rebase -i` be used non-interactively?
mklhmnn
No, not as such. However, everything that `git rebase -i` does can (in theory) be done using other, scriptable Git commands. So it would be possible to write a script to modify a previous commit message, but I don't know whether such a thing exists yet.
Greg Hewgill
@Greg: congrats on your 15th gold badge ;) You are now a true git! (Err... git-guru, I meant) (I mean, guru about the tool name git) (I mean, you know what I mean)
VonC
@VonC: Thanks, that one kind of snuck up on me!
Greg Hewgill
+2  A: 

To rebound on the sub-question: is there a git commit --amend for a previous commit (and not just the last one), you could try something like (not tested yet):

git checkout -b tmp
git reset --hard HEAD~2
git commit -amend 
git rebase --onto tmp HEAD@{1} master

That would be like:

x---x---x---x---x
                ^
                |
               (master*) (* = current branch)

git checkout -b tmp
x---x---x---x---x
                ^
                |
               (tmp*, master) 

git reset --hard HEAD~2
x---x---x---x---x
        ^       ^
        |       |
      (tmp*) (master) 

git commit -amend 
      y (tmp*) 
     /
x---x---x---x---x
        |       ^
   (HEAD@{1})   |
          (master) 

git rebase --onto tmp HEAD@{1} master
    (tmp)
      y---x'---x' (master*) 
     /
x---x---x---x---x (only referenced in reflog)
VonC
On the `rebase --onto`, see http://stackoverflow.com/questions/1994463/how-to-cherry-pick-a-range-of-commits-and-merge-into-another-branch/1994491#1994491
VonC
why bother? rebase -i is much simpler
CharlesB
@CharlesB: I agree, `rebase -i` is simpler, but it also *interactive*. Meaning you cannot include it in a script or in an alias grouping a sequence of commands.
VonC