git push origin master -- force đź’Ą

Vitaliy Stanyshevskyy
4 min readMay 2, 2018

--

I don’t use any UI for Git. Instead I type Git commands a lot. Especially the git push origin master. It’s in my muscle memory. I also think that git commit --amend and git push dev_branch --force are useful to keep Git history clean. Of course, I do that only if nobody else uses the branch, because changing public history will complicate other’s lives.

But few weeks ago I accidentally did git push origin master --force.

My feelings at time i realized what I have done. “A woman wearing a skirt walking through the war-torn city of Gunkanjima” by Jordy Meow on Unsplash

“PANIC!” was my fist thought. I couldn’t accept that this action is irreversible. I searched for the ways of saving my day and the day of my teammates. I’ve already known about 2 possible ways to fix it and found out the third one.

Note: if you changed the public history, let your teammates know, so they won’t use the modified branch as a base.

Call a friend 📱

Git is distributed system, so there should be at least one person who has latest master that I screwed up. So the simplest way to fix it is to ask that person to push his local master branch and override the broken one.

It was not an option for me since the person with latest master was on the other side of the planet and offline. I had no desire to block teammates so I went deeper.

âś… Pros:

  • It’s the simplest and the most reliable way

❌ Cons:

  • Might not suite the current situation. The person with last legit commit might be offline.

Travel back in time ⌚

Git keeps the history of all your recent actions. And it rarely cleans this history. We can use it and go few steps back in time in a repository universe.

Welcome git reflog. Here’s what Atlassian’s Tutorial says about it.

The reflog is Git’s safety net. It records almost every change you make in your repository, regardless of whether you committed a snapshot or not. You can think of it as a chronological history of everything you’ve done in your local repo.

If you take the latest master, modify the branch history and push it with--force flag, you can revert back to the original state and fix the remote master branch with git reflog command. For example:

Git reflog in action

As you can see in example above the latest commit had SHA starting withef1f113. Restored commit has the same SHA (line #33). So this action doesn’t modify the history and other users should not notice anything.

But unfortunately it was not an option for me, since I haven’t had latest master. I haven’t pulled master for few days. I just typed master instead of feature branch name in my push command.

âś… Pros:

  • Relatively easy — requires only few steps.

❌ Cons:

  • Will not help if pushed to a branch without pulling the latest commits first

Step into the void 🌌

After some time researching the web I found out the workaround. The main idea is that Git stores commits even when you delete or modify the branch. And these commits can be accessed.

git checkout allows to checkout directly to a commit if you know its SHA:

git checkout docs say that you can checkout to a commit

The trick here is to get the SHA of the last “healthy” commit. There are couple of ways to get it:

  1. Check the terminal. Every git command provides useful output that includes SHA. In the example below line #4 has 1d622dd...f521236 part, which stands for <old SHA>...<new SHA> .
Git push output with old and new SHAs

2. Check CI logs. Jenkins, TeamCity or any other CI servers save the logs. Usually build logs contain git output where you can see the SHA or it might be even in the UI:

Commit’s SHA in Jenkins

When you found the SHA, checkout to it. And you will be in detached HEAD state. You can read about it here. For example:

Checking to commit that no longer belongs to a branch

The good thing is that the commit you checked directly to, has all the history behind it unmodified. And you can recreate the master from it using the following steps:

Restoring master from latest legit commit

That’s it. Master branch was restored and all history preserved.

âś… Pros:

  • Works even if you don’t have the data locally.

❌ Cons:

  • It’s the most complex of these 3 ways.

Summary

There are almost no actions that you can’t revert in Git. Although measure twice and cut once. It’s a good rule of thumb not to use --force flag. Or be extra careful when you need to use it.

If you changed the public history, let your teammates know, so they won’t use the modified branch as a base.

And of course each accident is a possibility to learn something new.

--

--