Feb 05 2014

What to do when you’ve ruined origin/master

First of all, don’t panic. This can be fixed easily or relatively easily!

However, let’s get this out of the way:

Why you push -f master?

Okay, now that we have that out of the way, let’s go over the ways to fix this.

Local Commit Reference

If you have the commits locally, you can simply repush the correct commit SHA back to master. Your accidental force push should print out the following:

To https://github.com/#{YOUR_ORG}/#{YOUR_REPO}.git
+ #{PREVIOUS_MASTER_SHA}...#{NEW_MASTER_SHA} master -> master (forced update)

You can tell Git to update the reference of a remote branch with a colon by pushing again to master with

git push origin #{PREVIOUS_MASTER_SHA}:master -f

Easy, right?

Remote Reference

What’s not so easy is if you accidentally force push master to GitHub and you haven't fetched recently. Git will not let you push a reference you don’t have locally, and it won’t let you fetch commits that cannot be reached from some named reference like a branch.

Fortunately, GitHub has an API that you can easily hit through everyone’s favorite command line data transfer tool,

curl
.

You’ll need the same information as in the previous section regarding the SHAs, but you’ll need to jump through one more hoop.

PREVIOUS_MASTER_SHA
is actually only the first 7 characters of the commit’s SHA so to get the full thing, we’re going to have to go to GitHub. Just pop over to
https://github.com/#{YOUR_ORG}/#{YOUR_REPO}/commit/#{PREVIOUS_MASTER_SHA}
and you’ll see the full SHA. Grab that, head over to your terminal, and put in the following:

curl -u #{YOUR_GITHUB_USERNAME} --request PATCH https://api.github.com/repos/#{YOUR_ORG}/#{YOUR_REPO}/git/refs/heads/master --data '{"sha": "#{FULL_PREVIOUS_MASTER_SHA}", "force": true}'

Enter your password, and everything should be good.

An ounce of prevention is worth a pound of cure

Find out why you accidentally force pushed to master, and learn from it. What is your Git config’s

push
value is set to? The default is
matching
which can get you into trouble if you just do a blank
git push -f
. This is changing to
simple
in Git 2.0 but
current
is another good choice. More options can be found in Git's man pages or at http://git-scm.com/docs/git-config.

Also be careful with aliases that make it too easy to use flags you might not want. I personally use

gush
for
git push
which requires me to explicitly type
-f
, but many have set up an alias like
gpf=‘git push -f’
. It can save a little time but can easily get you in a bind.

As Uncle Ben said:

“With great power comes great responsibility.”

Use

-f
carefully.

— Aaron Rosenberg (@agrberg)

mwahahaha

MojoTech

Share: