Git Crash Course
This is the learning path for people new to Git. It follows a single story — create a repo, make commits, branch, push, and open a pull request — in the order you actually do them, with just enough explanation to keep moving. The four Git pages fit together as:
- This page (Crash Course) — a guided first walkthrough; read it top to bottom.
- Git Version Control — how Git works under the hood (objects, the DAG, internals).
- Git Command Reference — the alphabetical lookup cheat sheet for every command.
- Branching Strategies — team workflows: Git Flow, GitHub Flow, trunk-based.
Why version control?
Before Git, people emailed report_final_v2_REALLY_final.docx around. Version control replaces that chaos with a single source of truth that remembers every change, who made it, and why — and lets many people work in parallel without overwriting each other. The payoff is threefold: a full history where every saved version is recoverable forever, collaboration where many people edit the same project safely, and safe experiments you can try in a branch and throw away if they fail.
The mental model: three areas
Almost every Git command moves your work between three places. Internalize this picture and the commands stop feeling random.
flowchart LR
WD["Working Directory<br/>(files you edit)"] -->|git add| STAGE["Staging Area<br/>(what goes in next commit)"]
STAGE -->|git commit| REPO["Local Repository<br/>(.git history)"]
REPO -->|git push| REMOTE["Remote<br/>(GitHub / GitLab)"]
REMOTE -->|git pull / fetch| REPO
REPO -->|git checkout| WD
| Area | What it holds | You change it with |
|---|---|---|
| Working Directory | The actual files on disk you are editing | Your editor |
| Staging Area (Index) | The exact snapshot you are about to commit | git add |
| Local Repository | The committed history on your machine | git commit |
| Remote | The shared copy others pull from | git push |
Step 1 — One-time setup
Tell Git who you are (this stamps every commit) and pick sensible defaults.
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main # name the first branch "main"
git config --global pull.rebase false # default merge behavior on pull
Check it worked:
git config --list
Step 2 — Start a repository
You either create a new one or clone an existing project.
# Option A: brand-new project in the current folder
git init
# Option B: copy an existing project from a remote
git clone https://github.com/owner/repo.git
git init creates a hidden .git/ directory — that folder is your repository (the history database). Delete it and you delete the version control, not the files.
Step 3 — The core loop: edit → add → commit
This is the cycle you will repeat thousands of times.
# 1. See what changed
git status
# 2. Stage the changes you want to save together
git add file1.py file2.py
git add . # stage everything that changed
# 3. Save a snapshot with a message explaining WHY
git commit -m "Add login form validation"
What makes a good commit? One logical change per commit, with a message written in the imperative mood (“Add”, “Fix”, “Remove” — not “Added”/”Fixing”). Keep the first line under ~50 characters. Future-you reading git log will thank present-you.
Inspect your history any time:
git log --oneline --graph # compact, visual history
git diff # changes you have NOT staged yet
git diff --staged # changes that ARE staged for next commit
Step 4 — Branching: work without breaking things
A branch is a cheap, movable pointer to a commit. Create one per feature or fix so main always stays stable.
git switch -c feature/login # create and switch to a new branch (Git 2.23+)
# ...edit, add, commit as usual...
git switch main # jump back to main
git switch feature/login # and back to your work
gitGraph
commit id: "init"
commit id: "homepage"
branch feature/login
checkout feature/login
commit id: "add form"
commit id: "validate"
checkout main
commit id: "fix typo"
merge feature/login
commit id: "release"
git switchandgit restore(Git 2.23+) are the modern, clearer replacements for the overloadedgit checkout. You will still seecheckouteverywhere — it does both jobs.
Step 5 — Share your work: push and pull
origin is the conventional name for your main remote. The first push sets up tracking with -u.
# Push your branch to the remote for the first time
git push -u origin feature/login
# Later pushes on the same branch are just:
git push
# Bring down changes others have pushed
git pull
sequenceDiagram
participant You as Your machine
participant GH as GitHub (remote)
participant Team as Teammate
You->>You: edit + git commit
You->>GH: git push
GH->>Team: git pull
Team->>GH: their commits (git push)
GH->>You: git pull (get teammate's work)
Step 6 — Open a pull request
A pull request (PR) — called a merge request on GitLab — proposes merging your branch into main. It is where review, automated tests, and discussion happen before code lands.
- Push your branch (Step 5).
- On GitHub/GitLab, open a PR from your branch into
main. - Teammates review; CI runs tests automatically.
- After approval, merge — your work is now in
main. - Delete the branch; pull
mainlocally to stay current.
# Using the GitHub CLI from the terminal
gh pr create --fill
gh pr status
See Branching Strategies for how teams structure this at scale.
The 12 commands that cover 90% of daily work
| Command | What it does |
|---|---|
git status |
What changed, what’s staged |
git add <file> |
Stage changes |
git commit -m "msg" |
Save a snapshot |
git log --oneline |
View history |
git diff |
See unstaged changes |
git switch -c <br> |
New branch |
git switch <br> |
Change branch |
git merge <br> |
Combine branches |
git pull |
Get remote changes |
git push |
Send your commits |
git stash |
Shelve work temporarily |
git restore <file> |
Discard local edits |
“Oh no” — fixing common mistakes
Everyone breaks something early on. These get you out of the most common holes safely.
| Situation | Fix | Notes |
|---|---|---|
| Committed too early / wrong message | git commit --amend -m "Better message" |
Rewrites the last commit. Don’t amend commits you’ve already pushed and shared. |
| Undo last commit but keep the code | git reset --soft HEAD~1 |
Removes the commit, leaves the changes staged so you can recommit. |
| Drop everything since the last commit | git restore . |
Discards uncommitted edits — destructive, make sure you mean it. |
| Mid-task, need to switch branches | git stash → git switch other → git stash pop |
Shelves your work-in-progress and brings it back later. |
| Think I lost a commit | git reflog |
Shows where HEAD has been; almost nothing is truly gone. Check out the hash to recover it. |
Handling merge conflicts (the calm version)
A conflict just means two branches changed the same lines. Git pauses and asks you to choose.
git merge feature/login
# CONFLICT in app.py
Open the file; Git marks the clash:
<<<<<<< HEAD
greeting = "Hello"
=======
greeting = "Hi there"
>>>>>>> feature/login
Edit the file to the version you want, delete the <<<<<<</=======/>>>>>>> markers, then:
git add app.py
git commit # completes the merge
If it goes sideways, git merge --abort returns you to safety.
Where to go next
- Understand the machinery — read Git Version Control for the object model, the commit DAG, and how SHA hashing guarantees integrity.
- Look up a command — keep Git Command Reference open as your cheat sheet for rebase, cherry-pick, bisect, and more.
- Work on a team — pick a workflow in Branching Strategies and wire it into CI/CD.
Key Takeaways
- Three areas: working directory → staging (
add) → repository (commit) → remote (push). - The core loop is edit →
add→commit, repeated endlessly with clear messages. - Branch for every change so
mainstays stable; merge via pull requests. - Almost nothing is unrecoverable —
git reflogandgit resetare your safety net. - A dozen commands cover the vast majority of daily work; learn the rest as you need them.
References
- Pro Git Book — free, comprehensive, beginner-friendly
- GitHub Skills — interactive hands-on exercises
- Official Git Documentation
- Conventional Commits — a popular commit message convention