Git

Git Essentials: Version Control That Finally Makes Sense

The mental model behind Git — repository, staging area, branches — plus the daily command loop, practiced on a real repository you build as you read.

Gitversion controlcommand linebeginnerdeveloper tools

Tutorial overview

What you will learn

  • Explain the three zones of Git: working directory
  • staging area
  • repository
  • Run the daily loop — status
  • add
  • commit — without thinking
  • Create
  • merge
  • and delete branches confidently
  • Connect a local repository to a remote and push/pull
  • Undo mistakes at each stage without fear

By the end, you will have

  • A practice repository with real history
  • a merged branch
  • and an undone mistake
  • A daily Git routine you can run on autopilot
  • The vocabulary to read Git documentation and error messages

Introduction

Git tracks every version of your work, lets you experiment without fear, and is the collaboration backbone of essentially all modern software. It is also famously confusing to learn from error messages alone — because Git only makes sense once you hold its mental model, and most people are handed commands before the model.

This tutorial does it in the right order: model first, commands second, practiced on a real repository you'll build as you go. If you're returning after time away, the model is the part that comes back — skim Steps 1–2 and the muscle memory follows.

What you will build or practice

A real repository with meaningful history: several commits, a branch you create and merge, a remote-ready setup, and — most importantly — a mistake you make on purpose and then undo. Fear of breaking things is the main thing that keeps people from using Git well; we remove it deliberately.

Before you begin

Install Git from git-scm.com (every OS has an installer; on Ubuntu/WSL it's sudo apt install git). Then introduce yourself — Git stamps every commit with this identity:

git config --global user.name "Your Name"
git config --global user.email "you@example.com"

Key concept

Git moves your work through three zones.

  1. The working directory — your files as they are right now, on disk.
  2. The staging area — a loading dock where you assemble the next snapshot. git add puts changes here.
  3. The repository — the permanent history of snapshots. git commit seals whatever is on the loading dock into it.

Almost every beginner confusion dissolves against this picture. "Why didn't my change get committed?" — it was never staged. "What does git status show?" — the difference between the three zones. A commit is just a sealed snapshot with a message, an author, and a pointer to its parent — history is a chain of them. A branch is nothing but a movable label pointing at one commit. That's the whole model.

Step 1: Make a repository and read git status

mkdir git-practice && cd git-practice
git init
git status

git init creates a hidden .git folder — that is the repository; delete it and the folder becomes ordinary files again. git status is Git's dashboard and your most-typed command: it always tells you what zone everything is in and usually suggests the next command. When in doubt, run it.

Step 2: The daily loop — status, add, commit

Create a file and walk it through the zones:

echo "# Recipe collection" > README.md
git status                      # "untracked" — Git sees it, isn't tracking it
git add README.md               # onto the loading dock
git status                      # "changes to be committed"
git commit -m "Add project readme"
git status                      # clean — all three zones agree

Now change the file and go around again:

echo "## Pasta" >> README.md
git add README.md
git commit -m "Start the pasta section"
git log --oneline               # your history, one line per commit

That loop — edit, add, commit with a message that says why — is 80% of daily Git. Two habits worth forming now: run git diff before staging to see exactly what changed, and keep commits small enough that the message can be honest.

Step 3: Branches — cheap experiments

A branch lets you work on something risky while the main line stays untouched:

git switch -c desserts          # create a branch and move onto it
echo "## Tiramisu" >> README.md
git commit -am "Add tiramisu"   # -a stages tracked-file changes in one go
git switch main                 # look: README has no tiramisu here
git switch desserts             # and now it does again

Nothing was copied — a branch is a label, so creating one is instant and free. This is Git's superpower: every idea, fix, or experiment gets its own branch, and abandoning a bad idea is just deleting a label.

Merge it back when it's ready:

git switch main
git merge desserts              # bring the branch's commits into main
git branch -d desserts          # delete the label; the commits remain

If both branches changed the same lines, Git stops and asks you to resolve a conflict — it marks the competing versions in the file with <<<<<<< markers, you edit the file to keep what's right, then git add and git commit. Conflicts feel alarming and are actually just Git refusing to guess.

Step 4: Remotes — your repository, elsewhere

Everything so far lives on your machine. A remote is a copy of the repository somewhere else — GitHub, GitLab, Bitbucket — used for backup and collaboration:

git remote add origin <url-from-your-hosting-service>
git push -u origin main         # first push; -u links the branches
git push                        # every push after that
git pull                        # fetch others' commits and merge them in

origin is just the conventional nickname for your main remote. The rhythm with others is: pull before you start, work in small commits, push when tests pass. One naming note: git init still names the first branch master by default, while the big hosting services use maingit config --global init.defaultBranch main makes your local default match.

Step 5: Undo — the fear removal step

Make a mistake on purpose:

echo "TERRIBLE IDEA" >> README.md

Now undo it at each zone, matching the command to where the change lives:

  • Not staged yet: git restore README.md — the file snaps back to the last commit. (The change is gone for good, so this is the one to double-check.)
  • Staged but not committed: git restore --staged README.md — pulls it off the loading dock; the edit stays in the file.
  • Committed: git revert HEAD — creates a new commit that undoes the last one. History stays intact, which is why this is the safe choice on anything already pushed.
  • Committed the wrong message a second ago: git commit --amend -m "Better message" — fine locally, avoid on pushed commits.

The deeper reassurance: anything ever committed is very hard to truly lose. git reflog lists everywhere your branches have pointed, even "deleted" commits — it has rescued every developer you admire at least once.

Practice exercise

  1. The task: in a fresh folder, create a repo for a fictional blog. Make three commits on main (add a post, edit it, add a second post). Create a branch redesign, change something, merge it back, delete the branch. Then revert the merge commit.
  2. Expected output: git log --oneline shows the whole story, ending with a revert commit.
  3. One hint: after the merge, git log shows the merge commit at the top — git revert HEAD may ask which parent to keep; git revert -m 1 HEAD keeps main's side.
  4. Stretch goal: create a free account on a hosting service, add it as a remote, and push. Your practice repo is now backed up off your machine.

Common mistakes

  • Editing and wondering why commits are empty. You skipped add. The loading dock is never optional — git status would have told you.
  • Giant commits with messages like "stuff" or "fixes". A commit should be one change with a message stating why. Future-you reading git log is the customer.
  • Working directly on main for everything. Branches are free. The habit of branching per task is what makes experiments — and collaboration — painless.
  • Reaching for deletion when Git gets confusing. Deleting the folder and re-cloning "works," but every such moment is a missed lesson; git status plus the undo table above resolves nearly all of them.
  • Committing secrets. Passwords, API keys, and .env files must never enter history — once pushed, treat a leaked key as compromised and rotate it. A .gitignore file (list filenames/patterns, one per line) keeps them out; add it in your first commit.

Check your understanding

  1. Name the three zones and the two commands that move work between them.
  2. Why is git revert safer than deleting commits on a branch others have pulled?
  3. Your teammate says "my change vanished after I ran git restore." What happened, and which zone was the change in?

Key takeaways

  • Git is three zones: working directory → (add) → staging area → (commit) → repository.
  • git status is the dashboard; when confused, run it and read what it says.
  • Branches are movable labels — instant, free, and the right home for every experiment.
  • Remotes add backup and collaboration: pull before working, push when green.
  • Every zone has an undo, and committed work is almost impossible to truly lose. Fear is optional.

Next steps

Keep the Git Commands Cheat Sheet open until the loop is automatic — it compresses this tutorial and adds the next tier (stash, log archaeology, tag). Then make it real: spin up a project starter, git init, and build the history habit on an actual project.

Related resources

Newsletter or next lesson

The developer-tools lane is growing — browse all tutorials for the current set, one clear step at a time.