Classic Git Commands Notes

Core mental model

  • Working tree: your files on disk.
  • Index (staging area): what you have prepared for the next commit.
  • HEAD: what you currently have checked out (usually the tip of your current branch). (Git SCM)

Table of contents (skeleton)

  1. Inspect safely (read-only)
  2. Make changes (stage + commit)
  3. Branching (create, switch, merge)
  4. Remotes (fetch, pull, push)
  5. Undo (restore, reset, revert)
  6. Cleanup (clean)
  7. Recovery (reflog)

1. Inspect safely (read-only)

Status

git status
  • git: runs the Git command-line tool. (Git SCM)

  • status: shows:

    • changes between the index and the current HEAD commit,
    • changes between the working tree and the index,
    • and untracked (not ignored) files. (Git SCM)

Why: fastest “what will commit vs what is just edited vs what is untracked” check before you do anything else. (Git SCM)

History

git log
  • log: shows commit history (the commit log). (Git SCM)

Useful scan format:

git log --oneline --decorate
  • --oneline: uses a compact, single-line format (a built-in pretty format option). (Git SCM)
  • --decorate: shows reference names (branches/tags) next to commits. (Git SCM)

Differences (unstaged vs staged)

git diff
  • diff: shows changes in your working tree relative to a named commit; when used without specifying commits, it’s commonly used to inspect your current local changes before staging. (Git SCM)
  • You can explicitly compare against the latest commit using HEAD. (Git SCM)

Staged changes:

git diff --staged
  • --staged: synonym of --cached, shows what you staged for the next commit, typically compared to HEAD if you don’t provide a commit. (Git SCM)

Why: git diff answers “what did I edit”; git diff --staged answers “what will my next commit contain.” (Git SCM)

Show one object (most often a commit)

git show
  • show: shows one or more objects; for commits it shows the log message and a textual diff. (Git SCM)

Explicit latest commit:

git show HEAD
  • HEAD: references the current branch’s tip (or, in detached HEAD state, directly references a commit). (Git SCM)

Branches (local + remote-tracking)

git branch
  • branch: lists, creates, or deletes branches; with no arguments you’re typically listing local branches. (Git SCM)

Include remote-tracking branches too:

git branch -a
  • -a: shows local branches and remote-tracking branches (e.g. remotes/origin/main). (Git SCM)

Remotes (where “origin” points)

git remote -v
  • remote: manages the set of tracked remotes; with no arguments it lists existing remotes. (Git SCM)
  • -v / --verbose: shows each remote’s URL after its name. (Git SCM)

2. Make changes, stage, commit

Stage specific files

git add path/to/file
  • git: runs the Git CLI.
  • add: updates the index (staging area) with the current content of the path(s) you specify, so those exact contents are what the next commit will include. (Git SCM)
  • path/to/file: limits staging to one file (repeat the command for additional files).

Why: Git commits are created from what’s in the index, not directly from your working directory. (Git SCM)

Stage everything in the current directory (common, but blunt)

git add .
  • .: means “the current directory”, so this stages new/changed content under the current folder recursively.

Why: Fast when you actually want all current changes staged, but it’s easier to accidentally include something you didn’t mean to. The index exists specifically so you can choose what goes into the next commit. (Git SCM)

Stage only parts of a file (best when a file has mixed edits)

git add -p
  • -p: “patch” mode, letting you interactively pick hunks to stage instead of staging the entire file at once. (Git SCM)

Why: Keeps commits as “one logical unit of change” even if you edited multiple things in the same file.

Commit what you staged

git commit -m "message"
  • commit: creates a new commit from the current contents of the index (staging area). (Kernel.org)
  • -m: provides the commit message on the command line (instead of opening an editor). (Kernel.org)
  • "message": describes the change. Keep it specific to what the commit does.

Why: A commit is a snapshot of what you staged; if you forget to stage a change, it won’t be included. (Git SCM)

Fix the last commit message (and/or include newly staged changes)

git commit --amend
  • --amend: replaces the most recent commit with a new one (using the current index content and message editor flow). The docs describe this as amending the last commit rather than creating a separate new one. (Git SCM)

Why: Useful for “oops, typo in message” or “forgot to include a file” (stage it, then amend).

Unstage without losing your work (keep changes in the working tree)

git restore --staged path/to/file
  • restore: restores file contents from a source into either the working tree and/or index depending on flags. (Git SCM)
  • --staged: targets the index (unstages). By default with --staged, restore comes from HEAD. (Git SCM)
  • path/to/file: unstages just that file (your working directory edits remain).

Why: This is the “I staged it but don’t want it in the next commit” move, without discarding edits. (Git SCM)

3. Branching (create, switch, merge)

List branches

git branch
  • branch: with no non-option arguments, lists existing local branches; the current branch is marked. (Git SCM)
git branch -a
  • -a / --all: lists both local branches and remote-tracking branches. (Git SCM)

Why: you want to know what exists locally vs what’s just a remote-tracking ref before creating/deleting anything.

Create a new branch (does not switch)

git branch feature/my-change
  • Creates a new branch name pointing at the current HEAD (unless you provide a different start-point). (Git SCM)
  • It does not update your working tree to that branch. (Git SCM)

Why: useful when you want a branch created but you’re not ready to leave your current working state.

Switch branches (modern)

git switch feature/my-change
  • Switches to the specified branch.
  • Updates the working tree and the index to match that branch. (Git SCM)
  • Aborts if switching would lose local changes, unless you explicitly choose options like --discard-changes or --merge. (Git SCM)

Why: this is the clearest “change branches” command and is explicitly documented for that purpose. (Git SCM)

git switch -c feature/my-change
  • -c / --create: creates a new branch at the start-point and switches to it.
  • The docs describe this as the transactional equivalent of creating the branch then switching (it won’t create/reset the branch unless the switch succeeds). (Git SCM)

Why: avoids forgetting to switch after creating a branch.

Switch branches (older, still common)

git checkout feature/my-change
  • Sets the current branch and updates files in your working directory to match it. (Git SCM)
  • Can fail if you have uncommitted changes that would be overwritten by the target branch’s versions. (Git SCM)

Why: you’ll see it in older docs and many repos, but git switch is purpose-built for this job. (Git SCM)

Rename a branch

git branch -m old-name new-name
  • -m: renames (moves) a branch. (Git SCM)

Why: keeps history; you’re only changing the ref name.

Delete a branch

git branch -d feature/my-change
  • -d: deletes the branch. (Git SCM)
git branch -D feature/my-change
  • -D: force-delete (the docs describe it as allowing deletion regardless of merged status / validity). (Git SCM)

Why: -d is the safe default; -D is the “I know what I’m doing” option.

Merge a branch into the branch you’re currently on

git merge feature/my-change
  • Merges the named branch into your currently checked-out branch; the current branch is advanced to the merge result. (Git SCM)

Fast-forward behavior controls:

git merge --ff feature/my-change
  • --ff: fast-forward when possible (just move the branch pointer; no merge commit), otherwise create a merge commit. (Git SCM)
git merge --no-ff feature/my-change
  • --no-ff: always create a merge commit, even when a fast-forward would be possible. (Git SCM)
git merge --ff-only feature/my-change
  • --ff-only: only allow fast-forward; if not possible, refuse to merge. (Git SCM)

Why: these options control whether merges leave an explicit merge commit “junction” in history or keep history linear when possible. (Git SCM)

4. Remotes (fetch, pull, push)

What a remote is (quick anchor)

git remote -v
  • remote: lists and manages remotes (named references like origin). (Git SCM)
  • -v: prints the URLs for each remote (fetch + push). (Git SCM)

Why: confirms where “origin” actually points before you fetch/pull/push. (Git SCM)

Add a remote

git remote add origin <url>
  • add: records a new remote named origin pointing to <url>. (Git SCM)
  • <url>: the repository location (HTTPS/SSH/etc).

Why: creates the “handle” you’ll use for future fetch/push operations. (Git SCM)

Change a remote URL

git remote set-url origin <newurl>

# example pointing origin url to ssh format "git@github.com:"
git remote set-url origin git@github.com:username/repository-name.git
  • set-url: changes the configured URL for the remote. (Git SCM)
  • origin: the remote name you’re modifying.
  • <newurl>: the replacement URL.

Why: fix a wrong URL or switch from HTTPS to SSH without re-cloning. (Git SCM)

Fetch (download remote updates without integrating)

Fetch a remote

git fetch origin
  • fetch: downloads refs/objects and updates remote-tracking branches (e.g. origin/main). (Git SCM)
  • origin: which remote to fetch from.

Why: gets you the latest remote state while keeping your current branch and working tree unchanged (you’re updating remote-tracking refs, not merging). (Git SCM)

Fetch and prune stale remote-tracking branches

git fetch --prune origin
  • --prune: removes stale remote-tracking references that no longer exist on the remote (pruning behavior is part of fetch). (Git SCM)
  • origin: prunes under that remote namespace.

Why: keeps remotes/origin/* from accumulating deleted branches. (Git SCM)

Pull (fetch + integrate into your current branch)

Pull using the configured upstream

git pull
  • pull: fetches from the configured remote/upstream and then integrates into the current branch (by merge or rebase depending on config/options). (Git SCM)

Why: convenience when your branch already tracks an upstream branch. (Git SCM)

Pull a specific remote branch into the current branch

git pull origin main
  • origin: which remote to fetch from.
  • main: which branch/ref to fetch and integrate. (Git SCM)

Why: explicit is safer when you’re not sure what upstream is set. (Git SCM)

Pull and rebase (common “linear history” workflow)

git pull --rebase
  • --rebase: after fetching, rebases your current branch on top of the upstream branch instead of merging. (Git SCM)

If conflicts happen:

git rebase --abort
  • --abort: stops the rebase and returns you to the pre-rebase state. (Git SCM)

Why: rebasing replays your commits onto the updated base (same final snapshot, different history). (Git SCM)

Push (send your local refs to the remote)

Push the current branch to its upstream

git push
  • push: updates remote refs using local refs and sends the required objects. (Git SCM)

Why: simplest when upstream tracking is already configured.

Push a branch the first time and set upstream (so future git push works)

git push --set-upstream origin <branch>
  • --set-upstream (same idea as -u): sets the upstream tracking relationship while pushing. (Git SCM)
  • origin <branch>: where to push and what to name the remote branch.

Why: establishes “this local branch tracks that remote branch,” which makes later git pull / git push defaults work. (Git SCM)

Safer force push (when you must rewrite remote history)

git push --force-with-lease
  • --force-with-lease: force-updates remote refs only if the remote ref still matches what you expect (based on your remote-tracking refs). (Git SCM)

Why: protects you from overwriting someone else’s newer push that you haven’t fetched yet (safer than --force). (Git SCM)

5. Undo safely (restore, reset, revert)

Think in three layers

  1. Working tree changes
  2. Staging area (index)
  3. Commits (history)

Commands below are ordered from “safest” to “most destructive”.

Discard changes in the working tree (single file)

git restore path/to/file
  • restore Restores working tree files from a source (by default HEAD) and can also affect the index depending on options. Git introduced restore to make “undo” operations more explicit.
  • No flags With just a path, it restores the file in your working tree from HEAD while leaving the index unchanged.

Why Use when you want to throw away local edits in a file and go back to how it is in the latest commit.

Unstage a file (keep edits in working tree)

git restore --staged path/to/file
  • --staged Tells Git to operate on the index instead of the working tree. With --staged and no source, Git restores the index entry from HEAD.
  • path/to/file Only affects that file’s staged state. The working tree still has your edits.

Why Use when “I added this to the next commit by mistake” but you want to keep the changes in the file.

Throw away both staged and unstaged edits (reset file fully)

git restore --staged --worktree path/to/file
  • --worktree Explicitly says “also restore the working tree.” Combined with --staged, you restore both the index and working tree from HEAD.

Why Use when you want that file exactly as it exists in the latest commit, no local changes at all.

Soft reset (move HEAD, keep everything staged)

git reset --soft HEAD~1
  • reset Moves the current branch (and updates HEAD) to a specified commit; depending on mode, it also updates index and working tree.
  • --soft Updates HEAD only. Working tree and index stay as-is.
  • HEAD~1 The commit before current HEAD.

Effect The last commit disappears from history, but all its changes become staged again (ready to recommit differently).

Why Use for “I want to redo that commit message/structure” but prefer to keep everything staged.

Mixed reset (default) uncommit and unstage, keep edits

git reset HEAD~1
  • No mode flag Default is --mixed. It moves HEAD and resets the index to match the target commit but leaves the working tree untouched.

Effect The last commit is removed from branch history, its changes are now just working tree modifications (not staged).

Why Use for “uncommit this and put all the changes back into my working directory so I can decide what to stage.”

Hard reset (dangerous, moves HEAD + index + working tree)

git reset --hard origin/main
  • --hard Resets HEAD, the index, and the working tree to match the specified commit. Any local changes not committed are lost.
  • origin/main Often used when you want local to exactly match the remote-tracking branch.

Why Use when you deliberately want to discard local work and sync to a known commit. This is destructive; confirm with git status first.

Revert a commit (safe, history-preserving undo)

git revert <commit>
  • revert Creates a new commit that undoes the changes introduced by the specified commit. It does not change existing history.
  • <commit> Can be a hash, tag, or reference like HEAD~2.

Effect You get a new commit “Revert X” that applies the inverse patch of the chosen commit.

Why Use in shared branches when you must undo something already pushed, without rewriting history.

Revert the latest commit

git revert HEAD
  • HEAD Targets the most recent commit on the current branch.

Why Common “oops, that whole last commit should be undone” on a branch others may already be using.

Abort an in-progress revert

git revert --abort
  • --abort If a revert hits conflicts, this option cancels the revert and attempts to bring you back to the state before the revert started.

Why Use when revert conflicts are too messy and you decide to abandon that revert attempt.

6. Cleanup untracked files (git clean)

Dry-run first (see what would be removed)

git clean -n
  • clean Cleans the working tree by removing files that are not under version control, starting from the current directory. (Git)
  • -n / --dry-run “Don’t actually remove anything, just show what would be done.” (Git)

Why Always run this first so you see exactly which untracked files and directories would be deleted. The book explicitly recommends -n as the safe way to check before using -f. (Git)

Actually remove untracked files

git clean -f
  • -f / --force Required if clean.requireForce is not set to false; Git refuses to delete files unless -f, -n, or -i is given. (Git)

Effect Removes untracked files (but not untracked directories unless you also use -d). (Git)

Why Use when you are sure those untracked files are safe to delete, for example build artifacts or temporary files.

Remove untracked files and directories

git clean -f -d
  • -d In addition to untracked files, remove untracked directories (unless they are separate Git repos with their own .git). (Git)

Effect Typical “wipe all untracked stuff under here” command, often used to clear build outputs. The book notes git clean -f -d “removes any files and also any subdirectories that become empty.” (Git)

Include ignored files too (more aggressive)

git clean -f -d -x
  • -x Also remove ignored files; by default, git clean will not remove files that match ignore patterns. (Git)

Why Use for “really clean build” situations where you want all generated files gone, even if they are in .gitignore. Use -n first so you do not accidentally remove something important. (Git)

Interactive cleanup

git clean -i
  • -i / --interactive Runs clean in an interactive mode so you can choose which untracked items to remove. (Git)

Why A safer “picker” UI for when you have many untracked files and only want to delete some of them.

7. Recovery (git reflog)

Inspect where HEAD and branches have pointed (git reflog)

git reflog
  • reflog Manages the information recorded in reference logs. Reflogs “record when the tips of branches and other references were updated in the local repository.” (Git)
  • Output like HEAD@{2} Shortnames such as HEAD@{2} mean “where HEAD used to be two moves ago”; master@{one.week.ago} means “where master used to point one week ago.” (Git)

Why This is your “time machine” when you have moved HEAD (e.g. via reset) and want to find previous commit positions.

See reflog as a normal log

git log -g
  • -g Shows the reflog entries as a normal commit log. The book shows git log -g as a “more useful way” to view reflog history. (Git)

Why Easier to navigate and copy commit hashes from reflog entries when you are trying to recover work.

Recover a lost HEAD position (example)

  1. Find the position in reflog, e.g. HEAD@{2} or a hash.
  2. Reset or create a branch there.

Reset current branch back to that position:

git reset --hard HEAD@{2}
  • Uses the reflog specifier as the target commit; --hard moves HEAD, index, and working tree. (Git)

Safer alternative: create a rescue branch first:

git branch rescue HEAD@{2}
  • Makes a new branch rescue pointing at that past position from the reflog. (Standard git branch behavior with a given start point.) (Git)

Why This is the pattern for “I hard-reset and lost some commits” – use git reflog to find them, then either reset back or create a branch at that commit.