Git: Keeping in sync

In the Getting start with git post we covered a number of things, one of which was using push to send our commits to a remote git repo. This is works fine when both of these conditions are met:

  1. You’re the only person working on the project
  2. You’re doing all of your development from the same machine

If one of these points is not true, you’ll soon find the push command fails to work. The reason for this is because you must first retrieve all of the commits from the remote branch before you can merge your own. In other words, you must first be in sync before you can make modifications.

Therefore if someone does a push before you, and/or you do a push from a different machine, the machine you’re currently using will be out of sync with the remote branch. As a result you will be unable to do a push until you first re-sync with the remote branch.

Note: The reason why this issue is not encountered when you meet the two criterion listed above is because your machine will always be in sync with the remote branch given that it’s the only one doing any commits.

Let’s now run through an example to see this in action.

Step 1: Update the remote branch

The first thing we’ll need to do is update the remote branch. Rather than have someone else do a push or me use another machine to do the push, I’m going to create a new file through the GitLab web GUI. Doing so automatically makes a commit on the remote branch and therefore makes my machine’s copy out of sync.

After clicking Commit change my local copy of origin/master is now out of date. However, my machine doesn’t know that yet:

Step 2: Make modifications locally

Next we need to make a modification locally, whether it be the creation, modification or deletion of a file that will be/is currently tracked by the git. Let’s go ahead and create a new file, stage and commit it:

So far, so good! Now let’s push our commit the same way we did last time:

What happened?! Oh yes, that’s right,  Updates were rejected because the remote contains work that you do not have locally.

Getting back in sync

At this point the git status output can be a little confusing because it tells us that it knows about our local commit, but says nothing about the commit on the remote branch:

The reason for this is because git doesn’t update unless you specifically tell it to do so. Let’s go ahead and do that now, but instead of using the git pull command mentioned in the error output, let’s use git fetch instead:

Excellent, our origin/master  has now fetched the latest information and is in sync with the remote git server.

If we issue the git status command again we can see that git now knows about both our commit, as well as the commit which was made through the GUI:

However, if we try to push our commit again we’ll get a new error:

In this output git is telling us that our local master branch is out of sync with the remote origin/master branch and therefore we cannot push until they’re in sync. In order to sync them, git tells us to use the git pull command.

However, because we’ve already done a git fetch, we can instead use the git merge command to merge the origin/master branch’s changes into our master branch, as shown below.

Note: The git pull command does a  git fetch and git merge. Therefore seeing as though we had already done a git fetch, both the git pull and git merge commands would have resulted in the same outcome.

Excellent, our merge was successful! Let’s now check the git status output:

OK so now we’re two commits ahead of origin/master. This is makes sense because the first commit would be the change we made on master (remember the echo 'this is a new file' > new_file.txt command?), and the second change is one one we did in Step 1 being merged in.

Let’s now push our local master branch to the remote origin/master branch:

Finally, let’s do a git status to ensure that our local and remote branches are in sync:

Final Notes

I want to finish off this post with some final notes which might not have been abundantly clear to newcomers:

  • The git fetch, git merge and git pull are all done locally on our machine. To put it another way, the merging of the master and origin/master branches are done on our machine. Only when we do a git push are our changes published to the remote repo where others can see them. Therefore there’s no need to panic if you make a mistake with your fetching, merging and/or pulling, so long as you don’t then do a push.
  • In this post we merged one remote commit into our one local commit. This resulted in us having to push two commits to the remote repo. What you might not know though is that even if there were three remote commits and one local commit, we would still only push two commits to the remote repo – the first one being our local commit, and the second being all of the other commits wrapped up into a single commit. Let’s run through a quick example now…

Let’s make three commits on our remote repo (again using the GitLab GUI). Let’s call them file7.txt, file8.txt and file9.txt. Let’s also create a file locally on our machine called file10.txt.

Because we used the GitLab GUI to create the three remote files, they were each committed separately. This therefore resulted in three commits being made. Let’s now commit our file10.txt locally:

OK great, we can see that we’re one commit ahead of origin/master. Let’s now fetch the latest commits so that we can update our copy of origin/master and see the real difference in commits:

Now we’ve got the full story. We’ve made one change locally, but there have been three changes made remotely. To clean this situation up, we can use a git pull or git merge as discussed previously. Let’s do a git pull this time around:

And there we have it. Although there were a total of four commits originally, we end up with only two. This is known as a merge commit. For information on Recursive merges as well as Rebasing, please see the Git: Merging & Rebasing basics post.

Knowledge Base

See the Git section of my Knowledge Base for more information.

As always, if you have any questions or have a topic that you would like me to discuss, please feel free to post a comment at the bottom of this blog entry, e-mail at will@oznetnerd.com, or drop me a message on Twitter (@OzNetNerd).

Note: This website is my personal blog. The opinions expressed in this blog are my own and not those of my employer.

Leave a Reply

Your email address will not be published. Required fields are marked *