How do I undo things in Git?
There are times when you (or a team-mate) make a change that is not desired or causes your product or site to not work. Other times you forgot to include a certain change, or made a mistake in your commit message. In these situations, it’s common to want to rollback, or undo, a change made by you or your team.
You can do this with almost all activities in Git. Commits, merges, local or remote changes, and even uncommitted changes can all be “undone”. We’ll cover various scenarios below, from the least impact to the greatest.
- How do I remove all uncommitted changes to my working directory?
- How do I fix the commit message I just made?
- How do I add an additional file to a commit I just made?
- How do I rollback a file to a certain commit in history?
- How do I revert changes I made to a specific commit?
- How do I make a commit completely disappear from history?
These are just a few of the common scenarios developers experience. If you need help with something different, our team would love to give some guidance. Just use the Contact button at the top right to get in touch!
Uncommitted Changes
How do I remove all uncommitted changes in my working directory?
One possible action to take in Git is to undo changes you made locally, but have not yet committed or pushed up to your remote repo.
With Git, “local” means uncommitted changes, not just changes that have not been pushed (aka the “working” directory). And there are times when you would want to undo uncommitted changes. Some coding sessions go sideways, fast. A quick 10 minutes of work can result in changes that leave your code in a far less ideal state than when you started. And so a fresh start can be a good choice.
Note:
An important distinction with uncommitted changes is that you cannot recover the changes you discard with the commands below. As they have not been committed, Git has no record of the changes.
To undo all the changes you’ve introduced since the last commit, use the following command:
git reset --hard
This command reverts the repo to the state of the HEAD revision, which is the last committed version. Git discards all the changes you made since that point.
Other times, you may want to
only discard the changes to
one file in the repo. You can do this with the checkout command:
git checkout --
path/to/the/file.txt
Use the checkout command with two dashes, then the path to the file for which you want to revert to its previous state.
Committed Changes
As well as uncommitted changes, there will inevitably changes that you have committed to your repo that you want to revert. This is not something that should be scary — it's one of the greatest benefits of version control. Let's look at a few common scenarios.
How do I fix a message of a commit I just made?
First, Git includes the ability to amend the
most recent commit message. Note that this is not a specific commit in your history, but simply the very last commit. The usage is straight forward:
git commit --amend -m “Add your correct commit message here.”
How do I add an additional file to a commit I just made?
As well, if you forget to stage some changes, you can include them in a previous commit. Stage those changes with "git add", then use “git commit” with the amend option to correct the previous message.
git add path/to/changed/file
git commit --amend -m “Add your updated commit message here.”
Note:
This is only available for the most recent commit, not any commit in your repo history. As well,
you should only use the amend option on local commits, not commits that you pushed to a remote repo. Otherwise, you can cause confusion for teammates.
How do I rollback a file to a certain commit in history?
This scenario is also straightforward. You can use the
git-checkout command to change a specific file back to its state at a specific commit:
git checkout <commit_ID> path/to/the/file.txt
Once completed, you would then commit the change to this file, returning it to its earlier state.
How do I revert changes introduced by a specific commit?
When you need to undo something you’ve committed, you have a couple of good options. Both of the options below will only affect the current HEAD, so be sure to confirm that you have the intended branch checked out.
Revert
As it sounds, the revert command changes all the files for a specific commit back to their state before that commit was completed. Specify the commit that you want to revert:
git revert <commit_ID>
It’s important to note the mechanics of this command. The reverted commit is not deleted. Rather, Git creates a new commit with the included files reverted to their previous state.
So your version control history moves forward while the state of your files moves backwards.
Reset
This option is a little different than a revert. It resets the status of your repo (working HEAD) to an older revision. It’s a true rollback of the state of your repo.
git reset --hard <commit_ID>
When you use this option, Git discards any commits between the current state of the repo and the target commit. The branch will then appear to stop at the commit you reset the HEAD to.
Note:
Although the commits no longer appear to be a part of your branch history, they are not deleted. They are still stored in Git.
As well, be cautious with the --hard option. It will also discard any local changes you have made. If you want to reset to a previous commit, but still have your current changes saved as they are, use the --keep option instead.
Which is better?
Which is the better option? Since the purpose of version control is to record the work done by you and your team, a revert is the best choice for undoing changes. It results in your files being in the state you desire, but also keeps your complete history intact. It's your “paper trail”!
At times, junior developers want to undo their work in hopes that senior teammates won’t notice their mistakes. Embrace the fact that you’re always learning. Showing your teammates that you understand how to undo your changes elegantly will go a long way!
How do I make a commit completely disappear from history?
That said, people do want to completely remove an activity from being saved in their Git repo in some situations. If this happens, you can use the
git rebase command.
git rebase -i [revision number]
Although it may sound a tad obvious, be careful with this option. There are several ways to go about changing things and developers should always choose a recipe that suits their specific scenario. We’ll walk through an example below, but the listed steps are specific to this scenario only.
Imagine that a unintended file was included in your repo that you would rather not have there.
Nacho Libre GIFs are awesome, but you may not want them on your client’s site. This file was added to the repo 5 commits previous. The following is a recipe to have that file removed from the repo, and the repo history:
# create and check out a temporary branch at the location of the bad merge
git checkout -b tmpfix <sha1-of-merge>
# remove the incorrectly added file
git rm somefile.orig
# commit the amended merge
git commit --amend
# go back to the master branch
git checkout master
# replant the master branch onto the corrected merge
git rebase tmpfix
# delete the temporary branch
git branch -d tmpfix
Local vs. remote
One last thing to consider is whether the changes you're reverting should be on your local or remote repo. In short, the best practice is to do a pull before you start any work session. That way, you have all the latest updates from your teammates before beginning work.
Once you have completed your work, whether with new changes or undoing previous changes, do the work locally. Then you can push your changes back up to the remote repo.