Git basics
Status: π© COMPLETE Last updated: 2026-06-20 Plain-English tagline: The mental model and the 15 commands that cover 95% of day-to-day Git work.
In plain English
Git is the tool you use to track changes to your code over time. It was created by Linus Torvalds in 2005 to manage the Linux kernel (he was unhappy with the existing tools). Today itβs used by virtually every software project on the planet.
Git is a command-line tool β you run commands like git commit, git push, git pull. There are GUIs (VS Codeβs Git panel, GitHub Desktop, Tower, Fork) that wrap the commands, but understanding the underlying commands matters because thatβs what tutorials, error messages, and Claude Code will speak in.
The good news: you can do 95% of daily work with about 15 commands. This entry covers those.
Why it matters
You canβt really work on modern software without Git. Tutorials assume Git. Hosting providers (Vercel, Netlify) assume Git. Collaboration assumes Git. Even your AI assistant assumes Git.
The depth Git rewards is real β there are hundreds of commands and many edge cases β but the bar for βcompetent enoughβ is much lower than people fear. A short list of patterns covers most of what youβll do.
The mental model
Git has three βplacesβ where your files can live at any moment:
ββββββββββββββββ git add ββββββββββββββββ git commit ββββββββββββββββ
β Working β ββββββββββββββΆ β Staging β ββββββββββββββΆ β Repository β
β directory β β area β β (history) β
β (your files)β β (cart) β β β
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
- Working directory β the files youβre editing right now.
- Staging area β a βshopping cartβ where you select which changes to include in the next commit.
- Repository β the permanent history of all your commits.
You edit in the working directory, stage changes you want to keep (git add), then commit them (git commit). The commit is permanent in your local history.
To share with others (or back yourself up), you push your commits to a remote β usually GitHub.
Setting up Git (once per machine)
# Tell Git who you are (used in commit metadata)
git config --global user.name "George"
git config --global user.email "george@example.com"
# Pick your default branch name (modern convention: "main", not "master")
git config --global init.defaultBranch main
# Pick how Git handles line endings (CRLF on Windows, LF on Unix)
# Windows users:
git config --global core.autocrlf true
# Mac/Linux users:
git config --global core.autocrlf inputDone. These config values persist forever on this machine.
Starting a new repository
Two ways:
Option A: Start fresh in an existing folder
cd /path/to/project
git init
# Now this folder is a Git repo.Option B: Clone an existing repo from GitHub
git clone https://github.com/user/repo.git
cd repo
# Now you have a local copy of the repo.For modern web projects, npx create-next-app automatically runs git init for you. You donβt have to do it manually for new Next.js projects.
The 15 daily-use commands
These are what youβll actually type:
1. git status β what changed?
git statusShows: files youβve modified, files staged for commit, files Git doesnβt know about (untracked). Run this constantly. Itβs free and reassuring.
2. git add β stage changes
git add file.txt # stage one file
git add file1.txt file2.txt # stage multiple
git add . # stage everything in the current folder (and below)Staging is βI want this in the next commit.β You can stage some changes and leave others for a future commit β useful for keeping commits focused.
3. git commit β record the staged changes
git commit -m "Add dark mode toggle"The -m flag is the commit message. Without it, Git opens an editor for you to write the message.
Good commit messages explain WHY, not what. The diff already shows what changed. Future-you (or your team) wants to know why.
4. git log β see the history
git log # full log
git log --oneline # condensed (one line per commit)
git log --oneline -10 # last 10 commits
git log --graph --oneline --all # visual tree5. git diff β see what changed
git diff # unstaged changes
git diff --staged # staged but not committed changes
git diff HEAD~1 # changes since the previous commit6. git branch β manage branches
git branch # list branches
git branch feature/dark-mode # create a branch (doesn't switch)
git branch -d feature/dark-mode # delete a branch (only if merged)
git branch -D feature/dark-mode # FORCE delete (even if not merged β careful)7. git checkout (or modern git switch) β switch branches
git checkout main # switch to existing branch
git checkout -b feature/dark-mode # create AND switch
# Modern equivalent:
git switch main
git switch -c feature/dark-modegit switch is newer and clearer; git checkout is older and overloaded (it does many things). Use switch for branch switching when you can.
8. git merge β combine branches
git checkout main
git merge feature/dark-modePulls the changes from feature/dark-mode into main.
9. git push β send your commits to the remote
git push # push the current branch to its remote tracking branch
git push origin main # explicit: push main to the remote called "origin"
git push -u origin feature/dark-mode # first push: set the upstream10. git pull β bring othersβ commits to your local repo
git pull # fetch + merge in one stepgit pull is shorthand for git fetch (download changes) + git merge (apply them). For more control, run them separately.
11. git fetch β download without applying
git fetch # see what others have pushed, but don't applyUseful when you want to inspect remote changes before integrating them.
12. git stash β set aside uncommitted work temporarily
git stash # tuck away uncommitted changes
git stash pop # bring them back
git stash list # see your stashesUseful when you need to switch branches but have uncommitted work you donβt want to commit yet.
13. git remote β manage remotes
git remote -v # list remotes
git remote add origin https://github.com/u/r.git # add a remote
git remote remove origin # removeβoriginβ is the conventional name for the main remote. You usually have just one.
14. git reset β undo
git reset HEAD~1 # uncommit the last commit, keep the changes
git reset --hard HEAD~1 # uncommit AND delete the changes (DANGEROUS)See Git rescue moves for safer alternatives in most cases.
15. git clone β copy a repo from a remote
git clone https://github.com/user/repo.gitAlready mentioned but itβs daily-use important.
A typical day, command by command
What a real session looks like:
# Start the day β pull the latest
git checkout main
git pull
# Create a branch for today's work
git switch -c feature/add-search
# ... do work in your editor ...
# See what changed
git status
git diff
# Stage and commit a coherent chunk
git add lib/search.ts components/SearchBox.tsx
git commit -m "Add fuzzy search to the navbar"
# ... more work ...
git add app/results/page.tsx
git commit -m "Add results page rendering search hits"
# Push the branch to GitHub
git push -u origin feature/add-search
# Open a pull request on GitHub (in the web UI or via gh CLI)
gh pr create --title "Add search feature" --body "Adds fuzzy search across notes."
# Later β after review, merge the PR in GitHub UI
# Sync local main and delete the merged branch
git checkout main
git pull
git branch -d feature/add-searchThatβs a normal day. Once itβs automatic, you barely think about it.
.gitignore β files Git should ignore
A file at your project root called .gitignore lists patterns of files Git should never track:
# Dependencies
node_modules/
# Build outputs
.next/
dist/
build/
# Environment files (often have secrets!)
.env
.env.local
*.env
# IDE files
.vscode/
.idea/
# OS files
.DS_Store
Thumbs.db
Modern frameworks (Next.js, etc.) generate a sensible .gitignore for you. Tweak as you add tools.
Critical: .env* files almost always belong in .gitignore. Accidentally committing secrets to a public repo is one of the most common security disasters.
What a βgoodβ commit looks like
The standards:
- Focused. One coherent change per commit. Not βvarious changes to the app.β
- Buildable. The code should compile/pass tests at every commit. Donβt commit half-broken state.
- Well-described. First line = a clear, imperative summary (βAdd search,β not βAdded searchβ or βadded search functionality to the navbar component because we needed itβ). Optional longer body explains why.
- Why-focused. The diff shows what. The message should illuminate why.
Example:
Add fuzzy search to the navbar
Users were complaining that finding old notes required scrolling
through pages. Fuzzy search lets them type partial titles or
fragments and jump straight to matches.
Uses the `fzf` library (3KB gzipped) β small enough that loading
it in the navbar doesn't hurt initial paint.
That commit message will be useful in two years when someone asks βwhy does our navbar have a search box?β
Common gotchas
-
.env*files in Git. Triple-check.gitignorebefore committing a new project. Once a secret is in Git history, itβs effectively public β even if you delete the file. -
Line endings on Windows.
git config core.autocrlf truefor Windows; otherwise Git will tell you the entire file changed when you just edited one line. -
git pushafter rewriting history. Force-pushing (--force) can overwrite work others have based on. Use--force-with-leaseinstead, which refuses if someone has pushed since you fetched. -
git add .can stage things you didnβt expect. Including secret files you forgot to gitignore. Usegit statusto verify before committing, especially for first commits. -
git commit -askips the staging step. It auto-stages all modified tracked files. Convenient but bypasses the βreview whatβs in this commitβ benefit. Use carefully. -
git checkoutis overloaded. It switches branches, but also discards file changes βgit checkout file.txtreverts file.txt to the last committed version. This is whygit switchandgit restorewere introduced. -
Detached HEAD state. If you
git checkout <commit-hash>, youβre in βdetached HEAD.β Commits made here arenβt on any branch and can be lost. Switch back to a branch or create one. -
Branch already exists.
git switch -c namefails ifnameexists. Usegit switch nameto switch, orgit branch -D nameto delete first. -
Pull while having uncommitted changes. Git refuses if it would conflict. Stash, commit, or discard first.
-
βYour branch is behind origin/main by N commits.β Normal. Run
git pull. -
βYour branch and origin/main have diverged.β Each has commits the other doesnβt. Youβll need to merge or rebase.
See also
- What is version control? π©
- GitHub π© π¦
- Branches & merging π©
- Pull requests π©
- Rebase vs merge π©
- Resolving merge conflicts π©
- Git rescue moves π©
- Git gotchas π₯
- Glossary: Git, Branch, Diff
Sources
- Pro Git book (free)
- Official Git documentation
- Atlassian β Git tutorials
- GitHub β Git cheat sheet
- Oh Shit, Git!?! β common rescue scenarios in plain language