Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a changed file to an older (not last) commit in Git

Tags:

git

I have changed several things over the last hour and committed them step by step, but I just realized I've forgot to add a changed file some commits ago.

The Log looks like this:

GIT TidyUpRequests u:1 d:0> git log 
commit fc6734b6351f6c36a587dba6dbd9d5efa30c09ce 
Author: David Klein <> 
Date:   Tue Apr 27 09:43:55 2010 +0200

    The Main program now tests both Webservices at once

commit 8a2c6014c2b035e37aebd310a6393a1ecb39f463 
Author: David Klein <>
Date:   Tue Apr 27 09:43:27 2010 +0200

    ISBNDBQueryHandler now uses the XPath functions from XPath.fs too

commit 06a504e277fd98d97eed4dad22dfa5933d81451f 
Author: David Klein <> 
Date:   Tue Apr 27 09:30:34 2010 +0200

    AmazonQueryHandler now uses the XPath Helper functions defined in XPath.fs

commit a0865e28be35a3011d0b6091819ec32922dd2dd8 <--- changed file should go here
Author: David Klein <> 
Date:   Tue Apr 27 09:29:53 2010 +0200

    Factored out some common XPath Operations

Any ideas?

like image 289
leen Avatar asked Apr 27 '10 07:04

leen


People also ask

How do you add a change to an old commit?

You can modify the most recent commit in the same branch by running git commit --amend. This command is convenient for adding new or updated files to the previous commit. It is also a simple way to edit or add comments to the previous commit. Use git commit --amend to modify the most recent commit.

How do you correct the typo and add the changes to the previous commit?

To change the most recent commit message, use the git commit --amend command. To change older or multiple commit messages, use git rebase -i HEAD~N .


3 Answers

Use git rebase. Specifically:

  1. Use git stash to store the changes you want to add.
  2. Use git rebase -i HEAD~10 (or however many commits back you want to see).
  3. Mark the commit in question (a0865...) for edit by changing the word pick at the start of the line into edit. Don't delete the other lines as that would delete the commits.[^vimnote]
  4. Save the rebase file, and git will drop back to the shell and wait for you to fix that commit.
  5. Pop the stash by using git stash pop
  6. Add your file with git add <file>.
  7. Amend the commit with git commit --amend --no-edit.
  8. Do a git rebase --continue which will rewrite the rest of your commits against the new one.
  9. Repeat from step 2 onwards if you have marked more than one commit for edit.

[^vimnote]: If you are using vim then you will have to hit the Insert key to edit, then Esc and type in :wq to save the file, quit the editor, and apply the changes. Alternatively, you can configure a user-friendly git commit editor with git config --global core.editor "nano".

like image 127
Greg Hewgill Avatar answered Oct 16 '22 08:10

Greg Hewgill


To "fix" an old commit with a small change, without changing the commit message of the old commit, where OLDCOMMIT is something like 091b73a:

git add <my fixed files>
git commit --fixup=OLDCOMMIT
git rebase --interactive --autosquash OLDCOMMIT^

You can also use git commit --squash=OLDCOMMIT to edit the old commit message during rebase.

See documentation for git commit and git rebase. As always, when rewriting git history, you should only fixup or squash commits you have not yet published to anyone else (including random internet users and build servers).


Detailed explanation

  • git commit --fixup=OLDCOMMIT copies the OLDCOMMIT commit message and automatically prefixes fixup! so it can be put in the correct order during interactive rebase. (--squash=OLDCOMMIT does the same but prefixes squash!.)
  • git rebase --interactive will bring up a text editor (which can be configured) to confirm (or edit) the rebase instruction sequence. There is info for rebase instruction changes in the file; just save and quit the editor (:wq in vim) to continue with the rebase.
  • --autosquash will automatically put any --fixup=OLDCOMMIT commits in the correct order. Note that --autosquash is only valid when the --interactive option is used.
  • The ^ in OLDCOMMIT^ means it's a reference to the commit just before OLDCOMMIT. (OLDCOMMIT^ is the first parent of OLDCOMMIT.)

Optional automation

The above steps are good for verification and/or modifying the rebase instruction sequence, but it's also possible to skip/automate the interactive rebase text editor by:

  • Setting GIT_SEQUENCE_EDITOR to a script.
  • Creating a git alias to automatically autosquash all queued fixups.
  • Creating a git alias to automatically fixup a single commit.
like image 32
Joel Purra Avatar answered Oct 16 '22 09:10

Joel Purra


with git 1.7, there's a really easy way using git rebase:

stage your files:

git add $files

create a new commit and re-use commit message of your "broken" commit

git commit -c master~4

prepend fixup! in the subject line (or squash! if you want to edit commit (message)):

fixup! Factored out some common XPath Operations

use git rebase -i --autosquash to fixup your commit

like image 65
knittl Avatar answered Oct 16 '22 08:10

knittl