Skip to main content
  1. Guides/

Git Reference Guide

··1885 words·9 mins·

Concepts
#

  • Three stages of a file: working directory (in-progress edits) → staging area (ready to commit) → .git repository (committed/saved locally). Almost every command below moves a file between these three places.
  • .gitignore only stops untracked files from being added — a file already committed stays tracked even after you add it to .gitignore. Untrack it with git rm --cached <file> first. Sample .gitignore files.
  • checkout vs. switch/restore: git checkout is the old do-everything command (switch branches, restore files, view old commits). Modern Git split it into git switch (branches) and git restore (files) because checkout’s dual role was a common source of mistakes. Both forms are shown below — checkout because it’s what the source tutorials use and still works everywhere, switch/restore because they’re clearer for new scripts/habits.

Basic Setup & Navigation
#

  • git --version — check which Git version is installed.
  • git init — turn the current directory into a Git repo by creating a .git folder (delete that folder to un-git a project).
  • git clone <url> — copy a remote repo, and its full history, to a new local directory.
  • git config --list — show current configuration settings.
    • --local — current repo only · --global — all your repos · --system — every user on the machine
    • git config --global <setting> <value> — change a setting, e.g. git config --global user.name "Your Name"
    • git config alias.st status — create a shortcut (git st now runs git status)
    • man git-config — full list of every config option
  • git help <verb> or git <verb> --help — open the manual page for a command.

Prepare to Commit (Staging)
#

  • git status (or -s/-sb for a short form) — see what’s changed, staged, or untracked.
  • git add <file> — stage a new/modified file (re-run after further edits to re-stage the latest version).
  • git add -A / --all — stage everything (new, modified, deleted) in the whole working tree; the default for plain git add . at the repo root.
  • git add -u / --update — stage only changes to files Git already tracks, not new files.
  • git add . — like -A but limited to the current directory and below.
  • git add -p — interactively choose which chunks of a changed file to stage, instead of the whole file.
  • git mv <old> <new> — rename/move a tracked file (equivalent to mv + git add + git rm).
  • git rm <file> — delete a file from both the working directory and the repo.
  • git rm --cached <file> — stop tracking a file but keep it on disk (typical fix when a file was committed before being added to .gitignore).
  • git reset <file> (or git reset HEAD <file>) — unstage one file, keeping its edits.
  • git reset — unstage everything, keeping edits.

Make Commits
#

  • git commit — commit staged changes, opening your editor for the message.
  • git commit -m "message" — commit staged changes with an inline message.
  • git commit -a -m "message" / git commit -am "message" — stage every tracked file’s changes and commit in one step (does not pick up brand-new untracked files).
  • git commit --amend -m "New message" — replace the last commit’s message. ⚠️ Rewrites that commit’s hash.
  • git commit --amend (message unchanged in editor) — add a staged file to the previous commit instead of the message. ⚠️ Also rewrites the hash.

Move Between Branches
#

  • git switch <name> or git checkout <name> — switch to an existing branch.
  • git switch -c <name> or git checkout -b <name> — create a new branch and switch to it in one step.
  • git branch <name> — create a branch without switching to it.
  • git branch — list local branches.
  • git branch -a — list local and remote-tracking branches.
  • git branch --sort=-committerdate — list branches ordered by most recently committed to (handy for finding your recent work).
  • git branch --merged — list branches already fully merged into the current one (safe to delete).
  • git branch -d <name> — delete a local branch (Git refuses if it isn’t merged yet).
  • git branch -D <name> — force-delete a branch even if unmerged.
  • git push origin --delete <name> — delete the branch on the remote too.

Diffing
#

  • git diff — unstaged changes vs. the staging area.
  • git diff --staged — staged changes vs. the last commit.
  • git diff --staged --no-renames — same, without Git’s rename detection.
  • git diff HEADall staged + unstaged changes vs. the last commit, combined.
  • git diff -r HEAD / HEAD~1 / HEAD~2 — unstaged changes vs. a specific past commit.
  • git diff <commit> <commit> — changes between any two commits (e.g. git diff HEAD~2 HEAD~3).
  • git diff <commit> <file> — changes to one file since a given commit.
  • git diff <commit> --stat / git show <commit> --stat — a summary (file names + line counts) instead of a full diff.
  • git diff --stat --cached origin/main — summary of what’s staged, compared against the remote.
  • git show <commit> — full diff between a commit and its parent.
  • git show <commit> <filename> — a single file’s changes at that commit.
  • git annotate <file> / git blame <file> — show which commit (and author) last changed each line of a file.

Ways to refer to a commit
#

Anywhere <commit> is used above, you can pass:

Form Example Meaning
Branch name main tip of that branch
Tag v0.1 a named, usually release, point
Commit ID 3e887ab short or full SHA1 hash
Remote branch origin/main tip of a branch on a remote
Current commit HEAD where you currently are
N commits back HEAD~3 or HEAD^^^ 3 commits before HEAD

Log & Code Archaeology
#

  • git log — full history, reverse-chronological.
  • git log -1 — just the most recent commit, full SHA1.
  • git log --oneline — one line per commit, short SHA1 (add -n 10 to limit the count).
  • git log --stat — commits plus which files each one touched.
  • git log --patch — commits plus each one’s full diff.
  • git log --graph main — draw the branch/merge structure as ASCII art.
  • git log <file> — every commit that touched a specific file.
  • git log --follow <file> — same, but keeps tracking history across renames.
  • git log -G banana — find every commit that added or removed the text “banana” (a code-search tool, useful for tracking down when a line was introduced or deleted).
  • git reflog — history of everywhere HEAD has pointed (branch switches, resets, commits, rebases). Your safety net for “lost” commits.

Discard / Undo Changes
#

  • git checkout -- <file> or git restore <file> — discard unstaged changes, restoring the last committed version.
  • git checkout HEAD <file> or git restore --staged --worktree <file> — discard both staged and unstaged changes to one file.
  • git reset --hard — discard all staged and unstaged changes in the whole repo. ⚠️ Unrecoverable for those edits.
  • git reset --hard <hash> — same, but also rewinds the branch to <hash>, discarding later commits’ changes too.
  • git clean -df — delete untracked (d)irectories and (f)iles (things git status shows as “untracked”).
  • git stash — shelve staged + unstaged changes for later without committing them.

Edit History
#

⚠️ Everything in this section rewrites commit hashes. Safe only on commits/branches you haven’t shared with anyone yet.

  • git reset HEAD~1 — “undo” the most recent commit, keeping its changes in your working directory (mixed reset, the default).
  • git reset --soft <hash> — rewind to <hash>, keeping later changes staged.
  • git reset --mixed <hash> (same as plain git reset <hash>) — rewind to <hash>, keeping later changes unstaged in the working directory.
  • git rebase -i HEAD~5 — interactively edit the last 5 commits: reorder, reword, or fixup/squash them into fewer commits.
  • git commit --amend — change the last commit’s message, or add a forgotten staged file to it.
  • Undo a failed rebase: git reflog <branch> to find the commit ID from before the rebase, then git reset --hard <commit> to jump back to it.
  • git revert <hash> — create a new commit that undoes a prior one, leaving history intact. The safe way to undo something that’s already been pushed/shared.
  • git cherry-pick <hash> — copy one commit’s changes onto the current branch (leaves the original commit where it was).

Combine Diverged Branches
#

  • Mergegit switch main then git merge <branch>: brings another branch’s commits into the current one via a new merge commit. Preserves both branches’ history as-is.
  • Fast-forward merge — same commands, but if main has no new commits since <branch> diverged, Git just moves the main pointer forward (no merge commit created).
  • Rebasegit switch <branch> then git rebase main: replays <branch>’s commits on top of main, producing a linear history instead of a merge commit. ⚠️ Rewrites the rebased branch’s commit hashes.
  • Squash mergegit switch main then git merge --squash <branch> then git commit: combines all of <branch>’s commits into a single new commit on main.

Restore an Old File
#

  • git checkout <commit> <file> or git restore <file> --source <commit> — pull one file’s contents from an older commit into your working directory, without touching anything else.

Remotes
#

  • git remote add <name> <url> — register a remote repository under a short name (usually origin).
  • git remote -v — list configured remotes and their URLs.

Push Your Changes
#

  • git push origin main — push the main branch to the origin remote.
  • git push — push the current branch to its already-configured remote “tracking branch”.
  • git push -u origin <name> — push a branch for the first time and set up tracking so plain git push/git pull works afterward (-u = --set-upstream).
  • git push --force-with-lease — force-push, but abort if the remote has commits you haven’t seen yet (safer than plain --force for shared branches).
  • git push --tags — push tags along with commits.

Pull Changes
#

  • git fetch origin main — download remote changes without touching any of your local branches.
  • git fetch <branch1> <branch2> — fetch one branch’s commits into another.
  • git pull origin main / git pull — fetch and merge remote changes into your current branch.
  • git pull --rebase — fetch, then rebase your current branch on top of the fetched changes instead of merging (keeps history linear).

Stashing
#

  • git stash / git stash save "<comment>" — shelve working-dir + staged changes onto a stack.
  • git stash list — list all stashes (stash@{0}, stash@{1}, …).
  • git stash show — summarize the diff in a stash.
  • git stash pop — reapply the most recent stash and remove it from the stack.
  • git stash apply stash@{0} — reapply a stash but keep it on the stack.
  • git stash branch <name> — apply a stash onto a brand-new branch and drop it from the stack (useful if applying to the current branch would conflict).
  • git stash drop stash@{0} — delete one specific stash.
  • git stash clear — delete every stash.
  • Tip: stash on one branch, then commit (or apply) on another — a quick way to move work-in-progress changes between branches.

Important Files
#

  • .git/config — this repo’s local configuration (what --local reads/writes).
  • ~/.gitconfig — your global, per-user configuration (what --global reads/writes).
  • .gitignore — patterns for files Git should never track; generate examples at github.com/github/gitignore.

Diff/Merge GUI Tools
#

Useful for resolving conflicts visually: DiffMerge, Sourcetree.

Resources
#

Further reading at the git-scm.com/docs website and the Pro Git book.

Angelo Varlotta
Author
Angelo Varlotta
If you can’t explain it simply, you don’t understand it well enough – Albert Einstein