Skip to content

Git Command Atlas: Every Git Command by Task, with Cautions

Most command references tell you what a flag does. The useful part is usually what happens when you get it slightly wrong.

Every command here carries a working example and, where one exists, the failure mode that actually catches people — not a generic warning, but the specific way that command surprises you. Where the behaviour depends on a model worth understanding, there is a link into the lesson that explains it.

Setup & configuration

Identity, defaults and the configuration hierarchy Git reads on every command.

git config --global user.name "<name>"

Set the author name recorded in every commit you make.

git config --global user.name "Ada Lovelace"

Caution: Author identity is baked into the commit object. Changing it later means rewriting history, which changes every downstream commit SHA.

Read the lesson →

git config --list --show-origin

Show every effective setting and which file it came from.

git config --list --show-origin

The fastest way to answer "why is Git behaving like that here?"

Read the lesson →

git config --global init.defaultBranch <name>

Set the branch name used when you create a new repository.

git config --global init.defaultBranch main

Read the lesson →

git config --global core.editor "<editor>"

Choose the editor Git opens for commit messages and interactive rebase.

git config --global core.editor "code --wait"

Caution: The editor must block until the file is closed. Without a wait flag Git sees an empty message and aborts.

Read the lesson →

Creating & cloning

Starting a repository, and getting one onto your machine efficiently.

git init

Turn the current directory into a Git repository.

git init

Creates `.git/` — the entire repository lives in that one directory.

Read the lesson →

git clone <url>

Copy a remote repository, its full history and its branches.

git clone https://github.com/example-org/project.git

Read the lesson →

git clone --filter=blob:none <url>

Clone without file contents, fetching them on demand (partial clone).

git clone --filter=blob:none https://github.com/example-org/monorepo.git

Caution: History operations stay fast, but `git log -p` and `git blame` become network operations the first time they run. A partial clone is not a backup.

Read the lesson →

git clone --depth=1 <url>

Clone only the most recent commit (shallow clone).

git clone --depth=1 https://github.com/example-org/project.git

Caution: Shallow clones lack the history needed for merge bases, so diff-against-base tooling can silently misbehave in CI.

Read the lesson →

Staging & the index

The index is the layer between your files and your next commit.

git status

Show what is staged, what is modified, and what is untracked.

git status --short --branch

The short form is far easier to scan once you know the two-column format.

Read the lesson →

git add <path>

Copy the current content of a file into the index.

git add src/index.ts

Caution: The index holds a snapshot of the file as it was when you ran `git add`. Editing afterwards leaves the newer content unstaged.

Read the lesson →

git add -p

Stage selected hunks interactively rather than whole files.

git add -p src/index.ts

The single best habit for producing reviewable commits.

Read the lesson →

git restore --staged <path>

Remove a file from the index while keeping your edits.

git restore --staged src/index.ts

Read the lesson →

git diff --staged

Show what is staged — exactly what the next commit will contain.

git diff --staged

Read this before every commit and most bad commits never happen.

Read the lesson →

Committing

Recording snapshots, and correcting the most recent one.

git commit -m "<message>"

Record the staged snapshot as a new commit.

git commit -m "Fix off-by-one in pagination"

Read the lesson →

git commit --amend

Replace the most recent commit with a new one.

git commit --amend --no-edit

Caution: This creates a different commit with a different SHA. Amending something already pushed and shared means a force push and coordination.

Read the lesson →

git commit -S

Create a cryptographically signed commit.

git commit -S -m "Release 2.4.0"

Read the lesson →

Branches

A branch is a movable pointer to a commit — nothing more.

git switch -c <branch>

Create a branch and move onto it.

git switch -c feature/pagination

`switch` is the modern, single-purpose alternative to `checkout`.

Read the lesson →

git branch -vv

List branches with their upstream and how far ahead or behind each is.

git branch -vv

Read the lesson →

git branch -d <branch>

Delete a branch that has been merged.

git branch -d feature/pagination

Caution: `-D` forces deletion of unmerged work. The commits survive in the reflog for a while, so this is recoverable — but only for a while.

Read the lesson →

Merging

Combining histories, and resolving the conflicts that result.

git merge <branch>

Merge another branch into the current one.

git merge feature/pagination

Read the lesson →

git merge --no-ff <branch>

Always create a merge commit, even when a fast-forward is possible.

git merge --no-ff release/2.4

Keeps the fact that a branch existed visible in history.

Read the lesson →

git merge --abort

Abandon an in-progress merge and return to the pre-merge state.

git merge --abort

Caution: Only works while the merge is unresolved. After committing the merge, you need `git revert -m 1` instead.

Read the lesson →

git mergetool

Open your configured three-way merge tool on each conflicted file.

git mergetool

Read the lesson →

Rebasing

Replaying commits onto a new base — and the rules for doing it safely.

git rebase <base>

Replay the current branch’s commits on top of another branch.

git rebase main

Caution: Every replayed commit gets a new SHA. Rebasing anything already pushed and shared rewrites history other people have.

Read the lesson →

git rebase -i <base>

Reorder, squash, edit or drop commits interactively.

git rebase -i main

Read the lesson →

git rebase --abort

Abandon an in-progress rebase and restore the original branch.

git rebase --abort

The escape hatch. A rebase gone wrong is almost always recoverable.

Read the lesson →

git rebase --continue

Resume a rebase after resolving a conflict.

git rebase --continue

Caution: Stage your resolution first. `--continue` with nothing staged and no changes is treated as an empty commit.

Read the lesson →

git pull --rebase

Fetch and replay your local commits on top, instead of merging.

git pull --rebase origin main

Avoids the "Merge branch main into main" commits that clutter shared branches.

Read the lesson →

Remotes

Exchanging commits with other copies of the repository.

git remote -v

List configured remotes and their URLs.

git remote -v

git fetch --all --prune

Update every remote-tracking branch and delete ones that no longer exist.

git fetch --all --prune

Fetch is always safe: it changes no local branch and no working tree file.

git push -u origin <branch>

Push a branch and set it to track the remote copy.

git push -u origin feature/pagination

git push --force-with-lease

Force push, but refuse if the remote has commits you have not seen.

git push --force-with-lease origin feature/pagination

Caution: Always prefer this to `--force`. Plain `--force` will happily discard a colleague’s commits that landed while you were rebasing.

Read the lesson →

History & inspection

Reading what happened, and finding when something changed.

git log --oneline --graph --decorate

Compact, visual history showing branch topology.

git log --oneline --graph --decorate --all

Read the lesson →

git log -S"<string>"

Find commits that changed the number of occurrences of a string.

git log -S"parseTimestamp" --oneline

The "when was this introduced or deleted?" query. Often faster than reading blame.

git blame <file>

Show which commit last changed each line of a file.

git blame -L 40,60 src/index.ts

Caution: On a partial clone this fetches every revision it walks, so the first run can be slow.

git bisect start

Binary-search history to find the commit that introduced a bug.

git bisect start && git bisect bad && git bisect good v2.3.0

Finds the culprit in log₂(n) steps. `git bisect run <cmd>` automates it entirely.

Undo & recovery

The commands people reach for under pressure. Know these before you need them.

git restore <path>

Discard uncommitted changes to a file in the working tree.

git restore src/index.ts

Caution: This is genuinely destructive: uncommitted work is not in Git anywhere, so there is nothing to recover it from.

Read the lesson →

git reset --soft HEAD~1

Undo the last commit, keeping its changes staged.

git reset --soft HEAD~1

The right way to redo a commit message or split a commit.

Read the lesson →

git reset --hard <ref>

Move the branch and discard all changes after that point.

git reset --hard origin/main

Caution: Discards uncommitted work irrecoverably. Committed work it moves past is still in the reflog, but uncommitted work is simply gone.

Read the lesson →

git revert <commit>

Create a new commit that undoes an earlier one.

git revert a1b2c3d

The safe way to undo something already pushed — it adds history rather than rewriting it.

git reflog

Show where HEAD has been — including commits no branch points to.

git reflog

The recovery command. Almost anything "lost" in Git is findable here.

Read the lesson →

git stash push -m "<message>"

Set aside uncommitted changes and return to a clean tree.

git stash push -m "half-done pagination"

Caution: Stashes are easy to forget. `git stash list` regularly, or use a branch instead.

Tags & releases

Naming specific commits, usually for releases.

git tag -a <name> -m "<message>"

Create an annotated tag — a real object with author and date.

git tag -a v2.4.0 -m "Release 2.4.0"

Caution: Prefer annotated tags for releases. Lightweight tags are just a pointer with no metadata.

git push origin --tags

Push tags, which a normal push does not send.

git push origin --tags

git describe --tags

Name the current commit relative to the nearest tag.

git describe --tags --always --dirty

The usual source of a build version string.

Worktrees & submodules

Multiple checkouts of one repository, and repositories inside repositories.

git worktree add <path> <branch>

Check out another branch into a second directory, sharing one repository.

git worktree add ../hotfix hotfix/urgent

Avoids stashing to fix an urgent bug on another branch.

Read the lesson →

git worktree list

Show every working tree attached to this repository.

git worktree list

Read the lesson →

git submodule update --init --recursive

Fetch and check out the submodules a repository references.

git submodule update --init --recursive

Caution: A submodule pins an exact commit, not a branch. Forgetting to commit the updated pointer is the classic submodule bug.

Maintenance & performance

Keeping a large repository fast.

git maintenance start

Register the repository for scheduled background maintenance.

git maintenance start

Enables the incremental strategy: commit-graph and prefetch hourly, repacking daily.

Read the lesson →

git count-objects -vH

Report object counts and on-disk size in human units.

git count-objects -vH

The first command to run on a repository somebody has called slow.

Read the lesson →

git sparse-checkout set --cone <dir>...

Populate only selected directories in the working tree.

git sparse-checkout set --cone apps/web libs/core

Caution: Reduces what is written to disk, not what is downloaded. Combine with `--filter=blob:none` to reduce transfer too.

Read the lesson →

git gc --prune=now

Garbage-collect unreachable objects immediately.

git gc --prune=now

Caution: Prunes unreachable objects the reflog would otherwise let you recover. Do not run this while trying to recover lost work.

Read the lesson →

If you are describing a problem, not a command

Section titled “If you are describing a problem, not a command”

This page is organised by command. When you know the symptom but not the tool, start from the symptom instead: