Table of Contents

Introduction

When I started to work in my first company they were changing the Version Control System (VCS) [1] from Apache Subversion (SVN) [2] to Git [3]. I quickly started to become the expert of the company since I was the last joiner and I had the opportunity to spend time learning the basics. I had also the advantage of not knowing other VCSs (like SVN) so I didn’t have a biased vision of how things were supposed to work.

After years of work I have met some people really struggling with it. It is not related to the age, the seniority or the smartness of a person, but using git looks like a binary skill: you either have developed it or not.

With this article I will explain what is, in my opinion, the most important (and often hidden) thing about Git. I hope that by starting with it you will be able to overcome any insecurity and start seeing the value of using Git as a tool that allows you to relax. Not another thing you need to worry about.

The basic configuration

Before beginning our discussion on how to properly learn it, let’s review the basic configurations starting from scratch. You just have installed Git.

In order to be able to create a new commit you need to configure your name and email. Be careful with the email. If you publish your code on a public repository (like GitHub) you might expose a working email and some scammers (or some bot programmed by them) will start sending you unwanted emails. So, unless your code will stay in a private repository of a company, it is advisable to put a fake email or something like “noreply@domain.com”. My configuration is:

git config --global user.name  "BSDrulez"
git config --global user.email "noreply@bsdrulez.neocities.org"

The flag --global tells Git to store that configuration in the global config file of your user in that particular machine ($HOME/.gitconfig on a Unix-like OS). If you remove this parameter it will use the file .git/config in your current project.

Git has been designed to be used from the command line and even if you are not used to using it, it’s better to start learning from there. Then you can move to use a standalone UI or the integration with your favorite IDE. In my experience, if you start from the latter you will be more confused.

That being said the commands of Git can be a little bit too long to type every time, so it is important to take advantage of the autocompletion of the shell (if available) or of the concept of alias (always available because it is built-in in Git). With an alias, we can just type git st in the terminal instead of the long version git status -s. This might seem a little bit overkill, but you are going to love using those aliases.

This is my list (don’t worry if you don’t understand them all right now):

git config --global alias.br "branch"
git config --global alias.st "status -s"
git config --global alias.co "checkout"
git config --global alias.df "diff --raw"
git config --global alias.lo "log --all --oneline --graph --decorate"

The most effective way of learning it: develop a simple project

To learn how to use Git it is better to start practicing with an example. There is no need to involve source code, just regular text files are ok. For this reason, let’s say you want to improve your vocabulary so you want to keep track of words and meanings in a regular text file. Create an empty folder and create a file with your favorite text editor and put some words in it (call the file eng.txt):

house = place where you live
pizza = traditional Italian food (dough, tomato sauce and mozzarella)

Every day you add new words, review the list and correct mistakes. Why would you use Git in the first place? Some initial benefits are:

  • you want to save the state of your project so in case you make unwanted changes you will be able to revert to a previous state
  • you want a convenient method to review the changes you did before saving the state

To tell Git that it must take care of your new project you can open the terminal in your project’s folder and execute git init. This will create the folder .git (hidden by default in Unix-like OS) and some configuration files (like .git/config). Now you have converted the folder of the project into a Git Repository (a local repository just on your laptop). What does it mean? In practice when you run Git commands from this folder the VCS will save your project and its evolution over time in the folder .git. With appropriate commands, you will be able to restore a saved state of your project, jump to another state, show the differences between two states, etc.

We need to be familiar with these concepts:

  • working directory: the content of the project’s folder except for .git and .gitignore
  • commit: a snapshot of the project
  • staging area: changes that are meant to be saved in the next commit

A file in the working directory can be:

  • untracked: the file is in the working directory but we never included it in any commit
  • modified: we have changed the content of a file that was previously saved in a commit (and it is not ready to be saved in the next commit)
  • staged: a file we have flagged to be saved in the next commit
  • ignored: if a file has never been saved in any commit and the file name matches a pattern in .gitignore, Git will pretend this file does not exist

Type git st and check the output:

?? eng.txt

the couple of red question marks (??) means Git is seeing one untracked file in the working directory. Every new file we create will start from the status untracked. Run the following two commands to stage the file and save its content in the new commit.

git add eng.txt
git commit -m "English dictionary - day 1"

Add a new word and repeat the previous two commands changing the number of the day in the commit message (you need to repeat also git add because otherwise git will ignore your new changes). Do it once more so we have simulated our work up to day 3. The content of my file is now:

house = place where you live
pizza = traditional Italian food (dough, tomato sauce and mozzarella)
cat = a popular pet especially among software developers
withdraw = remove from a group or from consideration

You can develop a better understanding of how the status of eng.txt changes when edited, staged and committed by running git st before and after every operation. You should be able to see when a file is modified (a red M in the output of git st) and when it is staged (a green M). After the commit, the status of the working directory is the same as the last commit so the output will be an empty line.

The most important piece of the puzzle

To fully understand Git you need to be able to check the status of the repository and imagine how it changes after every operation. In practice you need to check and understand the tree of commits that is shown by git log --all --oneline --graph --decorate. If you run this command in your project you will see a stream of three commits similar to the following:

* 39cd015 (HEAD -> master) English dictionary - day 3
* 26ea295 English dictionary - day 2
* f62b56e English dictionary - day 1

This is a linear sequence of the three commits we created so far. The sequence is in reverse chronological order therefore the most recent commit is at the beginning. Even though it might not be evident in a simple case like this, the asterisks represent the dots in a graph: the status of a repository. All the rest of the data in the same line help to identify which commit is and a few other details.

Take time to learn in-depth about everything you see in this graph.

Let me explain the main details in our graph:

  • as already said, each asterisk is a commit
  • the hexadecimal value close to the asterisk is an identifier for that commit
  • the rest of the line shows the commit message
  • at the moment you can ignore the words HEAD and master (they will be explained in detail in the next article)
  • in more complicated graphs, you will see some connections between the asterisks
  • the connections represent the relationships between the commits: internally Git saves only the changes between states so the graph is its internal map to rebuild the full status of a project at a given commit
  • when there is no connection between two asterisks it means the upper is a child of the lower; if all the connections were shown the graph would be:
* 39cd015 (HEAD -> master) English dictionary - day 3
|
* 26ea295 English dictionary - day 2
|
* f62b56e English dictionary - day 1
  • HEAD tell us what is the current commit (a new commit will be a child of this one)
  • master is the name of a local branch (ignore this at the moment)

In case you haven’t guessed it, yes, you can use the handy short command git lo to display the same graph (thanks to the alias we defined at the beginning of this article). This graph is so useful that I don’t know why there isn’t a simple command already implemented.

To practice your understanding proceed with the following exercise:

  • create a new folder for a new project
  • open the shell in the folder
  • initialize the git repository: git init
  • before and after every command check the status of the repo with: git st and git lo
  • create/edit/save a text file

For example:

git init
git st
git lo
# create a text file called newfile.txt
git st
git lo
git add newfile.txt
git st
git lo
git commit -m "add first text file"
git st
git lo
# edit the content of newfile.txt
git st
git lo
git add newfile.txt
git st
git lo
git commit -m "added/modified content to text file"
git st
git lo

Running git st and git lo like that looks a little bit pedantic, but it is a very effective way of understanding how git works.

To verify your understanding, the next exercise is to guess what will be the output of git st and git lo before running it:

  • in the same project as the previous exercise, create a new file
  • try to guess what will be the output of git st
  • run git st
  • guess the output of git lo
  • run git lo
  • edit the first text file (created in the previous exercise)
  • make your guess and then run git st
  • do the same for git lo
  • continue like that with different combinations of the following operations
    • add a file with git add
    • edit one of the files
    • create a commit

Conclusions

Let me break here for today. In this article we saw how to start using Git and how we can learn step by step with a simple exercise. In the next articles we will talk about branches, how to jump from one state to another, how to check the differences and much more.

That being said the most important piece of the puzzle is to start understanding the commit’s graph shown by git lo. Start using git st and git lo before and after every operation. Then challenge yourself and try to guess what is the output of the command before running it. When you are able to foresee the changes to the graph in your head you will have mastered Git. In the following articles we explain the graph even further and we will add new pieces of it.

References

[1] https://betterexplained.com/articles/a-visual-guide-to-version-control

[2] https://subversion.apache.org

[3] https://git-scm.com