Git — an advanced introduction

Lior Zisman
Sep 3, 2018 · 5 min read
A wonderful sight at the end of the branch. Photo by dorota dylka on Unsplash.

Source Control systems play a key role in software development processes, but not only — from content writers to designers, people use it to manage versions of their projects.

Part 1 covered reasoning behind Source Control systems, and went over the foundations of working with Git, a commonly used Source Control system.

In this part I will cover more advanced, yet crucial, functionality of Git — working with remote repositories, branches, and problems that might occur when simultaneous work is done — and how to solve them.

Remotes

In order to enable collaboration, the project must be available somewhere for your team to access. It also effectively acts as a backup, as the project is fully available in the remote location, providing you keep it up-to-date.

To allow that, repositories are normally hosted somewhere on the internet (on a ‘remote’ server). It is worth noting though, a remote repo could also be on your local machine. The term ‘remote’ only specifies that it’s elsewhere.

For that to happen, your Git project needs to have a destination address for that remote location, and a name for that address.
You can have more than one such destination for a project, so traditionally the main one is named origin.

To add an origin for your repo, enter git remote add origin <address> .
You can view the remote addresses of your Git project with git remote -v .

Sometimes, you will need to get a fresh copy of a project from a remote repo. You can use git clone <address> for that. It will also add that address as the origin for the project.

Slightly Branching

Let’s branch for a moment from remotes and talk about… well, branches.

In a nutshell, a branch in Git is simply a lightweight movable pointer to a commit. The default branch name in Git is master, and is created automatically when you init a repo. As you make your commits, the master branch ‘pointer’ points at the last commit you made, and moves forward automatically.

You can always create more of these pointers, which will initially point to the same commit as the pointer you branched from, and select which one is the currently working branch — meaning the commits will be ‘pointed’ by that branch pointer. Notice — those commits will not affect any other branch.

This enables working in parallel on the same project — each collaborator can work on a branch of his own, and merge the work back to the main branch when he’s done. We’ll talk about merging later on.

Typical branching workflow. Each person branches off the main one, and merges his work to it when he’s done.

This also adds a major benefit — since the commits ‘belong’ to a separate branch, incase you want to discard your work or go back to the previous state (the most up to date master), you can just delete the branch or start a new one, which is way easier and efficient than manually deleting, or reverting to an early commit on the master branch. This is why I use branches even when I work alone on a project — maintenance is a breeze and I don’t ‘mess’ the codebase when I experiment with a new feature or new technology.

In order to get the list of branches of the current repo from your remote, enter git fetch. It will fetch the list from the server, so you can select any of them as your currently working branch, and proceed to commit to that branch.

Push and Pull

So far we saw how to configure a project for collaborative work. Now lets learn how to put that to use.

In order to put the changes you committed to a branch on a remote, simply run git push. It will modify the branch on the remote to match your local version.

But how does Git know how to ‘merge’ the commits into one version of the branch? This operation can be done because the snapshots taken of a branch are ordered as discussed in part 1.
One might wonder what could happen if two (or more) parallel changes are committed to the same part of a file, and how Git resolves this ‘conflict’.

Before we approach that though, I should mention the reverse operation — syncing changes committed to a remote branch to your local working copy. This is a common thing to do when working collaboratively on a branch.
This is done by doing git pull. And as before, this could also result in a ‘conflict’.

Merges — Putting it all together

The ultimate goal of all of this collaborative work on branches is to be able to combine the work of everyone into one branch. Putting the changes committed to a branch on another branch is called merging.

The complete picture.

Because Git knows which changes are more recent, it can put together the commits in the correct order in the destination branch of the merge, assuming it the sequence ‘makes sense’ — putting the combined work together.

But, if the same part of a file has been changed in two different ways we get a merge conflict. In this situation Git does not know how to order the changes (which one is more relevant than the other?) and presents it to the user to resolve manually. You can choose to keep the changes from either branch or keep all changes.

Final words

I hope you enjoyed the two part Git introduction. Source Control, and especially the commonly used Git, has become such an integral part of how we manage versions of our products — working with it is almost a must-have skill. And the more you understand it, the better you will be able to use it to your benefit.

Lior Zisman

Written by

Lior is a Front-End developer at Booking.com. He loves creativity and always up for good, challenging problem solving. And pancakes.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade