Sitemap

Git Internals: Part 2

6 min readJun 29, 2026

--

Commits, Branches & Git History

In Part 1, we saw what actually happens when you run git init, and how a file moves from Untracked → Staged → Committed.

We ended with this:

[main e62081a] Completed feature

And I asked — what do main and that strange string of characters actually mean?

That question is exactly where Part 2 begins.

Press enter or click to view image in full size

What Is a Commit, Really? A commit is not “a copy of the files you changed.” That’s the mental model most of us start with, and it’s the one that causes confusion later.

A commit is a snapshot of your entire project at that moment, plus some metadata about it — who made it, when, why, and what came before it.

Every commit stores:

  • A pointer to the snapshot of your project’s files
  • The author and committer details
  • A commit message
  • A pointer to its parent commit (the commit that came right before it)

That last point is the important one. Each commit knows which commit came before it. String enough of these together, and you get something that looks less like a list of saves and more like a chain.

Press enter or click to view image in full size

This chain is what lets Git answer questions like “what did this file look like three commits ago?” — it just walks backward along the chain.

The Commit Hash So what is e62081a?

It’s not random, and it’s not a counter like commit #1, #2, #3.

It’s a SHA-1 hash — a 40-character fingerprint generated from the commit’s content: the snapshot it points to, the parent commit, the author, the timestamp, and the message. Git just shows you a shortened version of it in the terminal.

Because the hash is generated from the content, two important things follow:

  • If even one character of the commit’s content changes, the hash changes completely.
  • The same content will always produce the same hash, no matter whose machine it was committed on.

This is why Git doesn’t need a central server to assign commit numbers. Every commit identifies itself.

Press enter or click to view image in full size

git log Now that we know commits are chained together, how do we actually see that chain?

git log

This walks backward from your current commit, through every parent, and prints the history — newest first.

Press enter or click to view image in full size

A typical entry looks like this:

commit e62081a9f3c1b8d4a7e2f0c9b6d5a4f3e2d1c0b9
Author: Aarthi Honguthi <aarthi@example.com>
Date: Mon Jun 29 10:42:11 2026 +0530
    Completed feature

Notice that each commit lists its own hash, but not its parent’s hash directly in this view. That parent link still exists underneath — git log is just choosing to display it as a friendly chronological list instead of a raw chain.

If you ever want to see the chain shape itself, git log --oneline --graph draws it out as a literal graph of dots and lines.

What Is HEAD? You’ve probably seen HEAD mentioned in Git output without a clear explanation of what it actually is.

Get Aarthi_Honguthi’s stories in your inbox

Join Medium for free to get updates from this writer.

HEAD is simply a pointer to whichever commit you currently have checked out — your "you are here" marker in the project's history.

Most of the time, HEAD doesn't point directly to a commit. It points to a branch, and that branch points to a commit.

HEAD → main → e62081a
Press enter or click to view image in full size

This indirection is the whole reason branches in Git are so lightweight, which brings us to the next question.

What Is a Branch? Here’s the idea that took me the longest to actually believe, even after using Git for a while:

A branch is not a copy of your project. It is not a folder. It is not a separate set of files sitting somewhere.

A branch is just a pointer to a commit.

That’s it. A small file, 41 bytes long, sitting inside .git/refs/heads/, containing nothing but a commit hash.

Press enter or click to view image in full size

Why main Is Just a Pointer When you run git init, Git creates a default branch — usually named main — which starts out pointing at... nothing, because there are no commits yet.

The moment you make your first commit, main updates to point at that commit. Make another commit, and main moves forward to point at the new one.

Press enter or click to view image in full size

This is why creating a branch in Git is almost instant, while in some other version control systems it can take a while — Git isn’t duplicating any files. It’s writing a single new pointer file.

git branch To create a new branch:

git branch feature-login

This creates a new pointer named feature-login, pointing at whatever commit HEAD currently points to. Your working files don't change. HEAD doesn't move. You've just added a second name for the same point in history.

Note: In the output of git branch, the * indicates your current branch. Since HEAD points to the branch you're currently working on, * main effectively means HEAD → main.

git switch / checkout Creating a branch doesn’t move you onto it. To actually start working from that branch, you switch to it:

git switch feature-login

(You’ll also see git checkout feature-login used for this in older tutorials and existing codebases — switch was introduced later specifically to make this action clearer, since checkout used to handle several unrelated jobs at once.)

What actually happens here is simple: HEAD stops pointing at main and starts pointing at feature-login instead.

Before:  HEAD → main          → e62081a
After: HEAD → feature-login → e62081a
Press enter or click to view image in full size

Now, if you make a new commit while on feature-login, only feature-login moves forward to point at it. main stays exactly where it was.

Press enter or click to view image in full size

This is the entire trick behind branching in Git: multiple lightweight pointers, each free to move independently, all pointing into the same shared history of commits.

Putting It Together

  • A commit is a snapshot plus a pointer to its parent.
  • A commit hash is a fingerprint of that commit’s content — not a counter.
  • git log walks the chain of parent commits to show you history.
  • HEAD points to whatever you currently have checked out — usually a branch.
  • A branch is just a small file containing a commit hash, nothing more.
  • git branch creates a new pointer; git switch moves HEAD to point at it.

If branches are just pointers, how do they come together? → Merge

--

--

Aarthi_Honguthi
Aarthi_Honguthi

Written by Aarthi_Honguthi

Exploring the world of code, one byte at a time