Git-Fu Level 1: Red Belt

This is the second part of a three part series on git. For the initial post see here.

In the first “belt”, I have described why one wants to use a CVS system like git: foremost to keep track of the various versions of the files within a code repository (or of some text files, e.g. when writing an article).

In the next level (“red belt”), I will show you the various concepts that help you collaborate with others or when working on several ideas at once. This level should give most people already enough to be productive with git.

Git Log

Before we start with branches, remotes and merging, a small note about git log. In the first part, I have advised to use the command line interface (CLI) as much as possible. However, compared to a graphical user interface (GUI), the CLI comes with no nice log for displaying diverging branches and complicated histories. But the git CLI has a lot of options to tweak this.

Compare the two outputs below. On the left, there is the (truncated) standard output. On the right, the output for my git alias “logall”.

git standard logging and some more useful variant

The standard version is quite verbose and it is difficult understand what is actually going on — especially when branches are involved. Meanwhile with some tweaks, the output can become quite concise and useful.

The git logall command is not a standard command but an alias that can be configured. Simply use the following command to add the alias to your global git configuration file

git config --global alias.logall ‘log --decorate --all --graph --oneline‘

The alias should now appear in your .gitconfig file. If you want to even further tweak the output, have a look at the official documentation.

Branches

Branches allow you to quickly create a “parallel” universe for your code in which you can experiment and fiddle around with new ideas without any danger to corrupt the main version (or rather branch). This main branch is often called the master branch and usually all other branches are based on this master branch. Once you are happy with your changes on your dedicated branch, you can merge it back into the master branch.

You can create a new branch with

git branch <name>

and then you can change to it with

git checkout <name>

You can combine these two steps with

git checkout -b <name>

And that is how you create branches!

Remotes

Git is a truly decentralized code versioning system that lets you have locally everything you need. However, in real life, we often need to integrate the work from various contributors. Or we might maintain a remote copy of a repository as a backup.

Git has the concept of remote repositories (or short remote). The most common remote is often called origin and it is automatically created when you clone (i.e. copy) a git repository.

To list all the remotes use

git remote

and to add a new remote, use

git remote add <name> <url>

All the remotes will be listed in the .git/config file of your repository.

Keep in mind that simply adding a remote does not mean that git will get any information from it. Especially not in the background. You have to manually update the information by running

  git fetch <name>

Merging and Pulling

All those tricks with branches and remotes are futile if git had no merging capabilities. Merging allows you to incorporate back any changes from the remotes into your master branch.

In combination with remotes, the term in git is also to pull which is nothing else than a fetch followed by a merge. Sometimes, it’s best to keep the two steps separate and to only first fetch and then use the logall alias from above (which will also show the branches on the remote) to inspect the situation. Once, it is clear that a merge is safe (or how it needs to be performed), one can execute the merge.

The most common merges are shown in the image below: the fast-forward merge, the three-way merge and the empty merge. The image shows three different scenarios for merging based on the case where a branch called feature/a has been branched off master and is supposed to be merged back into master.

The fast-forward merge is the default if there are no conflict. Basically, the only thing that happens is that the master branch reference is being updated, such that it now points to the same commit as the feature/a branch. In the image above this indicated by the shift of the master branch pointer.

Sometimes, there can be another commit on master since the feature/a branch was created. And it might be in conflict with what is currently on feature/a. In order to complete the merge, the conflict has to be resolved. Either git itself will do it (and it is pretty smart) or one has to resolve all conflicts manually. At the end of the merge, a merge commit will result that contains all those resolutions.

Especially when one has to resolve merge conflicts, in my view, the CLI is clearly superior. Of course it might be helpful to look at the diffs in a graphical interfaces but only the CLI will tell you nicely which conflicts still exist and how to proceed (use git status for that).

The third of the most common merges is in some sense a mix between the first two and it is often seen when using some git hosting services like bitbucket or github. As people get so used to see a dedicated merge commit, these services often create one (called an empty commit) even in the case when a simple fast-forward merge would have done it. This can often be configured in those tools and I would advocate for it as it declutters the git history (compare the left side and the right side in the image above; the state of master at the end should be equivalent).

Red Belt

Congratulations: you have obtained your red belt! Now you can create and merge branches with ease. In the next level, I will show some tricks to rewrite the git history to fix some of the issues that can emerge in more complex collaboration situations. Stay tuned!

Previous
Previous

Git-Fu Level 2: Black Belt

Next
Next

Git-Fu Basics: White Belt