Typically, changes made by developers to git repositories are made on branches, which overview some sort of code review / testing process and are merged. Sometimes, accidentally, we make commits on or prematurely merge to master, staging, dev, etc.., and want to reset master to match our upstream repository.

The lazy way to do this, and one I've often employed in a rush, is to perform a fresh checkout of the repository and delete the one with errant commits. This almost always takes longer than repairing the existing clone, esp for large repositories, and if there are unsynced local branches, it can be inconvenient to lose them.

Above all, it's always best to understand our tools and to not choose solutions which avoid learning, so I'm documenting this for the benefit of others, and so that I can point here when asked. :)

This situation often manifests itself as a failed "git pull", in which case I typically start with:

git reset --hard HEAD

Now, for a given branch, $BRANCH, we store the current branch pointer in case we need to refer to it later, and re-create $BRANCH.

git checkout $BRANCH
git checkout -b old_wierd_broken_$BRANCH
git branch -d $BRANCH
git checkout $BRANCH
git pull