You would typically want to UNDO/REDO when you commit some changes to git, and realize that the changes need to be removed/reverted. This very common in scenarios for example, when you did a temporary change to some files, and forgot to revert them, then proceeded to adding them to commit accidentally.
The UNDO/REDO workflow:
Assuming you did some changes and made commits like:
git commit -m "Commit 1 - Some changes to the code"
git commit -m "Commit 2 - Some MORE changes to the code"
- (UNDO-ing): Revert back the last commit
git reset --soft HEAD~
- Do the changes.
- Add your files to the staging area
git add <filenames or paths>
orgit add --all
- (REDO-ing): Do the commit.
git commit -c ORIG_HEAD
orgit commit -C ORIG_HEAD
How does this work?
Now that you know the flow lets understand how this works behind the scenes.
-
Step 1
resets the last commit i.e."Commit 2 - Some MORE..."
back to the"Commit 1 - Some..."
commit. - In
Step 2
, you do changes you deem fit to the files. - In
Step 3
, you add the changed files to the staging area either selectively withgit add <filenames>
or all files withgit add --all
. - In the final step you commit the changes in the staging area.
Note: you can either use -c
or -C
. The small -c
will open an editor for modifying the commit message, in this case it will be Commit 2 - Some MORE...
. You can edit the commit message as you want.
Or alternatively you can use caps -C
, where git will skip the editor window, and reuse the LAST commit message which again in this case is Commit 2 - Some MORE...
.
Re-using the “Same” commit message is also known as redoing/recommiting.
Unstage before a commit
To undo a change staged before a commit simply run git reset <file>
or git reset
to unstage all changes before a commit.
Note: In older versions of git, the commands were git reset HEAD <file>
and git reset HEAD
respectively. This was changed in Git 1.8.2
Some More tricks:
You can go back any number of commits by using git reset --soft HEAD~n
where you want to undo last n
commits.
More detail on How Git Reset Works
The git reset
command allows you to RESET your current head to a specified state. You can reset the state of specific files as well as an entire branch.
Reset a file or set of files
The following command lets you selectively choose chunks of content and revert or unstage it.
git reset (--patch | -p) [tree-ish] [--] [paths]
Unstage a file
If you moved a file into the staging area with git add
, but no longer want it to be part of a commit, you can use git reset
to unstage that file:
git reset HEAD FILE-TO-UNSTAGE
The changes you made will still be in the file, this command just removes that file from your staging area.
Reset a branch to a prior commit
The following command resets your current branch’s HEAD to the given COMMIT
and updates the index. It basically rewinds the state of your branch, then all commits you make going forward write over anything that came after the reset point. If you omit the MODE
, it defaults to --mixed
:
git reset MODE COMMIT
The options for MODE
are:
-
--soft
: does not reset the index file or working tree, but resets HEAD tocommit
. Changes all files to “Changes to be commited” -
--mixed
: resets the index but not the working tree and reports what has not been updated -
--hard
: resets the index and working tree. Any changes to tracked files in the working tree sincecommit
are discarded -
--merge
: resets the index and updates the files in the working tree that are different betweencommit
and HEAD, but keeps those which are different between the index and working tree -
--keep
: resets index entries and updates files in the working tree that are different betweencommit
and HEAD. If a file that is different betweencommit
and HEAD has local changes, the reset is aborted
Points to Note
Be very careful when using the --hard
option with git reset
since it resets your commit, staging area and your working directory. If this option is not used properly then one can end up losing the code that is written.