abangratz - blag

Stuff that matters - at least for me.

Git EEP!

Over the course of working with git, everyone encounters errors. Now, there are quite a few tutorials that explain stuff nicely - but git is very powerful, so even the easiest explanations are hidden beyond pages and pages of documentation.

I want to point out the most common error messages and resolve strategies.

Common to all of the following is: DON’T PANIC!

Read the error message and you will find a strategy for everything.

Merge Errors

Merge errors happen after a git merge, git rebase or git pull. The most common are

  1. Merge conflicts
  2. Avoiding overwriting of local changes

Merge Conflicts

For the first, imagine that the following happens:

Merge conflict
1
2
3
4
5
$ git pull
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
$

So, what happened? First, you changed and commited some lines in index.html, and during that time, someone else changed something in index.html, too. Second, the changes could not be automatically merged, which means either someone deleted lines so the correct place to put your changes could not be found, or the both of you changed the same line(s).

Now, how you resolve it depends on what you want to do. If you are sure that your changes are correct and should override the other (remote) changes, then you go

Merge conflict - Keeping ours
1
$ git checkout --ours -- index.html

If on the other hand you want to keep their changes and throw away yours, you go

Merge conflict - Keeping theirs
1
$ git checkout --theirs -- index.html

But if you want to really merge the change, that means you keep a little bit of your changes AND a little bit of their changes, then you should use a merge tool.

A merge tool is a (usually graphical) user interface that lets you direct the merge. I prefer to use kdiff3. It has a nice interface and a lot of options, and it is very smart about automatically resolving more complex merges before presenting you an unresolvable conflict. You might want to make yourself familiar with the tool, though, because the multitude of options or buttons might overwhelm you at first.

On invocation, this should look similar to the following:

Merge conflict - using mergetool
1
2
3
4
5
6
7
$ git mergetool
Merging the files: index.html

Normal merge conflict for 'index.html':
  {local}: modified
  {remote}: modified
Hit return to start merge resolution tool (kdiff3):

kdiff3 will try to resolve the conflict once again, and it does succeed every once in a while - then the GUI will never be started. To see what the GUI looks like, you’ll find screenshots at the homepage linked above. git mergetool will leave files with the suffix ‘*.orig’ behind which should never be added to the git index, but can be deleted safely after committing the merge.

Another method would be to resolve the conflict manually. The content of a file will look similar to this:

Merge conflict - conflict markers
1
2
3
4
5
6
7
<head>
<<<<<<< HEAD
    <title>This is the most awesome title</title>
=======
    <title>This is the awesomest title</title>
>>>>>>> 093420abc897324dfe
  </head>

The things <<<<<<, ====== and >>>>>> are called “conflict markers”. These show you what the others (between the first marker and the middle marker) and you (between the middle and the last marker) have added that lead to a conflict. To resolve this, you remove the markers and the wrong change - or you change it to acommodate both, e.g.

Merge conflict - manually resolved
1
2
3
<head>
    <title>This is the most awesomest title</title>
  </head>

After that, you have to commit the merge. Usually, it is sufficient to type

Merge conflict - committing
1
$ git commit

which will open an editor with the most important information already filled out (like an automated commit message, and which files had a conflict).

After that, you are free to push, because the conflict has been resolved.

Overwriting local changes

Now, every now and then, you will encounter a different beast. On a git pull or git rebase, you will see:

Merge conflict - local changes
1
2
3
4
$ git merge
...error: Your local changes to the following files would be overwritten by merge:
    index.html
Please, commit your changes or stash them before you can merge.

This is actually easy and has four resolutions: first, you can just commit your change and maybe run into a merge conflict, which you just learned how to resolve.

Second, you could stash the current work, which means it would be moved out of the way and saved locally, before merging

Merge conflict - stash
1
2
3
$ git stash
Saved working directory and index state WIP on master: 056fdb6123 Add index
HEAD is now at 056fdb6123 Add index

Then you can pull or merge normally, and then apply your local changes again:

Merge conflict - stash pop
1
2
3
$ git stash pop
....
Dropped refs/stash@{0} (...)

This also might lead to a merge conflict - but you know now how to handle these anyways.

The third option is to reset your changes via checkout:

Merge conflict - checkout resetting
1
$ git checkout -- index.html

WARNING! This will throw away the local changes in this file irrevocably!

And the third option would be to reset the source tree before pulling:

Merge conflict - checkout resetting
1
$ git reset --hard HEAD

BIG WARNING! This will reset all changes in all files locally to the last committed version! Your changes will be gone for good!

Push Errors

There’s actually only one: you try to push and it doesn’t work, telling you about conflicts. Now, that’s easy:

What happened:

Push Errors - rejected non-fast forward
1
2
3
4
5
6
$ git push
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to 'git@github.com:....git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the 'non-fast forward'
section of 'git push --help' for details.

The resolution is simple: use git pull to receive the changes that you don’t have yet locally. If a merge conflict occurs, go back to the beginning of the document.

Alright, this should cover the most common error messages. Keep cool and remember:

Use git commit before git pull and git pull before git push. That should halve the errors.

TL;DR

If you encounter the following git errors, try:

  1. Merge conflict:
  • git mergetool or
  • git checkout --(ours|theirs) -- filename or
  • resolve by hand
  1. Avoiding overwriting local changes:
  • git commit before pull
  • git stash before pull, git stash pop after pull
  • git checkout -- filename or git reset --hard HEAD to reset
  1. Push conflict:
  • git pull between commit and push

Questions, suggestions? Try the links on the sidebar or leave a comment.

Happy developing!

Comments