Thursday, April 25, 2013

Extra Git Merge Commits: Merge branch 'master' of github.com:owner/repo

As I've been working with some friends on a GitHub-hosted project lately, I've seen tons of seemingly extraneous merge commits in our master branch that look something like this:

Merge branch 'master' of github.com:owner/repo

This can seem confusing, especially to those coming from a subversion paradigm, for a few reasons:

  1. You see it when you're working on master. If there's no branching happening, why is there a merge?
  2. The merge commit includes changes that have already been committed, so it looks like they're happening twice.

What Causes This?

When you're working as part of a team, you and your friends will be committing and pushing up to your remote (say, GitHub, Bitbucket, etc.) at different times. Consider the following sequence:

  1. You and Jack both pull down from your remote at the same time. Your local repos both have the same state.
  2. Jack makes a change, commits it, and pushes it to the remote.
  3. You make a change, commit it, and push to the remote.

That's when you get this message:

! [rejected] master -> master (non-fast-forward)

…along with a hint about merging the remote changes using git pull. So you do that…

  1. You do a git pull
  2. You do a git push
  3. You pull up the log and see that doggone merge commit

How Do I Avoid This?

The problem is that the remote master and your local master are out of sync, so Git has to merge the two.

You can get around this by making sure you've got the latest updates from your remote before you do your commit. For example, let's revisit the above scenario, this time taking care to avoid a merge commit:

  1. You and Jack both pull down from your remote at the same time. Your local repos both have the same state.
  2. Jack makes a change, commits it, and pushes it to the remote.
  3. You make a change.
  4. You add your change.
    git add .
  5. You stash your change.
    git stash
  6. You pull the latest from the remote.
    git pull origin master
  7. You pop your stash.
    git stash pop
  8. You commit your change.
    git commit
  9. You push to your remote.
    git push origin master

Voila, no merge commit! The key is that there should be minimal time between steps 6-9. If someone sneaks in a push to your remote between those steps, your push will still get rejected, and you'll end up with a merge commit.

No comments:

Post a Comment

Profile Picture
Dave Leeds
My Hobbies:
  • Programming
  • Cartooning
  • Music Writing
Full Profile