Free lab Real Python 3. Zero installs. Your code stays in this browser. Open the playground

Mini Git: Version Control from Scratch

Rebuild the core of Git: content-addressed blobs hashed exactly like Git hashes them, commits chained by parent, line diffs, and branches that are nothing more than named pointers.

Advanced 4 steps 180 XP ~65 min

How it works in the real world

Git looks complicated from the outside and is beautifully simple inside:

  1. Blobs: every file's content is stored under the SHA-1 hash of that content, so identical files are stored once and any change produces a new id.
  2. Commits: a commit records a snapshot (which blob each file points to), a message and its parent commit, and is itself identified by a hash.
  3. History: git log just follows parent pointers backwards.
  4. Branches: a branch is a name pointing at one commit. Committing moves the pointer.

Your step 1 hashes match real Git byte for byte: run git hash-object on the same content and compare.

Build progress0 / 4 steps
1

Content-addressed blobs

Git hashes a file as sha1(b"blob " + size + b"\0" + content). Write hash_blob(text) and print the first 10 hex characters for each file, then whether two files with identical content share a blob.

Blank · autosaved
PYstep_1.py
Run your code to check this step…
2

Commits and history

Write commit(files, message, parent): store each blob in OBJECTS, build a tree of name -> blob id, hash tree + parent + message into a commit id and store the commit. Make three commits, then print a log (newest first) by following parents.

Blank · autosaved
PYstep_2.py
Run your code to check this step…
3

Line diffs

Show what changed between two versions of a file with difflib.unified_diff, labelled a/app.py and b/app.py (pass lineterm=""), then print a summary in Git's format: 1 file changed, N insertions(+), N deletions(-).

Blank · autosaved
PYstep_3.py
Run your code to check this step…
4

Branches are just pointers

Add BRANCHES and HEAD. commit_on(branch, files, message) commits with the branch tip as parent and moves the branch. Create main with two commits, branch feature from it, commit on both, then print each branch's history as message <- message <- ... and the commit they share.

Blank · autosaved
PYstep_4.py
Run your code to check this step…

Take it further

Make it a real command-line tool that stores objects on disk, just like the .git folder. Nothing below is graded: it runs on your own machine, not in this tab.

Stretch goals

  1. Write each object to .minigit/objects/ab/cdef... compressed with zlib, exactly as Git does, then read one back with git cat-file -p to prove it matches.
  2. Add a three-way merge: compare both branch tips against the merge base and flag lines changed on both sides as conflicts.
  3. Build status: hash the working directory and compare it with the last commit's tree.
  4. Use argparse to expose init, commit -m, log and diff subcommands.

Check your hashes against real Git

# In any terminal with git installed:
printf 'print(\x27hello\x27)\n' | git hash-object --stdin

# In Python, the same id:
import hashlib
data = b"print('hello')\n"
print(hashlib.sha1(b"blob %d\0" % len(data) + data).hexdigest())

Ask an AI to review your build

I rebuilt the core of Git in Python: content-addressed blobs hashed like git hash-object, commits chained by parent, unified diffs and branches as pointers. Here is my code: [paste it]. Explain what real Git does differently in its tree objects and commit format, and outline how I would implement a three-way merge with conflict markers.

Your next ten minutes

Write Python that does something useful.

Start free. No install, no card, no passive video marathon.

Start learning free → Explore the path