Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify a specified commit?

I usually submit a list of commits for review. If I have the following commits:

  1. HEAD
  2. Commit3
  3. Commit2
  4. Commit1

...I know that I can modify head commit with git commit --amend. But how can I modify Commit1, given that it is not the HEAD commit?

like image 717
Sam Liao Avatar asked Jul 27 '09 05:07

Sam Liao


People also ask

Can I amend already pushed commit?

It is recommended not to use amend if you have already pushed the changes to remote and other developers have already started using those changes.


2 Answers

You can use git rebase. For example, if you want to modify commit bbc643cd, run

$ git rebase --interactive 'bbc643cd^' 

Please note the caret ^ at the end of the command, because you need actually to rebase back to the commit before the one you wish to modify.

In the default editor, modify pick to edit in the line mentioning 'bbc643cd'.

Save the file and exit: git will interpret and automatically execute the commands in the file. You will find yourself in the previous situation in which you just had created commit bbc643cd.

At this point, bbc643cd is your last commit and you can easily amend it: make your changes and then commit them with the command:

$ git commit --all --amend --no-edit 

After that, type:

$ git rebase --continue 

to return back to the previous HEAD commit.

WARNING: Note that this will change the SHA-1 of that commit as well as all children -- in other words, this rewrites the history from that point forward. You can break repos doing this if you push using the command git push --force

like image 185
ZelluX Avatar answered Sep 24 '22 02:09

ZelluX


Use the awesome interactive rebase:

git rebase -i @~9   # Show the last 9 commits in a text editor 

Find the commit you want, change pick to e (edit), and save and close the file. Git will rewind to that commit, allowing you to either:

  • use git commit --amend to make changes, or
  • use git reset @~ to discard the last commit, but not the changes to the files (i.e. take you to the point you were at when you'd edited the files, but hadn't committed yet).

The latter is useful for doing more complex stuff like splitting into multiple commits.

Then, run git rebase --continue, and Git will replay the subsequent changes on top of your modified commit. You may be asked to fix some merge conflicts.

Note: @ is shorthand for HEAD, and ~ is the commit before the specified commit.

Read more about rewriting history in the Git docs.


Don't be afraid to rebase

ProTip™:   Don't be afraid to experiment with "dangerous" commands that rewrite history* — Git doesn't delete your commits for 90 days by default; you can find them in the reflog:

$ git reset @~3   # go back 3 commits $ git reflog c4f708b HEAD@{0}: reset: moving to @~3 2c52489 HEAD@{1}: commit: more changes 4a5246d HEAD@{2}: commit: make important changes e8571e4 HEAD@{3}: commit: make some changes ... earlier commits ... $ git reset 2c52489 ... and you're back where you started 

* Watch out for options like --hard and --force though — they can discard data.
* Also, don't rewrite history on any branches you're collaborating on.



On many systems, git rebase -i will open up Vim by default. Vim doesn't work like most modern text editors, so take a look at how to rebase using Vim. If you'd rather use a different editor, change it with git config --global core.editor your-favorite-text-editor.

like image 33
Zaz Avatar answered Sep 26 '22 02:09

Zaz