Throwing away local changes in Git workspace, allowing 'git pull' to proceed

; Date: August 8, 2017

Tags: Git

Git is a powerful source code revision control system, letting teams large and small track changes between team members. It is widely used and very flexible. However, it's easy to get into an inscrutable state where it's not clear how to proceed.

Just now I found myself wishing to update my local repository with changes from co-workers. The repository contains UML models designed with Enterprise Architect, hence the primary thing in the repository is a large binary file. I'd been running Enterprise Architect on my local file, and there must have been some changes made to that file. As such Git told me there were local changes which I must merge before I could fetch the upstream changes. (specifically: Your local changes to the following files would be overwritten by merge) But I knew any change that had been made was unimportant, unneeded, and should be tossed away. Leaving me wondering how to throw away changes to a local Git repository.

Here's the problem:

$ git pull
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 2), reused 6 (delta 2), pack-reused 0
Unpacking objects: 100% (6/6), done.
From github.com:ORGANIZATION/REPOSITORY
   add0c66..2d8a40d  master     -> origin/master
Updating add0c66..2d8a40d
error: Your local changes to the following files would be overwritten by merge:
    MODEL_FILE_NAME.eap
Please commit your changes or stash them before you merge.
Aborting

I have used Enterprise Architect on a local .eap file to browse the UML models being designed by co-workers. I am not the person to be making changes, that is the responsibility of those co-workers, and therefore any change I make should be thrown away. But I do need to use Enterprise Architect to browse the UML models.

As is common with desktop applications, simple use of the application to READ the file will often cause the application to make changes to the file it is READING. That's crazy but there are plenty of applications where this is true.

That must be what has happened this time -- somehow clicking on something, even though I didn't change anything, must have caused the file to register some kind of change.

Whatever the reason, Git is believing the file has changes. Git is treating those changes as if they're important and giving me valuable advice on how to preserve those changes. Indeed there are many situations where I WOULD want to save local changes. What I would do in such a case is to commit local changes, for example, so that a git merge command could work.

Instead, in this case I do not want to preserve local changes.

My first thought was to use git revert. While that's a useful command to learn, its effect is to undo certain commits in your working tree. That isn't what is needed in this case.

Instead what's required is the git reset command. The documentation isn't all that clear, but this command does the trick:

$ git reset --hard HEAD
HEAD is now at add0c66 Minor changes to modules properties

What this does is reset the working tree to match the named commit. HEAD is a magic value that refers to the most recent commit.

Once you've run git reset, you can now do:

$ git pull
Updating add0c66..2d8a40d
Fast-forward
 MODEL_FILE_NAME.eap | Bin 2297856 -> 2885632 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)

Because this is a "Fast-Forward" action it demonstrates that the local file had zero changes from the repository and Git could do a fast merge.