Headers examples
Introduction
I used Git for the first time around 2010 and let me tell you: I hate it. Notice that I didn't write "I hated it", as in "I hated it at the time but then I ended up loving it". Rather "I hate it", present tense, as in "I hate Git right now". I hated Git back then, and I still do today more than 10 years later.
If I start this tutorial this way is because I want to make something crystal clear from the very beginning: unlike other tutorials, this one acknowledges that Git is hard. And every time you feel overwhelmed and start wondering whether it's you who doesn't understand something that everybody claims to be easy, I want you to take a deep breath, relax, and remember: It's not you, it's them.
I wrote this tutorial because I wanted to focus on the type of people who don't want to learn Git but have to do it anyway. Perhaps you are migrating away from Subversion, or maybe you are a data scientist who works with the type of programmers who find the above tweet funny. Whatever the reason, this tutorial is aimed at people like you.
So, what is Git anyway?
Git is a distributed version control system. Borrowing from this definition, Git is a tool programmers use to keep track of who wrote what and when, to ensure that multiple programmers can work on the same file at the same time, and to restore old versions of files when someone makes a mistake. That's all there is to it.
Why is Git hard?
As a tool developed by programmers for programmers, Git expects you to be familiar with problems that are moderately difficult for people with a Computer Science degree and really difficult for everyone else: dealing with state, dealing with indirection, and naming things. In fact, one of those problems is so particular to Computer Science that it has been used as the programmer aptitude test for the last 20 or 30 years (if you follow that link, search for "15 years of experience" for the relevant part). Let's talk about them briefly.
"Dealing with state" means interacting with a system that interprets your orders in one way or another depending on its internal state. Think of an elevator: if someone calls it from the last floor before you do, there's a good chance that the elevator will pass through your floor without stopping for you because its internal state told it that it was already committed to a floor and is not accepting new requests until it's done. And while we understand why the elevator did what it did when we look at the complete state, from a single person's point of view it looks as if the elevator ignored a request just out of spite. Git is very strict when it comes to which actions can be executed when, and getting into this "Git mindset" is something we'll deal with in this tutorial.
A second difficult task for humans is dealing with indirection: instead of talking about a thing, you talk about a different thing that points to the original thing. A typical example is a person's name: when we talk about "Richard" we are using an indirection that refers to a specific, flesh-and-bone person. And if you are like me, you may know exactly who a person is, picture their face, know where you've seem them before... but you still have trouble remembering their name. When working with Git, the thing you care about (namely, files) are wrapped in multiple layers of indirection such as "version" or "branch". This tutorial will teach you how to see through these layers by constantly stopping to explain what's happening behind the curtains.
And finally: when it comes to giving understandable names to things, Git doesn't even try. Git identifies different stages of your project using a (semi) random string of characters, and if you want something better then it's up to you to label them appropriately.
None of these problems is impossible to get through - in fact, programmers (it's always programmers) will often praise how easy working with Git is. And there's something to it: once you understand why Git is doing what it's doing, getting it to do what you need gets a lot less frustrating.
Contents of this tutorial
This tutorial is divided into five Parts.
- Part 1 introduces you to keeping track of different versions of a file. In our example, that will be a recipe for poached eggs.
- Part 2 explains how to share your work with people over the internet and work in parallel. Following our example, we'll see how two cooks can work together on the same recipe.
- Part 3 explains what to do when two users modify the same file at the same time. That means: what to do when one cook adds mustard to a recipe while the other one lowers the temperature.
- Part 4 explains how to keep parallel versions of a file. In our recipe example, that means keeping a version of the recipe without salt.
- Part 5 explains how to recover older versions of your files plus some esoteric commands that you shouldn't need in your daily work.
Acknowledgements
This tutorial was inspired by Joel Spolky's HG Init tutorial for Mercurial, a version control system that used to compete with Git.