2026.03.20 / 6 min read

git is not about the commands

a version control system that starts making sense once you stop memorising it. start thinking about what it's actually doing.

today started with something i've technically "used" before.

git.

but if i'm being honest, most of that usage was mechanical. copy commands. push code. hope nothing breaks. and the moment something did break, things got confusing fast.

so instead of just memorizing commands again, i tried to understand what git is actually doing under the hood. that's when it started to click.

git is basically time travel for code

imagine building something and being able to say: "take me back to how things were 2 hours ago."

that's exactly what git enables. every time you commit, you're creating a snapshot of your project at that point in time. not just saving files, but saving state.

so instead of thinking: "git stores code" — it's more accurate to think: "git stores versions of my thinking over time."

quick check — what does a git commit actually store?

git vs github. not the same thing

this tripped me up early.

git is the system that lives on your machine. it tracks every change, lets you go back to older versions, and helps you experiment without breaking things.

github is where you put that project online. backup, sharing, collaboration.

local (your machine) ←→ remote (GitHub) push → send changes up pull → bring changes down

two different things. git is the tool. github is the place.


alright. let's start with actually getting git on your system. none of this works without it installed.

saving isn't the same as committing

the thing that confused me early on was the step between "i made a change" and "i saved it to git." you have to stage it first.

working directory → staging → commit → push

staging is where you decide what actually goes into the snapshot. it seems annoying at first. but it exists so you can commit only the things that belong together, not everything you touched in the last three hours.

so a commit isn't just a save. it's a snapshot you chose to take.

the commands you'll use every single day

before anything else. these are the only commands you need to get started. everything else comes later.

git init                    # start a repo from scratch
git clone <url>             # copy an existing repo

git status                  # what changed
git add .                   # stage everything
git commit -m "message"     # save a snapshot

git push                    # send to github
git pull                    # bring latest down

that's it. that's most of git for daily use. if you get comfortable with just these, you're already ahead of a lot of people who've been "using" git for years.

branches are pointers, not copies

this one took me a while to get right in my head.

when you create a branch, git doesn't duplicate the codebase. it creates a pointer to the same commit you're already on.

main → A → B → C feature → A → B → C

both point to the same place. the moment you commit on feature, they diverge. no copying, no extra storage for the same files.

same codebase. very different mental model.

git creates a new pointer called "feature" pointing at the exact same commit HEAD is on right now. no files are copied. no folders are duplicated. it's just a label that moves forward independently from here. that's it.

HEAD is just where you are

A → B → C → D ↑ HEAD

HEAD is your current position in the commit history. HEAD~1 is one step back. that's it.

once you know this, commands like git reset --soft HEAD~1 stop looking scary. you're just moving where you're standing.

what does HEAD~2 mean?

stash is a pocket, not a drawer

git stash saves unfinished work temporarily without making a commit out of it. useful when something urgent comes up and you need to switch context without making a messy commit just to clean your working directory.

git stash pop brings it back. temporary storage. not filing something away. just holding it for a second.

rebase vs merge

merge combines histories. rebase rewrites them so they look linear.

neither is wrong. rebase makes the git log cleaner. merge preserves the actual sequence of events. which one you use depends on what your team prefers or what the history needs to look like.

never rebase commits that have already been pushed to a shared branch. rebase rewrites history. if someone else has pulled those commits, you'll create diverging histories and cause merge conflicts for the whole team. on your own local branches: rebase freely. on shared branches: merge.

a mistake that's easy to fix

committed to the wrong branch. it happens to everyone.

git checkout -b correct-branch  # move to right branch
git checkout wrong-branch
git reset --hard HEAD~1         # undo on wrong branch

or the safer route. if others might have already pulled:

git revert HEAD

revert doesn't erase history. it adds a new commit that undoes the last one. less violent than reset for shared branches.

the commands when things get complex

once the basics feel natural, these are what you reach for:

git log                       # full commit history
git diff                      # see exactly what changed

git reset --soft HEAD~1       # undo commit, keep changes
git reset --hard HEAD~1       # undo commit, delete changes

git stash                     # save work temporarily
git stash pop                 # restore it

git rebase main               # reapply commits cleanly
git commit --amend            # edit the last commit

git restore file.txt          # discard file changes
git restore --staged file.txt # unstage a file

git blame file.txt            # who changed what line

you don't need to memorise these. you need to know they exist so when something breaks, you know what to search for.

the commands are just how you tell git to move things around. once the mental model clicks — versions, pointers, snapshots — the rest follows naturally.

but if you think you've got git figured out now —

so you think you know git? →
← back to blogs