162

Frequently I'll have a workflow like the following:

  1. Commit changes to a group of files
  2. Commit changes to a different group of files
  3. Realize I missed some changes that belong in the first commit
  4. Curse

I can't make use of git commit --amend because it's not the most recent commit that I need to change. What's the best way to add changes to the first commit without touching the second one?

Robert Speicher
  • 15,382
  • 6
  • 40
  • 45
  • 1
    See also http://stackoverflow.com/questions/3940266/edit-the-commit-message-of-any-commit/3940887#3940887 for a scripted version. – VonC Oct 15 '10 at 09:15
  • 4
    I've created a Bash script for this exact purpose: https://github.com/colinodell/git-amend-old Once installed, you'd use it like this: `git amend-old abcd123`, where `abcd123` is the old commit you want to amend with your staged changes. Hope somebody finds it useful! – Colin O'Dell May 27 '14 at 17:56

1 Answers1

214

You can use git rebase to solve this. Run git rebase -i sha1~1 where sha1 is the commit hash of the one you want to change. Find the commit you want to change, and replace "pick" with "edit" as described in the comments of the rebase editor. When you continue from there, you can edit that commit.

Note that this will change the sha1 of that commit as well as all children -- in other words, this rewrites the history from that point forward. You can break repositories doing this, but if you haven't pushed, it's not as much of a big deal.

Daenyth
  • 35,856
  • 13
  • 85
  • 124
  • 31
    @rspeicher: Instead of 'sha1' you might also want to check 'HEAD~N', where N is the number of commits before 'HEAD' where you want to begin your rebase. – 3lectrologos Oct 13 '10 at 18:46
  • 15
    Have I misunderstood? It seems you actually have to select a commit *before* the one you want to change. If `sha1` is the hash of the commit you want to change, you'd specify `sha1^` on the rebase command. Otherwise, the commit to change doesn't appear in the list. – Rob Kennedy Nov 09 '13 at 00:12
  • 8
    At the end, when done amending the commit, one must run `git rebase --continue` to re-apply the commits that followed. – Artyom Jul 02 '14 at 12:12
  • 2
    if you have only one file with unstaged changes that you want to commit to an old commit, the easiest way I've found is to 1) copy your file to the desktop or something 2) `git stash` 3) `git rebase -i sha1^` 4) change `pick` to `edit` on the old commit you want to change 5) now that your workspace looks like it did during the old commit, replace the (old) file with the copy you made of the new file 6) `git add path/to/file` to add that file to the commit 7) `git commit --amend` 8) `git rebase --continue` to exit rebase 8) `git stash pop` – woojoo666 Sep 11 '14 at 22:23
  • 50
    Worked like a charm. `git stash; git rebase -i sha1~1; git stash apply; git commit --amend; git rebase --continue; git push --force` – snlehton May 20 '15 at 19:44
  • you may need to i.e. `git add .` before `git commit --amend` as I can see the files changed by applied stash as unstaged – ciekawy Feb 07 '17 at 16:53
  • if you want to ammend the first commit: `git rebase -i --root` will do the trick. Trying to `HEAD~N` till root throws this error: `fatal: Needed a single revision` – Sudip Bhandari Jun 11 '18 at 06:54