If I've learned anything in my 15+ years of programming, it's that mistakes are common, and I make a lot of them. This equally applies to version control tools as well. Whether you accidentally commit changes, or just realized your previous committed code isn't what you wanted, oftentimes you'll need to revert a previous commit in Git.
In this article I'll show a few ways to revert your commits, depending on your use-case. This is a complicated topic (which is true for many Git topics in general), so make sure you follow the instructions that best suit your needs.
Delete Unpublished Commits
If you haven't yet published your commits to a remote repository, like GitHub, then you can essentially delete previous commits by using the
While this is an effective solution, it's a dangerous one since you're rewriting history and leaving the "deleted" commits unreferenced, or "orphaned". The only way to find and recover these unreferenced commits is with
reset command has three different options, two of which we'll describe here:
git reset --hard <hash-or-ref>
--hard option, everything is reverted back to the specific commit. This includes the commit history reference pointers, the staging index, and your working directory.
This means that by using just this command you'll not only revert to a previous commit, but you'll lose all working changes in the process. To avoid losing any working changes, you can use the
stash pop commands:
git stash git reset --hard <hash-or-ref> git stash pop
stash command saves your working changes (without any commits or changes to the tree), and then
stash pop brings them back.
The other option you may consider is the
--soft option. This option works much the same way as
git reset --hard <hash-or-ref>, but it only affects the commit history, not your working directory or staging index.
git reset --soft <hash-or-ref>
So if you have uncommitted changes that you want to keep, then this is likely the option you want.
Deleting Published Commits
So let's say you committed your code and then pushed it to the remote repository. At this point it's highly advised that you do not use something like
git reset since you'd be rewriting history.
Instead, the recommended approach would be to use the
revert command. This command works by undoing changes that were made in the specific commit by creating a new commit and not actually removing any previous commits. This is ideal for published changes because then the true history of the repo is preserved. Here is the command:
git revert <hash-or-ref>
So let's say you have a text file in your repo with the following content:
This is my sample text
And then you change it to:
This is my awesome sample text
Your commit history might look something like this:
git log --pretty=oneline 676ec97a9cb2cebbb5c77904bbc61ced05b86f52 Added 'awesome' to text 735c5b43bf4b5b7107a9cc3f6614a3890e2889f6 Initial commit
If we decide we don't want "awesome" in our text anymore, but we don't want to delete the
676ec commit, we can use
revert to undo that change:
git revert 676ec [master f68e546] Revert "Added 'awesome' to text" 1 file changed, 1 insertion(+), 1 deletion(-)
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
After being prompted to enter a commit message, we can now see in our commit history that there is actually a new commit:
git log --pretty=oneline f68e546ac2ae240f22b2676b5aec499aab27f1ca Revert "Added 'awesome' to text" 676ec97a9cb2cebbb5c77904bbc61ced05b86f52 Added 'awesome' to text 735c5b43bf4b5b7107a9cc3f6614a3890e2889f6 Initial commit
As a result of this, the first and third commits represent the exact same project state. The commit has been reverted, and no history was lost.
Note that there are quite a few other ways to use this command, like if you want to revert back 2 commits, you can use:
git revert HEAD~2
Or if you want to revert many non-continuous commits you specify them individually:
git revert 676ec 735c5
Cherry-Picking a Commit
In Git, "cherry-picking" refers to the process of applying a specific commit from one branch to another. This allows you to selectively apply changes made in the past without affecting the current state of the repository.
To cherry-pick a commit, first identify the commit hash of the commit you want to apply. You can do this by running the
git log command and looking for the hash of the commit you want to cherry-pick.
Once you have identified the commit hash, switch to the branch you want to apply the changes to, and run the following command:
git cherry-pick <commit-hash>
This will apply the changes made in the specified commit to the current branch, creating a new commit that contains only those changes. If the changes conflict with the current state of the branch, Git will prompt you to resolve the conflicts before continuing.
It's important to note that cherry-picking a commit does not merge the entire branch that the commit is on. It only applies the changes made in the specified commit. This can be useful if you want to apply a specific fix or feature from one branch to another without merging the entire branch.
Cherry-picking a commit can also be used to revert changes made in a previous commit. To do this, simply cherry-pick the commit you want to revert, and then apply the changes to the current branch. This will create a new commit that undoes the changes made in the original commit.
Temporarily Checkout a Previous Commit
By "reverting a commit", you might mean that you temporarily want to go back to a previous state in your repo, but without making any actual changes to the tree. In this case you'd probably just want to checkout the commit, allowing you to go back to master or any other state when you're done:
git checkout <hash-or-ref>
This will change your working directory to the contents of that commit, as well as the location HEAD points to, none of which is irreversible. Any changes you make here can either be committed to a branch or stashed for later use.