Skip to content


Skip to the problems!

What's Git and why should I care?

Imagine you're writing a program.. At the beginning, it's small and minimalistic, but it runs without error.
class Calculator:

    def add(self, a, b):
        return a + 1

Then you decide you want to add a complicated, experimental feature . Your program starts to grow in size and complexity.
class Calculator:

    def add(self, a, b):
        return a + 1

    def is_prime(self, x):

As you're implementing this new feature, you find and fix a few bugs related to your initial program.
class Calculator:

    def add(self, a, b):
        return a + b

    def is_prime(self, x):
        # Oof this is hard..

As time goes on, you realize this experimental feature was a mistake ๐Ÿคฆโ€โ™‚๏ธ. At this point, you want to ditch the experimental feature and revert your code back to how it was originally. But not entirely.. you'd like to keep some of the bug fixes you implemented.

For a large codebase with major changes, doing this without a version control system can be a nightmare. With Git, you can save your code at various "checkpoints", and then revert your code to how it was at any of your saved checkpoints.

You can also branch your project, allowing you to work on multiple features independently of each other and merge those branches such that the code for feature A doesn't overwrite or conflict with the code from feature B.

Confused? ๐Ÿ™‹โ€โ™‚๏ธ

Don't worry, these things will make more sense once you start practicing! ๐Ÿ˜‰

How it works (the basics)

Git lets you track changes to a project (directory) and all its contents by saving the state of your project at various "checkpoints".


Suppose you have a project like this..


Initializing a Git repo

You can set up a Git repository (repo) for your project using the git init command.

bill@gates:~$ cd path/to/my-project
bill@gates:~$ git init
Initialized empty Git repository in /path/to/my-project/.git/

This inserts a hidden directory named .git/ in the root of your project.


.git/ is where the saved "checkpoints" of your project live.

Committing your code

How do I save a new checkpoint of my project?

Git calls these "checkpoints" commits. To make a new one,

  1. stage your new and changed files using git add
  2. then commit the staged files with git commit

Are you running these commands on your machine?

Don't. Some of these commands won't even work without including additional parameters!

Now's the time to understand the high-level concepts. The time to learn syntax comes when you get to the practice problems.

The commit graph

You can visualize each commit as a node in a graph. The first time you commit your code, it's like creating a graph with one node.


With each commit (saved checkpoint), a new node appears connected to the previous node.


Some of you may recognize this as a Directed Acyclic Graph (DAG).
(In this example, each child points to its parent.)

Graphs can even split into multiple branches allowing you to test two or more features from a common starting point.


We'll discuss branches in more detail later.

Working Tree

Your working tree refers to the project you can see ๐Ÿ‘€ and edit on your filesystem. For example, suppose your initial project looks like this


You commit your files and then you delete foo.txt.

  foo.txt  <-- delete this abomination!

Now your working tree looks like this

working tree

Fear not. foo.txt is not gone forever. It still lives in the commit graph, contained in your first commit! ..but it's not part of the working tree. In other words, the working tree is all the stuff you can see when you look inside my-project/ on your computer.

Staging Area

The staging area will make more sense when you solve this problem, but in short, staging is an intermediate place to move your changes before inserting them into the commit graph.


The staging area lets you commit just some of your changes. Without staging, you'd have to commit all of your changes at once!