This page looks best with JavaScript enabled

Back in time with git

 ·   ·  ☕ 3 min read

Reset, revert and more!

Git is an awesome piece of software, but it can be as complex as you want it to be.
There are plenty of ways one can undo changes with git.
We’ll review a couple of them.

This command shows the hashes of the last 10 commits, you’ll probably need it!

1
git log -10 --abbrev-commit --pretty=oneline

Undo one or more commits

For this we use git reset <HASH>.

This puts us back to the commit we give it.
It can do it in one of three ways:

  • --hard: Destroys everything in its path. No changes are kept (staged or not).
  • --soft: Keeps all uncommitted changes, both staged and unstaged.
  • --mixed(Default option): Keeps all uncommitted changes, but unstages everything.

As a bonus, we can go back n number of commits by using the HEAD position instead of the commit hash:

1
git reset HEAD~n

Where n is the number of commits we want to go back

To undo the last commit and keep uncommitted changes:

1
git reset --soft HEAD~1

To undo the last commit and remove uncommitted changes:

1
git reset --hard HEAD~1

Undo a merge

Merges seem scary and messy (and in some cases they are) but in the end it’s just a fancy commit.

As such, a git reset --hard HEAD~1 is more than enough to undo it!

If something goes wrong during a merge conflict you might consider using git merge --abort and trying again from scratch.

Undo an add

If we don’t pass a hash or HEAD position to git reset, it will default to the current HEAD position.
Knowing this and that the default flag it uses is --mixed, you can infer that to undo a git add . the solution is:

1
git reset

As explained before, no commits will be touched, but all staged changes will end up in the working tree.

Undo a push

You can’t.
What you can do is undo the breaking commit and push again.

There are two ways to go about this:

You work alone -> reset

Don’t worry about it, just use git reset --hard HEAD~1 as we saw before and use the -f flag when doing the next push.

This way, you are changing the commit history and forcing your local repository onto the remote one.

After you push this second time, you’ll see the last commit disappear from the remote repo.

You work in a team -> revert

That won’t work if you are not the only one working on that repo (or on that branch).
Well it would work, you just shouldn’t do it.

Someone else might depend on what you just removed and even if they don’t, you are likely to cause conflicts with that method.

In this case, we do a git revert HEAD --no-edit.
This will create a separate commit that only includes the changes necessary to undo (revert) the commit it receives (in this case, HEAD).

Now, after a normal git push you’ll see a new commit with the same message as the one that broke stuff, prepended by ‘Revert …’.
This is the safe approach.

The Nuclear option

Sometimes, you just have no clue what the heck you did to your local repository.
It’s a mess you can only untangle by resetting it to whatever is working on the remote.

To get your local repo back in sync with the remote one:

1
2
3
git fetch origin
git reset --hard origin
git clean -xdf

We sync our repo refs to the remote ones, use it to do a hard reset and clean all untracked files recursively, just in case.

Hopefully you can work calmly now, knowing that git has your back!

Support the author with