# Code Reference — Git

_40 pages_

---
# Git (/docs/git)



# Git [#git]

Everyday Git, recovery, GitHub CLI.

Browse the sidebar for every cheat sheet in this section.

## Sections [#sections]

* [Examples](./examples)


---

# amend (/docs/git/amend)



# amend [#amend]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git commit --amend` rewrites the latest commit (message and/or tree). Safe only for unpushed commits you own. After amend, the commit hash changes; pushed amends require a coordinated force-push.

## 🔧 Core concepts [#-core-concepts]

* **Message only** — `git commit --amend -m "…"` or editor.
* **Include staged** — stage fixes, then `--amend --no-edit`.
* **Author / date** — `--reset-author` updates author metadata.
* **Hooks** — amend re-runs `commit-msg` / related hooks unless skipped.
* **Recovery** — old commit remains in reflog briefly.

## 💡 Examples [#-examples]

```shellscript
# Fix message
git commit --amend -m "fix: handle null session"

# Add forgotten file to last commit
git add src/missed.ts
git commit --amend --no-edit

# Edit message in editor
git commit --amend

# Reset author to current user
git commit --amend --reset-author --no-edit

# After amend of unpushed commit
git push

# If already pushed (team OK with force-with-lease)
git push --force-with-lease
```

## ⚠️ Pitfalls [#️-pitfalls]

* Amending published commits rewrites shared history — prefer a new commit.
* `--no-verify` skips hooks — avoid unless explicitly required.
* Empty amend (no changes, same message) may be rejected without `--allow-empty`.
* Merge commits / amend during rebase have extra rules — use rebase todo instead.
* Never amend someone else’s commit on a shared branch.

## 🔗 Related [#-related]

* [commit.md](/docs/git/commit)
* [reset.md](/docs/git/reset)
* [reflog.md](/docs/git/reflog)
* [squash.md](/docs/git/squash)
* [push.md](/docs/git/push)
* [hooks.md](/docs/git/hooks)


---

# bisect (/docs/git/bisect)



# bisect [#bisect]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git bisect` binary-searches history to find the commit that introduced a bug. Mark commits `good` / `bad` (or `old` / `new`); automate with `bisect run` and a script that exits 0 (good) or non-zero (bad).

## 🔧 Core concepts [#-core-concepts]

* **Start** — `bisect start`, then mark known bad and good endpoints.
* **Midpoints** — Git checks out a mid commit; you test and mark.
* **Terms** — `good`/`bad` or `old`/`new` (regression vs behavior change).
* **Skip** — untestable commits (`bisect skip`).
* **Run** — `git bisect run ./test.sh` automates the loop.

## 💡 Examples [#-examples]

```shellscript
git bisect start
git bisect bad HEAD
git bisect good v1.2.0

# manually test, then:
git bisect good   # or: git bisect bad

git bisect reset  # return to original branch

# Automated
git bisect start HEAD v1.2.0
git bisect run npm test
# script exit: 0 = good, 1-127 (not 125) = bad, 125 = skip

git bisect skip
git bisect log
git bisect replay bisect-log.txt
```

## ⚠️ Pitfalls [#️-pitfalls]

* Need a reliable test — flaky tests send bisect the wrong way.
* Shallow clones may lack enough history — deepen first.
* Skipped ranges can leave an ambiguous first-bad commit.
* Detached HEAD during bisect — don’t start new feature work mid-bisect.
* Build failures unrelated to the bug should `skip` or fix the script’s exit codes.

## 🔗 Related [#-related]

* [log.md](/docs/git/log)
* [blame.md](/docs/git/blame)
* [checkout via branch.md](/docs/git/branch)
* [reflog.md](/docs/git/reflog)
* [tag.md](/docs/git/tag)
* [diff.md](/docs/git/diff)


---

# blame (/docs/git/blame)



# blame [#blame]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git blame` annotates each line with the commit that last changed it (author, date, SHA). Use it to find when a bug was introduced, then dig with `show` / `bisect`. Ignore whitespace and move detection options reduce noise.

## 🔧 Core concepts [#-core-concepts]

* **Line attribution** — SHA, author, timestamp, line content.
* **Range** — `-L start,end` limits lines.
* **Moves/copies** — `-M` / `-C` detect moved/copied lines.
* **Ignore rev** — `--ignore-rev` / `--ignore-revs-file` skip bulk format commits.
* **GUI** — `git gui blame`, IDE blame views wrap the same data.

## 💡 Examples [#-examples]

```shellscript
git blame path/to/file.ts
git blame -L 40,80 path/to/file.ts
git blame -w path/to/file.ts          # ignore whitespace
git blame -M -C path/to/file.ts       # moves / copies

git show abcdef1
git log -L 40,80:path/to/file.ts

# Ignore noisy formatting commits
echo abcdef1 >> .git-blame-ignore-revs
git config blame.ignoreRevsFile .git-blame-ignore-revs
git blame path/to/file.ts

# Porcelain for scripts
git blame --line-porcelain path/to/file.ts | head
```

## ⚠️ Pitfalls [#️-pitfalls]

* Blame shows last *touch*, not necessarily the logical author of a design.
* Mass reformat commits pollute blame — use ignore-revs.
* Renames without follow can look like wholesale rewrites — try `-C` / history follow.
* Generated files are useless to blame — exclude them.
* Shallow clones may lack the original commit objects.

## 🔗 Related [#-related]

* [log.md](/docs/git/log)
* [bisect.md](/docs/git/bisect)
* [diff.md](/docs/git/diff)
* [gitattributes.md](/docs/git/gitattributes)
* [commit.md](/docs/git/commit)
* [show via log.md](/docs/git/log)


---

# Branch (/docs/git/branch)



# Branch [#branch]

**Git · Reference cheat sheet**

***

## 📖 Overview [#-overview]

Branches are movable pointers to commits. Create feature branches for isolated work, switch with `switch`/`checkout`, and delete when merged. Track remote branches with upstreams for `pull`/`push` defaults.

## 🧩 Core concepts [#-core-concepts]

* **Local branch** — ref under `refs/heads/`.
* **Remote-tracking branch** — e.g. `origin/main` under `refs/remotes/`.
* **Upstream** — `-u` / `--set-upstream-to` links local ↔ remote for defaults.
* **Detached HEAD** — checked out commit is not a branch tip; create a branch before committing.
* **Naming** — `feature/…`, `fix/…`, `chore/…` conventions help navigation.
* **Protection** — host rules may block force-push/delete on `main`.

## 💡 Examples [#-examples]

```shellscript
# List
git branch
git branch -vv
git branch -a

# Create and switch
git switch -c feature/checkout
# equivalent: git checkout -b feature/checkout

# Switch existing
git switch main

# Create from remote tip
git switch -c feature/api origin/feature/api

# Rename
git branch -m feature/checkout feature/cart

# Delete local (merged)
git branch -d feature/cart
git branch -D feature/cart   # force

# Set upstream
git push -u origin feature/cart
git branch --set-upstream-to=origin/main main
```

## ⚠️ Pitfalls [#️-pitfalls]

* Deleting a branch does not delete unmerged work until GC — recover via `reflog` soon.
* Working on detached HEAD loses easy branch pointers — `git switch -c` immediately.
* Stale remote-tracking branches linger until `git fetch --prune`.
* Long-lived branches drift — rebase or merge from main regularly.

## 🔗 Related [#-related]

* [Commit](/docs/git/commit)
* [Merge](/docs/git/merge)
* [Rebase](/docs/git/rebase)
* [Push](/docs/git/push)
* [Pull](/docs/git/pull)


---

# cherry-pick (/docs/git/cherry-pick)



# cherry-pick [#cherry-pick]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git cherry-pick` applies the patch of one or more existing commits onto the current branch as new commits. Use to backport fixes; avoid heavy cherry-picking as a substitute for proper merges/rebases.

## 🔧 Core concepts [#-core-concepts]

* **New SHAs** — picked commits get new hashes (same diff, new parents).
* **Ranges** — `A^..B` or `--no-walk` for explicit lists.
* **Mainline** — `-m 1` when picking merge commits.
* **Continue** — conflict → fix → `--continue` / `--abort` / `--skip`.
* **Sign-off** — `-x` records “cherry picked from” in the message.

## 💡 Examples [#-examples]

```shellscript
git checkout release/1.2
git cherry-pick abcdef1
git cherry-pick -x abcdef1   # note source SHA in message

# Multiple
git cherry-pick abcdef1 1234567
git cherry-pick A^..B

# No auto-commit
git cherry-pick --no-commit abcdef1

# During conflicts
git status
# fix files
git add -u
git cherry-pick --continue
# or
git cherry-pick --abort
```

## ⚠️ Pitfalls [#️-pitfalls]

* Duplicate commits later when merging the original branch (duplicate changes / conflicts).
* Empty cherry-pick if changes already present — `--skip` or abort.
* Merge commits need `-m`; picking merges is often the wrong tool.
* Don’t cherry-pick unpublished WIP that will be rewritten (amended/rebased).
* Binary conflicts and renames can make picks painful — prefer merge for large sets.

## 🔗 Related [#-related]

* [rebase.md](/docs/git/rebase)
* [merge.md](/docs/git/merge)
* [conflict.md](/docs/git/conflict)
* [revert.md](/docs/git/revert)
* [log.md](/docs/git/log)
* [commit.md](/docs/git/commit)


---

# clean (/docs/git/clean)



# clean [#clean]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git clean` deletes untracked files and directories from the working tree. Dry-run first (`-n`). It does not remove ignored files unless `-x` / `-X` is used. Irreversible for files not stored in Git.

## 🔧 Core concepts [#-core-concepts]

* **Untracked** — files not in the index (and not ignored, by default).
* **`-n` / `--dry-run`** — show what would be removed.
* **`-f`** — required unless `clean.requireForce` is false.
* **`-d`** — also remove untracked directories.
* **`-x` / `-X`** — include ignored / only ignored (build artifacts).

## 💡 Examples [#-examples]

```shellscript
git clean -n -d          # preview
git clean -f -d          # delete untracked files + dirs

# Also remove ignored (e.g. dist/, .env.local if ignored)
git clean -n -xd
git clean -f -xd

# Only ignored
git clean -f -X -d

# Interactive
git clean -i -d

# Path limited
git clean -f -d -- apps/web/tmp
```

## ⚠️ Pitfalls [#️-pitfalls]

* No recycle bin — untracked work is gone unless backed up elsewhere.
* `-x` can delete local secrets and IDE files that were gitignored on purpose.
* Don’t clean during a conflicted merge without understanding untracked conflict helpers.
* Nested other repos / submodules need care — clean won’t remove submodule gitlinks.
* Prefer targeted pathspecs over repo-wide `-xd` in large monorepos.

## 🔗 Related [#-related]

* [status.md](/docs/git/status)
* [gitignore.md](/docs/git/gitignore)
* [stash.md](/docs/git/stash)
* [reset.md](/docs/git/reset)
* [stage.md](/docs/git/stage)
* [worktree.md](/docs/git/worktree)


---

# clone (/docs/git/clone)



# clone [#clone]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git clone` copies a remote repository (history, branches, remotes) into a new local directory and checks out the default branch. Use shallow / sparse / filter options for large repos.

## 🔧 Core concepts [#-core-concepts]

* **URL forms** — HTTPS, SSH (`git@host:org/repo.git`), local path.
* **Default remote** — `origin`; default branch from remote HEAD.
* **Depth** — `--depth N` shallow history; `--single-branch` limits refs.
* **Recurse** — `--recurse-submodules` initializes submodules.
* **Bare / mirror** — `--bare`, `--mirror` for server-style copies.

## 💡 Examples [#-examples]

```shellscript
git clone https://github.com/org/repo.git
git clone git@github.com:org/repo.git my-app
cd my-app

# Shallow (CI)
git clone --depth 1 --branch main https://github.com/org/repo.git

# Specific branch only
git clone --single-branch --branch develop git@github.com:org/repo.git

# With submodules
git clone --recurse-submodules git@github.com:org/repo.git

# Existing empty dir
git clone https://github.com/org/repo.git .

# Sparse (partial clone + sparse-checkout)
git clone --filter=blob:none --sparse git@github.com:org/huge.git
cd huge
git sparse-checkout set apps/web
```

## ⚠️ Pitfalls [#️-pitfalls]

* Cloning into a non-empty directory fails unless the dir is empty / `.`.
* Shallow clones limit `blame` / some bisect / merge-base operations.
* Wrong protocol (HTTPS vs SSH) causes auth friction — set remotes intentionally.
* Large LFS repos need Git LFS installed before checkout of pointers.
* `--recurse-submodules` can fail if submodule URLs need credentials.

## 🔗 Related [#-related]

* [init.md](/docs/git/init)
* [remote.md](/docs/git/remote)
* [submodule.md](/docs/git/submodule)
* [sparse\_checkout.md](/docs/git/sparse-checkout)
* [fetch.md](/docs/git/fetch)
* [git\_lfs.md](/docs/git/git-lfs)


---

# Commit (/docs/git/commit)



# Commit [#commit]

**Git · Reference cheat sheet**

***

## 📖 Overview [#-overview]

A commit records a snapshot of the staged index with metadata (author, message, parent). Prefer small, purposeful commits with clear messages; amend only when safe (unpushed, intentional).

## 🧩 Core concepts [#-core-concepts]

* **Snapshot model** — commit points at a tree; parents form history.
* **Message** — subject (+ optional body); conventional prefixes (`feat:`, `fix:`) are team conventions.
* **Amend** — `git commit --amend` rewrites the latest commit (changes hash).
* **Sign-off / GPG** — `-s` / `-S` for DCO or signed commits when required.
* **Empty commits** — `--allow-empty` for CI triggers or markers (rare).
* **Hooks** — `pre-commit` / `commit-msg` can block or rewrite messages.

## 💡 Examples [#-examples]

```shellscript
# Commit staged changes
git commit -m "feat: add login form validation"

# Stage tracked files and commit
git commit -am "fix: handle null user in session"

# Amend message only
git commit --amend -m "feat: add login form validation"

# Amend and include newly staged files (unpushed only)
git add src/login.ts
git commit --amend --no-edit

# Show last commit
git log -1 --stat
git show HEAD

# Skip hooks only if you must (usually avoid)
# git commit --no-verify -m "wip"
```

## ⚠️ Pitfalls [#️-pitfalls]

* Amending a commit already pushed requires force-push — coordinate with the team.
* `-a` ignores untracked files — new files still need `git add`.
* Huge commits are hard to review and revert — split by concern.
* Never put secrets in commit messages or blobs; rewriting history later is painful.

## 🔗 Related [#-related]

* [Stage](/docs/git/stage)
* [Branch](/docs/git/branch)
* [Push](/docs/git/push)
* [Rebase](/docs/git/rebase)
* [Merge](/docs/git/merge)


---

# conflict (/docs/git/conflict)



# conflict [#conflict]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

Conflicts occur when merge, rebase, cherry-pick, or revert can’t auto-apply changes. Git marks files with conflict markers; you resolve, `git add`, then continue the operation. Abort to return to the pre-operation state.

## 🔧 Core concepts [#-core-concepts]

* **Markers** — `&lt;&lt;&lt;&lt;&lt;&lt;&lt;`, `=======`, `>>>>>>>` (ours / theirs depend on command).
* **Ours/theirs** — merge: ours = current branch; rebase: ours = upstream (inverted mental model).
* **Tools** — `git mergetool`, IDE 3-way merge, `diff --cc`.
* **Continue** — `merge --continue` / `rebase --continue` / `cherry-pick --continue`.
* **Abort** — `--abort` restores pre-op state (if possible).

## 💡 Examples [#-examples]

```shellscript
git status   # unmerged paths
# edit files — remove markers, keep correct code
git add path/to/file.ts
git merge --continue   # or rebase / cherry-pick

# Take one side for a file
git checkout --ours -- path/to/file.ts
git checkout --theirs -- path/to/file.ts
git add path/to/file.ts

git merge --abort
git rebase --abort

git diff   # unmerged diff
git mergetool
```

```plaintext
<<<<<<< HEAD
current change
=======
incoming change
>>>>>>> feature
```

## ⚠️ Pitfalls [#️-pitfalls]

* Leaving conflict markers in committed files breaks builds — search for `&lt;&lt;&lt;&lt;&lt;&lt;&lt;`.
* Ours/theirs flip meaning during rebase vs merge — verify with `status` / content.
* Binary conflicts can’t use markers — choose one version explicitly.
* Resolving then forgetting `git add` blocks `--continue`.
* Don’t abort if you’ve already fixed a lot without backup — commit WIP or stash carefully.

## 🔗 Related [#-related]

* [merge.md](/docs/git/merge)
* [rebase.md](/docs/git/rebase)
* [cherry\_pick.md](/docs/git/cherry-pick)
* [revert.md](/docs/git/revert)
* [status.md](/docs/git/status)
* [diff.md](/docs/git/diff)


---

# diff (/docs/git/diff)



# diff [#diff]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git diff` shows changes between worktree, index, commits, and branches. Use it before staging/committing and in code review. Word-diff and path filters help focus on signal.

## 🔧 Core concepts [#-core-concepts]

* **Unstaged** — `git diff` (worktree vs index).
* **Staged** — `git diff --staged` / `--cached` (index vs HEAD).
* **Commits** — `git diff A B`, `git diff A..B`, `A...B` (merge-base).
* **Stats** — `--stat`, `--numstat`, `--name-only`.
* **Options** — `-w` ignore whitespace; `--word-diff`; `-M` renames.

## 💡 Examples [#-examples]

```shellscript
git diff
git diff --staged
git diff HEAD
git diff main...feature --stat

git diff abcdef1 1234567 -- apps/web
git diff --name-only origin/main

# Word / whitespace
git diff --word-diff
git diff -w

# Function context (C/JS often)
git diff -W

# Binary detection
git diff --binary

# Exit code for scripts (0 = no diff)
git diff --quiet || echo "dirty"
```

## ⚠️ Pitfalls [#️-pitfalls]

* `A..B` vs `A...B` differ for branch comparison — `...` uses merge-base (PR-style).
* Line endings / CRLF can create noisy diffs — normalize with `.gitattributes`.
* Generated files and lockfile churn drown real changes — pathspec filter.
* `diff` of binary shows “Binary files differ” — use Git LFS or external tools.
* Submodule diffs show SHA changes only unless you diff inside the submodule.

## 🔗 Related [#-related]

* [status.md](/docs/git/status)
* [stage.md](/docs/git/stage)
* [log.md](/docs/git/log)
* [blame.md](/docs/git/blame)
* [gitattributes.md](/docs/git/gitattributes)
* [commit.md](/docs/git/commit)


---

# Examples (/docs/git/examples)



# Examples [#examples]

Git notes in **Examples**.


---

# Fix Last Commit (/docs/git/examples/fix-last-commit)



# Fix Last Commit [#fix-last-commit]

*Git · Example / how-to*

***

## 📋 Overview [#-overview]

Amend the most recent commit to fix the message or add forgotten files — only when it is safe (not pushed, or you own the branch).

## 🔧 Core concepts [#-core-concepts]

| Piece                | Role                             |
| -------------------- | -------------------------------- |
| `git commit --amend` | Rewrite HEAD commit              |
| Staged changes       | Fold into last commit            |
| Message edit         | `--amend -m` or editor           |
| Safety               | Avoid amending published history |

## 💡 Examples [#-examples]

**Fix message only:**

```shellscript
git commit --amend -m "fix: correct typo in changelog"
```

**Add forgotten files:**

```shellscript
git add path/to/missed_file.ts
git commit --amend --no-edit
```

**Check before amending:**

```shellscript
git status
git log -1 --format='%an %ae %s'
git status -sb   # look for "ahead" vs tracking remote
```

## ⚠️ Pitfalls [#️-pitfalls]

* Never amend commits already pushed to a shared branch unless the team agrees (needs force-push).
* `--no-edit` keeps the old message; use an editor/`-m` when the message should change.
* Hooks may rewrite files on amend — review `git status` after.

## 🔗 Related [#-related]

* [Undo local changes](/docs/git/examples/undo-local-changes)
* [Sync fork branch](/docs/git/examples/sync-fork-branch)


---

# Sync Fork Branch (/docs/git/examples/sync-fork-branch)



# Sync Fork Branch [#sync-fork-branch]

*Git · Example / how-to*

***

## 📋 Overview [#-overview]

Update your fork’s branch from the upstream repository using remotes, fetch, and rebase or merge.

## 🔧 Core concepts [#-core-concepts]

| Piece              | Role                   |
| ------------------ | ---------------------- |
| `upstream` remote  | Original repo          |
| `origin` remote    | Your fork              |
| `fetch`            | Download without merge |
| `rebase` / `merge` | Integrate upstream     |

## 💡 Examples [#-examples]

**One-time remote setup:**

```shellscript
git remote add upstream https://github.com/ORG/REPO.git
git remote -v
```

**Sync main, then update feature branch:**

```shellscript
git fetch upstream
git checkout main
git merge --ff-only upstream/main
git push origin main

git checkout feature/my-work
git rebase main
# or: git merge main
git push origin feature/my-work
```

**If rebase rewrote commits already on the fork:**

```shellscript
git push --force-with-lease origin feature/my-work
```

## ⚠️ Pitfalls [#️-pitfalls]

* Prefer `--force-with-lease` over `--force` to avoid clobbering others’ pushes.
* Confusing `origin` and `upstream` pushes updates to the wrong place.
* Long-lived forks: sync often to reduce conflict size.

## 🔗 Related [#-related]

* [Fix last commit](/docs/git/examples/fix-last-commit)
* [Undo local changes](/docs/git/examples/undo-local-changes)


---

# Undo Local Changes (/docs/git/examples/undo-local-changes)



# Undo Local Changes [#undo-local-changes]

*Git · Example / how-to*

***

## 📋 Overview [#-overview]

Discard or unstage local work safely: restore files, unstage the index, or reset unpushed commits without rewriting remote history.

## 🔧 Core concepts [#-core-concepts]

| Piece           | Role                             |
| --------------- | -------------------------------- |
| `restore`       | Discard working tree / unstage   |
| `reset --soft`  | Move HEAD, keep changes staged   |
| `reset --mixed` | Move HEAD, keep changes unstaged |
| `clean`         | Remove untracked files           |

## 💡 Examples [#-examples]

**Unstage a file (keep edits):**

```shellscript
git restore --staged path/to/file.ts
```

**Discard unstaged edits to a file:**

```shellscript
git restore path/to/file.ts
```

**Undo last local commit, keep changes staged:**

```shellscript
git reset --soft HEAD~1
```

**Undo last local commit, keep changes unstaged:**

```shellscript
git reset HEAD~1
```

**Remove untracked files (dry run first):**

```shellscript
git clean -nd
git clean -fd
```

## ⚠️ Pitfalls [#️-pitfalls]

* `git restore` / `clean -fd` permanently deletes uncommitted work — dry-run first.
* `reset --hard` is destructive; avoid unless you truly want a clean tree.
* Do not reset commits that exist on the remote shared branch.

## 🔗 Related [#-related]

* [Fix last commit](/docs/git/examples/fix-last-commit)
* [Sync fork branch](/docs/git/examples/sync-fork-branch)


---

# Fetch (/docs/git/fetch)



# Fetch [#fetch]

**Git · Reference cheat sheet**

***

## 📖 Overview [#-overview]

`git fetch` downloads objects and updates remote-tracking refs from a remote without changing your working tree or current branch. Use it to inspect upstream changes before merging or rebasing.

## 🧩 Core concepts [#-core-concepts]

* **Remote** — named location (`origin`) with URL(s).
* **Remote-tracking branches** — updated to match the remote (e.g. `origin/main`).
* **Prune** — remove stale remote-tracking refs deleted upstream.
* **Tags** — default fetch may omit tags; `--tags` pulls them.
* **Refspecs** — control which refs are fetched into which local names.
* **Fetch ≠ pull** — pull is fetch + integrate (merge/rebase).

## 💡 Examples [#-examples]

```shellscript
# Fetch default remote
git fetch
git fetch origin

# Fetch all remotes
git fetch --all

# Prune deleted remote branches
git fetch --prune
git fetch origin --prune

# Fetch one branch
git fetch origin main

# Include tags
git fetch --tags

# Inspect after fetch
git log --oneline HEAD..origin/main
git diff main origin/main

# Dry-run prune
git fetch --prune --dry-run
```

## ⚠️ Pitfalls [#️-pitfalls]

* Fetch never updates your checked-out branch — you must merge/rebase/reset intentionally.
* Without prune, deleted remote branches still appear in `git branch -r`.
* Shallow clones (`--depth`) need deepen/unshallow for full history operations.
* Multiple remotes: `git fetch` alone only hits the current branch’s remote (or `origin` by config).

## 🔗 Related [#-related]

* [Pull](/docs/git/pull)
* [Push](/docs/git/push)
* [Merge](/docs/git/merge)
* [Rebase](/docs/git/rebase)
* [Branch](/docs/git/branch)


---

# GH CLI (/docs/git/gh-cli)



# GH CLI [#gh-cli]

**Git · Reference cheat sheet**

***

## 📖 Overview [#-overview]

GitHub CLI (`gh`) manages repositories, pull requests, issues, releases, and Actions from the terminal. Authenticate once, then script common GitHub workflows without leaving the repo.

## 🧩 Core concepts [#-core-concepts]

* **Auth** — `gh auth login` stores credentials (HTTPS or SSH).
* **Repo context** — commands infer the GitHub remote from `origin` (override with `-R owner/repo`).
* **PRs** — create, checkout, review, merge from the CLI.
* **Issues** — list/create/close with labels and assignees.
* **API** — `gh api` for arbitrary REST/GraphQL when no subcommand exists.
* **Actions** — `gh run list/watch` for workflow runs.

## 💡 Examples [#-examples]

```shellscript
# Auth & status
gh auth login
gh auth status

# Repo
gh repo view
gh repo clone owner/name
gh repo create my-app --private --source=. --remote=origin --push

# Pull requests
gh pr status
gh pr list
gh pr create --title "feat: checkout" --body "$(cat <<'EOF'
## Summary
- Add checkout flow

## Test plan
- [ ] Pay with test card
EOF
)"
gh pr checkout 42
gh pr diff 42
gh pr review 42 --approve
gh pr merge 42 --squash --delete-branch

# Issues
gh issue list --label bug
gh issue create --title "Null ref on login" --body "Steps…"
gh issue close 7

# Actions
gh run list --limit 10
gh run watch
gh run view 123456 --log-failed

# API escape hatch
gh api user
gh api repos/{owner}/{repo}/pulls --jq '.[].title'
```

## ⚠️ Pitfalls [#️-pitfalls]

* Wrong remote/`gh` repo context operates on a different project — confirm with `gh repo view`.
* `gh pr create` needs a pushed branch with an upstream.
* Org SSO may require `gh auth refresh -h github.com -s read:org` (or similar) after login.
* Scripting merges still respects branch protection — expect interactive or admin failures.

## 🔗 Related [#-related]

* [Push](/docs/git/push)
* [Pull](/docs/git/pull)
* [Branch](/docs/git/branch)
* [Commit](/docs/git/commit)
* [Fetch](/docs/git/fetch)


---

# Git LFS (/docs/git/git-lfs)



# Git LFS [#git-lfs]

**Git · Reference cheat sheet**

***

## 📖 Overview [#-overview]

Git Large File Storage (LFS) replaces large binaries in Git history with lightweight pointer files while storing blobs on an LFS server. Track patterns early — migrating after the fact requires history rewrite.

## 🧩 Core concepts [#-core-concepts]

* **Pointers** — small text files in Git; real content fetched via LFS smudge/clean filters.
* **`git lfs track`** — writes patterns into `.gitattributes`.
* **Install** — `git lfs install` sets up local hooks/filters once per user machine.
* **Fetch/pull** — LFS objects download on checkout; `git lfs pull` fetches explicitly.
* **Locks** — optional file locking for non-mergeable binaries.
* **Storage quotas** — hosts (GitHub, etc.) meter LFS bandwidth/storage.

## 💡 Examples [#-examples]

```shellscript
# Install CLI (platform-specific) then enable filters
git lfs install

# Track file types (updates .gitattributes)
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "design/**/*.sketch"
git add .gitattributes
git commit -m "chore: track design assets with Git LFS"

# Status / list
git lfs status
git lfs ls-files

# Fetch LFS objects
git lfs fetch --all
git lfs pull

# Migrate existing history (destructive — coordinate)
git lfs migrate import --include="*.psd" --everything

# Locking (if enabled on remote)
git lfs lock path/to/file.psd
git lfs unlock path/to/file.psd
```

Pointer file shape (what Git stores):

```plaintext
version https://git-lfs.github.com/spec/v1
oid sha256:…
size 12345678
```

## ⚠️ Pitfalls [#️-pitfalls]

* Tracking after files were committed still leaves blobs in history until migrate/rewrite.
* Clones without LFS installed see pointer files instead of real assets.
* CI must install Git LFS or checkouts will be incomplete.
* Exceeding host LFS quotas breaks pushes — monitor usage and prune unused objects.

## 🔗 Related [#-related]

* [Gitattributes](/docs/git/gitattributes)
* [Gitignore](/docs/git/gitignore)
* [Push](/docs/git/push)
* [Commit](/docs/git/commit)
* [GH CLI](/docs/git/gh-cli)


---

# Gitattributes (/docs/git/gitattributes)



# Gitattributes [#gitattributes]

**Git · Reference cheat sheet**

***

## 📖 Overview [#-overview]

`.gitattributes` assigns attributes to paths: line-ending normalization, diff/merge drivers, linguist overrides, and Git LFS filters. Keep it committed so every clone behaves the same.

## 🧩 Core concepts [#-core-concepts]

* **`text` / `eol`** — normalize LF in the repo; checkout `lf` or `crlf` per path.
* **`binary`** — skip text conversion/diff for binaries.
* **`diff` / `merge`** — custom drivers for generated or vendor files.
* **`export-ignore`** — omit paths from `git archive`.
* **Linguist** — `linguist-language`, `linguist-vendored`, `linguist-generated` for GitHub stats.
* **LFS filter** — `filter=lfs diff=lfs merge=lfs -text` for large files.

## 💡 Examples [#-examples]

```ini
# Normalize text; force LF in working tree for these
* text=auto eol=lf
*.sh text eol=lf
*.bat text eol=crlf
*.ps1 text eol=lf

# Binaries
*.png binary
*.jpg binary
*.pdf binary
*.zip binary

# Generated / vendored (GitHub Linguist)
dist/** linguist-generated=true
vendor/** linguist-vendored=true

# Custom diff for lockfiles (optional)
package-lock.json -diff
pnpm-lock.yaml -diff

# LFS (after git lfs track)
*.psd filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text

# Archives
docs/internal/** export-ignore
```

```shellscript
# Refresh working tree after attributes change
git add --renormalize .
git status
```

## ⚠️ Pitfalls [#️-pitfalls]

* Changing `eol` mid-project causes huge diffs unless you renormalize carefully.
* Marking text as `binary` hides useful diffs and can complicate merges.
* LFS patterns belong here *and* need `git lfs install` on each machine.
* Attributes are path-based — rename/move files can drop intended rules if patterns are too narrow.

## 🔗 Related [#-related]

* [Gitignore](/docs/git/gitignore)
* [Git LFS](/docs/git/git-lfs)
* [Commit](/docs/git/commit)
* [Merge](/docs/git/merge)
* [Stage](/docs/git/stage)


---

# Gitignore (/docs/git/gitignore)



# Gitignore [#gitignore]

**Git · Reference cheat sheet**

***

## 📖 Overview [#-overview]

`.gitignore` lists patterns Git should treat as untracked noise (build output, deps, secrets, OS junk). Patterns apply to untracked files; already-tracked files stay tracked until removed from the index.

## 🧩 Core concepts [#-core-concepts]

* **Pattern syntax** — globs (`*.log`), directories (`dist/`), negation (`!important.log`).
* **Scoped rules** — root `.gitignore`, nested ignores, and global `core.excludesFile`.
* **`/` anchoring** — leading `/` anchors to the file’s directory; trailing `/` means directory.
* **`**` recursion** — matches across directories depending on position.
* **Check-ignore** — debug why a path is ignored.
* **Un-ignore tracked files** — `git rm -r --cached` then commit.

## 💡 Examples [#-examples]

```ini
# Dependencies & build
node_modules/
dist/
build/
*.tsbuildinfo

# Env & secrets
.env
.env.*
!.env.example

# Logs & caches
*.log
.cache/
.coverage/

# OS / IDE
.DS_Store
Thumbs.db
.idea/
.vscode/*
!.vscode/extensions.json
```

```shellscript
# Test a path
git check-ignore -v path/to/file

# Stop tracking without deleting the file
git rm -r --cached node_modules
git rm --cached .env
git commit -m "chore: stop tracking local env and deps"

# Global ignores
git config --global core.excludesFile ~/.gitignore_global
```

## ⚠️ Pitfalls [#️-pitfalls]

* Ignoring after `git add` does nothing until you untrack with `--cached`.
* Negation (`!`) cannot re-include a file inside an ignored parent directory easily — un-ignore parents carefully.
* Committing `.env` once leaves secrets in history — rotate keys and consider history rewrite/BFG.
* Over-broad `*` patterns can hide files you meant to commit.

## 🔗 Related [#-related]

* [Gitattributes](/docs/git/gitattributes)
* [Stage](/docs/git/stage)
* [Commit](/docs/git/commit)
* [Git LFS](/docs/git/git-lfs)
* [GH CLI](/docs/git/gh-cli)


---

# Glossary (/docs/git/glossary)



# Glossary [#glossary]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

Alphabetical glossary of core Git terms for commits, branches, remotes, history rewriting, and collaboration workflows.

## 🔧 Core concepts [#-core-concepts]

| Term          | Definition                                                                   |
| ------------- | ---------------------------------------------------------------------------- |
| Amend         | Rewriting the latest commit by adding staged changes or editing its message. |
| Branch        | A movable pointer to a commit, usually representing a line of development.   |
| Cherry-pick   | Copying a commit’s changes onto another branch as a new commit.              |
| Clone         | Creating a local copy of a remote repository including history.              |
| Commit        | A snapshot of the staged project state with metadata and a parent link.      |
| Conflict      | Overlapping changes Git cannot auto-merge and must be resolved by hand.      |
| Detached HEAD | A state where HEAD points at a commit, not a branch name.                    |
| Diff          | A patch showing line-level changes between two trees or commits.             |
| Fast-forward  | A merge that simply moves a branch pointer forward with no merge commit.     |
| Fetch         | Downloading remote commits and refs without updating local branches.         |
| HEAD          | The symbolic ref pointing at the current branch or checked-out commit.       |
| Hook          | A script Git runs on events like `pre-commit` or `pre-push`.                 |
| Index         | The staging area holding the next commit’s proposed snapshot.                |
| Merge         | Combining histories from two branches into one.                              |
| Origin        | The conventional default name for a cloned remote.                           |
| Pull          | Fetching from a remote and integrating into the current branch.              |
| Push          | Uploading local commits to a remote branch.                                  |
| Rebase        | Replaying commits onto another base to linearize history.                    |
| Reflog        | A local log of where HEAD and branch tips have pointed.                      |
| Remote        | A named URL pointing at another repository copy.                             |
| Reset         | Moving a branch pointer (and optionally index/worktree) to another commit.   |
| Revert        | Creating a new commit that undoes a previous commit’s changes.               |
| Stash         | Temporarily shelving uncommitted worktree changes.                           |
| Tag           | A named marker for a specific commit, often used for releases.               |
| Worktree      | An additional working directory attached to the same repository.             |

## 💡 Examples [#-examples]

**Stage and commit:**

```shellscript
git status
git add README.md
git commit -m "docs: clarify install steps"
```

**Branch, merge, and push:**

```shellscript
git switch -c feature/login
# ... edits ...
git switch main
git merge feature/login
git push origin main
```

**Stash and rebase:**

```shellscript
git stash push -m "wip"
git pull --rebase origin main
git stash pop
```

## ⚠️ Pitfalls [#️-pitfalls]

* Confusing **reset** (moves branch/history locally) with **revert** (adds an undo commit).
* Mixing **fetch** (download only) with **pull** (download + integrate).
* Treating **merge** and **rebase** as identical — history shape and conflict timing differ.
* Equating **amend** on a pushed commit with a safe local edit — rewriting published history needs force-push care.
* Assuming **stash** is a backup — it is local and easy to drop accidentally.

## 🔗 Related [#-related]

* [commit](/docs/git/commit)
* [branch](/docs/git/branch)
* [merge](/docs/git/merge)
* [rebase](/docs/git/rebase)
* [stash](/docs/git/stash)
* [remote](/docs/git/remote)


---

# hooks (/docs/git/hooks)



# hooks [#hooks]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

Git hooks are scripts that run on events (commit, push, merge). Client hooks live in `.git/hooks/`; teams often share them via Husky, pre-commit framework, or `core.hooksPath`. Use hooks to lint, test, and block bad commits — keep them fast.

## 🔧 Core concepts [#-core-concepts]

| Hook                           | When                            |
| ------------------------------ | ------------------------------- |
| `pre-commit`                   | Before commit object is created |
| `commit-msg`                   | Validate/edit message           |
| `pre-push`                     | Before refs are pushed          |
| `post-checkout` / `post-merge` | After switch/merge              |
| `pre-receive` (server)         | Before updating remote refs     |

* **Sample hooks** — `.git/hooks/*.sample` (disabled until renamed).
* **Skip** — `--no-verify` bypasses client hooks (use sparingly).
* **Shared path** — `git config core.hooksPath .githooks`.

## 💡 Examples [#-examples]

```shellscript
# Enable a sample
cp .git/hooks/pre-commit.sample .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit

# Shared hooks in repo
mkdir -p .githooks
git config core.hooksPath .githooks

# .githooks/pre-commit
#!/usr/bin/env bash
set -euo pipefail
npm run lint
npm run typecheck

# Skip once (emergency)
git commit --no-verify -m "wip"
```

```shellscript
# pre-commit framework (Python) / Husky (Node) install hooks for the team
```

## ⚠️ Pitfalls [#️-pitfalls]

* Hooks in `.git/hooks` aren’t versioned — without `hooksPath`/tooling, teammates miss them.
* Slow `pre-commit` trains people to `--no-verify`.
* Hooks must be executable on Unix; Windows needs compatible runners.
* Server-side hooks are the real enforcement for protected repos.
* Don’t put secrets in hook scripts committed to the repo.

## 🔗 Related [#-related]

* [commit.md](/docs/git/commit)
* [amend.md](/docs/git/amend)
* [push.md](/docs/git/push)
* [init.md](/docs/git/init)
* [status.md](/docs/git/status)
* [gitignore.md](/docs/git/gitignore)


---

# init (/docs/git/init)



# init [#init]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git init` creates a new repository (a `.git` directory) in the current or given folder. Optionally set the initial branch name and template; then add a remote and make the first commit.

## 🔧 Core concepts [#-core-concepts]

* **Repo root** — `.git/` holds objects, refs, config.
* **Initial branch** — `-b main` (or `init.defaultBranch`).
* **Bare** — `git init --bare` for remotes without a working tree.
* **Template** — `--template=<dir>` copies hooks/info.
* **Reinit** — safe to re-run; won’t overwrite existing history.

## 💡 Examples [#-examples]

```shellscript
mkdir my-app && cd my-app
git init -b main

# Or
git init
git branch -M main

echo "# my-app" > README.md
git add README.md
git commit -m "chore: initial commit"

git remote add origin git@github.com:org/my-app.git
git push -u origin main

# Bare remote-style repo
git init --bare /srv/git/my-app.git

# Shared permissions (server)
git init --shared=group
```

## ⚠️ Pitfalls [#️-pitfalls]

* Don’t `git init` inside an existing repo unless you intend a nested repo (usually wrong).
* Forgetting `.gitignore` before the first add can commit secrets/build artifacts.
* Default branch may still be `master` on older Git — set `-b main` explicitly.
* Bare repos have no working tree — don’t develop directly in them.
* Nested `git init` in monorepo packages breaks tooling — use one root repo.

## 🔗 Related [#-related]

* [clone.md](/docs/git/clone)
* [commit.md](/docs/git/commit)
* [remote.md](/docs/git/remote)
* [gitignore.md](/docs/git/gitignore)
* [hooks.md](/docs/git/hooks)
* [stage.md](/docs/git/stage)


---

# log (/docs/git/log)



# log [#log]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git log` walks commit history with filters, formatting, and graphs. Use it to audit changes, find authors, and prepare release notes. Pair with `git show` for a single commit’s patch.

## 🔧 Core concepts [#-core-concepts]

* **Range** — `A..B`, `A...B` (symmetric), path-limited history.
* **Decorate** — branch/tag names on commits (`--decorate`).
* **Format** — `--oneline`, `--graph`, pretty formats (`%h %an %s`).
* **Filters** — `--author`, `--grep`, `--since` / `--until`, `-S` / `-G` pickaxe.
* **Follow** — `--follow` for single-file renames (limited).

## 💡 Examples [#-examples]

```shellscript
git log --oneline --graph --decorate -20
git log main..HEAD --oneline
git log --since="2026-01-01" --author="Ada" --oneline

# Patch for each commit
git log -p -- path/to/file.ts

# Find commits that added/removed a string
git log -S "featureFlag" --oneline
git log -G "featureFlag\s*=" --oneline

# Custom format
git log --pretty=format:"%h %ad %an %s" --date=short

# First parent only (linearize merges)
git log --first-parent main

# Tags / merges
git log --merges --oneline
git log v1.0.0..v1.1.0 --oneline
```

## ⚠️ Pitfalls [#️-pitfalls]

* `A..B` means reachable from B not from A — order matters.
* `--follow` only works with a single path.
* Shallow clones truncate history — deepen with `git fetch --unshallow`.
* Default pager may hide output — `GIT_PAGER=cat` or `--no-pager`.
* Rewritten history (rebase/amend) changes hashes — don’t rely on old SHAs.

## 🔗 Related [#-related]

* [reflog.md](/docs/git/reflog)
* [blame.md](/docs/git/blame)
* [diff.md](/docs/git/diff)
* [tag.md](/docs/git/tag)
* [bisect.md](/docs/git/bisect)
* [show via commit.md](/docs/git/commit)


---

# Merge (/docs/git/merge)



# Merge [#merge]

**Git · Reference cheat sheet**

***

## 📖 Overview [#-overview]

`git merge` joins histories by integrating another branch into the current one. Fast-forward moves the pointer when possible; otherwise Git creates a merge commit. Resolve conflicts, then complete the merge commit.

## 🧩 Core concepts [#-core-concepts]

* **Fast-forward** — no merge commit if current tip is ancestor of incoming.
* **True merge** — creates a commit with two parents when histories diverged.
* **`--no-ff`** — always create a merge commit (preserves feature-branch topology).
* **`--squash`** — stage combined changes without a merge commit (then commit yourself).
* **Conflict markers** — edit files, `git add`, then `git commit` / `git merge --continue`.
* **Abort** — `git merge --abort` returns to pre-merge state.

## 💡 Examples [#-examples]

```shellscript
git switch main
git fetch origin
git merge origin/main

# Feature into main
git switch main
git merge --no-ff feature/checkout

# Squash merge locally
git merge --squash feature/checkout
git commit -m "feat: checkout flow"

# During conflicts
git status
# edit files, remove <<<<<<< ======= >>>>>>> markers
git add path/to/file
git commit   # completes merge

# Abort
git merge --abort

# Prefer ff-only on release branches
git merge --ff-only origin/main
```

## ⚠️ Pitfalls [#️-pitfalls]

* Merging the wrong direction (main into feature vs feature into main) confuses PR history.
* Leaving conflict markers in committed files breaks builds — search for `&lt;&lt;&lt;&lt;&lt;&lt;&lt;`.
* Squash merges on the remote make local feature branches diverge — delete/recreate after.
* Recursive/ort strategies handle most text; binary conflicts need manual choice.

## 🔗 Related [#-related]

* [Rebase](/docs/git/rebase)
* [Pull](/docs/git/pull)
* [Branch](/docs/git/branch)
* [Commit](/docs/git/commit)
* [Fetch](/docs/git/fetch)


---

# Pull (/docs/git/pull)



# Pull [#pull]

**Git · Reference cheat sheet**

***

## 📖 Overview [#-overview]

`git pull` fetches from a remote and integrates into the current branch. Default integration is merge; configure or pass `--rebase` for a linear history. Prefer an explicit fetch + review when the update is risky.

## 🧩 Core concepts [#-core-concepts]

* **Fetch + integrate** — updates remote-tracking refs, then merge or rebase.
* **Upstream** — pull uses the branch’s configured remote/merge ref.
* **`--rebase`** — replay local commits on top of the updated tip.
* **`--ff-only`** — refuse non-fast-forward updates (safe default for shared mains).
* **Autostash** — `--autostash` stashes dirty worktree around rebase/merge.
* **Conflict handling** — same as merge/rebase; finish with commit or `rebase --continue`.

## 💡 Examples [#-examples]

```shellscript
# Pull current upstream (merge)
git pull

# Pull with rebase
git pull --rebase
git pull --rebase origin main

# Fast-forward only
git pull --ff-only

# Explicit remote/branch
git pull origin main

# Autostash local changes
git pull --rebase --autostash

# Safer workflow: fetch, inspect, then integrate
git fetch origin
git log --oneline HEAD..origin/main
git merge --ff-only origin/main
# or: git rebase origin/main
```

Set rebase-by-default for pulls (optional):

```shellscript
git config pull.rebase true
git config pull.ff only
```

## ⚠️ Pitfalls [#️-pitfalls]

* Blind `git pull` on a dirty tree can create messy conflict states — stash or commit first.
* Mixing merge pulls and rebase pulls on the same branch confuses history.
* Pulling with divergent histories creates merge commits unless you rebase/ff-only.
* After a rebased pull of commits already pushed, you may need a force-with-lease push.

## 🔗 Related [#-related]

* [Fetch](/docs/git/fetch)
* [Merge](/docs/git/merge)
* [Rebase](/docs/git/rebase)
* [Push](/docs/git/push)
* [Branch](/docs/git/branch)


---

# Push (/docs/git/push)



# Push [#push]

**Git · Reference cheat sheet**

***

## 📖 Overview [#-overview]

`git push` uploads local commits (and optionally tags) to a remote. Set an upstream once with `-u`, prefer `--force-with-lease` over `--force`, and push tags deliberately.

## 🧩 Core concepts [#-core-concepts]

* **Upstream** — `-u` records remote/branch for future `push`/`pull`.
* **Fast-forward** — remote tip must be ancestor unless forced.
* **Force-with-lease** — refuses overwrite if remote moved unexpectedly.
* **Refspecs** — `git push origin local:remote` maps branches explicitly.
* **Tags** — `git push --tags` or push a single tag by name.
* **Delete remote branch** — `git push origin --delete branch`.

## 💡 Examples [#-examples]

```shellscript
# First push of a feature branch
git push -u origin feature/checkout

# Subsequent pushes
git push

# Push to explicit remote/branch
git push origin main

# Safe force after rebase (preferred)
git push --force-with-lease origin feature/checkout

# Push one tag / all tags
git push origin v1.2.0
git push --tags

# Delete remote branch
git push origin --delete feature/checkout

# Dry run
git push --dry-run
```

## ⚠️ Pitfalls [#️-pitfalls]

* `--force` can destroy others’ commits — use `--force-with-lease` and branch protections.
* Pushing to the wrong remote/branch is common with multiple remotes — check `git remote -v`.
* Large binary blobs bloat history — use Git LFS before the first push.
* CI/CD may reject unsigned commits or unprotected force pushes on `main`.

## 🔗 Related [#-related]

* [Pull](/docs/git/pull)
* [Fetch](/docs/git/fetch)
* [Branch](/docs/git/branch)
* [Rebase](/docs/git/rebase)
* [Git LFS](/docs/git/git-lfs)


---

# Rebase (/docs/git/rebase)



# Rebase [#rebase]

**Git · Reference cheat sheet**

***

## 📖 Overview [#-overview]

`git rebase` replays commits onto a new base, rewriting history for a linear sequence. Use it to update a feature branch onto `main`, clean up before sharing, and avoid unnecessary merge commits. Do not rebase commits already shared unless the team agrees.

## 🧩 Core concepts [#-core-concepts]

* **Replay** — take commits after the merge-base and apply onto the upstream tip.
* **Interactive (`-i`)** — reorder, squash, reword, drop, edit commits.
* **Continue / abort / skip** — resolve conflicts then `rebase --continue`.
* **Onto** — `git rebase --onto` for advanced history surgery.
* **Autosquash** — works with `fixup!` / `squash!` commit messages.
* **Update refs** — rewritten commits get new SHAs; remotes need force-with-lease.

## 💡 Examples [#-examples]

```shellscript
# Update feature branch onto latest main
git switch feature/checkout
git fetch origin
git rebase origin/main

# Interactive cleanup
git rebase -i origin/main
# pick / reword / squash / fixup / drop

# Continue after conflicts
git add .
git rebase --continue

git rebase --abort
git rebase --skip

# Rebase onto a different cut point
git rebase --onto main old-base feature/checkout

# Pull with rebase
git pull --rebase origin main
```

## ⚠️ Pitfalls [#️-pitfalls]

* Rebasing published history rewrites SHAs — collaborators must reset/rebase carefully.
* Never rebase `main`/`master` that others base work on without coordination.
* Long conflict chains: abort and merge instead if the cost is too high.
* Avoid interactive rebase in environments that cannot provide a real editor session.

## 🔗 Related [#-related]

* [Merge](/docs/git/merge)
* [Pull](/docs/git/pull)
* [Push](/docs/git/push)
* [Commit](/docs/git/commit)
* [Branch](/docs/git/branch)


---

# reflog (/docs/git/reflog)



# reflog [#reflog]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

The reflog records when HEAD and branch tips moved locally (commit, checkout, reset, rebase). Use it to recover “lost” commits after reset/amend/rebase. Reflogs are local and expire (default \~90 days).

## 🔧 Core concepts [#-core-concepts]

* **Entries** — `HEAD@\{n\}`, `main@\{yesterday\}`, timestamps.
* **Scope** — per-ref reflogs (`git reflog show main`) + `HEAD` reflog.
* **Recover** — find SHA → `checkout` / `branch` / `reset` to it.
* **Expire** — `gc` / `reflog expire` prune old entries.
* **Not pushed** — remotes don’t have your reflog.

## 💡 Examples [#-examples]

```shellscript
git reflog
git reflog show main
git reflog --date=iso

# Recover after hard reset
git reset --hard HEAD@{1}
# or
git branch recover-me abcdef1

# After failed rebase
git reflog | head
git reset --hard HEAD@{5}

# Relative time
git show main@{2.days.ago}

git reflog expire --expire=30.days --all
git gc --prune=now
```

## ⚠️ Pitfalls [#️-pitfalls]

* Expired / GC’d objects can’t be recovered — act sooner than later.
* Reflog doesn’t help on another machine — push recovery branches if needed.
* `@\{u\}` is upstream, not reflog — different syntax.
* Don’t confuse reflog index `HEAD@\{1\}` with commit parent `HEAD~1`.
* Sensitive SHAs in reflog remain until expiry — consider security on shared disks.

## 🔗 Related [#-related]

* [reset.md](/docs/git/reset)
* [amend.md](/docs/git/amend)
* [rebase.md](/docs/git/rebase)
* [log.md](/docs/git/log)
* [stash.md](/docs/git/stash)
* [branch.md](/docs/git/branch)


---

# remote (/docs/git/remote)



# remote [#remote]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

Remotes are named URLs for other repositories (`origin`, `upstream`). Manage fetch/push URLs, prune stale refs, and track branches. Most day-to-day sync uses `fetch` / `pull` / `push` against remotes.

## 🔧 Core concepts [#-core-concepts]

* **Add / rename / remove** — `remote add`, `rename`, `remove`.
* **URL** — `remote set-url`, separate pushurl if needed.
* **Verbose** — `remote -v` lists fetch/push URLs.
* **Prune** — delete local remote-tracking branches removed upstream.
* **Upstream** — fork workflow: `origin` = your fork, `upstream` = canonical.

## 💡 Examples [#-examples]

```shellscript
git remote -v
git remote add origin git@github.com:you/app.git
git remote add upstream git@github.com:org/app.git

git remote rename origin old-origin
git remote remove old-origin

git remote set-url origin git@github.com:you/app.git
git remote set-url --push origin https://github.com/you/app.git

git fetch upstream
git remote prune origin
git fetch --prune

# Show details
git remote show origin

# Tracking
git branch -vv
git push -u origin HEAD
```

## ⚠️ Pitfalls [#️-pitfalls]

* Multiple remotes with similar names cause pushes to the wrong place — check `-v`.
* Changing URL doesn’t rewrite existing remote-tracking history.
* Credential helpers differ for HTTPS vs SSH — fix auth at the remote URL layer.
* `prune` deletes remote-tracking refs, not local branches — still delete locals yourself.
* Mirror / bare remotes have different push semantics.

## 🔗 Related [#-related]

* [clone.md](/docs/git/clone)
* [fetch.md](/docs/git/fetch)
* [push.md](/docs/git/push)
* [pull.md](/docs/git/pull)
* [branch.md](/docs/git/branch)
* [gh\_cli.md](/docs/git/gh-cli)


---

# reset (/docs/git/reset)



# reset [#reset]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git reset` moves HEAD (and optionally the index / worktree) to a target commit. Soft / mixed / hard modes control how much is discarded. Prefer `restore` for unstaging/discarding file content without moving HEAD.

## 🔧 Core concepts [#-core-concepts]

| Mode                | HEAD  | Index        | Worktree     |
| ------------------- | ----- | ------------ | ------------ |
| `--soft`            | moves | kept         | kept         |
| `--mixed` (default) | moves | matches HEAD | kept         |
| `--hard`            | moves | matches HEAD | matches HEAD |

* **Path reset** — `git reset HEAD -- file` unstages (mixed on paths).
* **vs revert** — reset rewrites history; revert adds a new undo commit.
* **vs restore** — `git restore --staged` / `--worktree` for file-level ops.

## 💡 Examples [#-examples]

```shellscript
# Unstage all / one file
git reset HEAD
git reset HEAD -- src/app.ts

# Undo last commit, keep changes staged
git reset --soft HEAD~1

# Undo last commit, keep changes unstaged
git reset HEAD~1

# Destroy local commits + changes (dangerous)
git reset --hard HEAD~1
git reset --hard origin/main

# Move branch tip to a SHA
git reset --hard abcdef1
```

## ⚠️ Pitfalls [#️-pitfalls]

* `--hard` deletes uncommitted work — confirm with `status` / stash first.
* Never reset published commits others use — use `revert` instead.
* After reset of pushed commits, force-push is required (coordinate with team).
* Detached HEAD + reset can orphan commits — recover via `reflog`.
* Pathspec reset doesn’t move branch tip — only affects index entries.

## 🔗 Related [#-related]

* [revert.md](/docs/git/revert)
* [reflog.md](/docs/git/reflog)
* [amend.md](/docs/git/amend)
* [stage.md](/docs/git/stage)
* [status.md](/docs/git/status)
* [commit.md](/docs/git/commit)


---

# revert (/docs/git/revert)



# revert [#revert]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git revert` creates new commits that undo the changes of prior commits. Safe for shared branches because history is not rewritten. Use for undoing merges and published mistakes.

## 🔧 Core concepts [#-core-concepts]

* **Inverse patch** — applies the opposite of the selected commit(s).
* **Non-destructive** — original commits remain in history.
* **Ranges** — can revert multiple commits (order matters).
* **Merges** — `-m 1` specifies mainline parent for merge commits.
* **No-commit** — `--no-commit` applies inverses and leaves staging for one commit.

## 💡 Examples [#-examples]

```shellscript
# Undo a single commit on main
git revert abcdef1
git revert HEAD

# Revert without auto-commit
git revert --no-commit abcdef1
git commit -m "revert: undo broken feature flag"

# Sequence (oldest..newest often clearer with -n then one commit)
git revert --no-commit bad1^..bad3
git commit -m "revert: roll back bad1..bad3"

# Revert a merge commit (keep first parent line)
git revert -m 1 mergecommitsha

# Abort conflicted revert
git revert --abort
```

## ⚠️ Pitfalls [#️-pitfalls]

* Reverting a merge without `-m` fails — pick the parent to keep.
* Re-reverting later can be confusing if the original feature is re-applied.
* Conflicts still happen when later commits touch the same lines.
* Don’t confuse with `reset` — revert is for published history.
* Empty revert (changes already undone) may need `--skip` or abort.

## 🔗 Related [#-related]

* [reset.md](/docs/git/reset)
* [conflict.md](/docs/git/conflict)
* [log.md](/docs/git/log)
* [commit.md](/docs/git/commit)
* [merge.md](/docs/git/merge)
* [cherry\_pick.md](/docs/git/cherry-pick)


---

# sparse-checkout (/docs/git/sparse-checkout)



# sparse-checkout [#sparse-checkout]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

Sparse-checkout checks out only a subset of paths from a wide repository (monorepos). Combine with partial clone (`--filter=blob:none`) to reduce network and disk use. Cone mode is the recommended pattern.

## 🔧 Core concepts [#-core-concepts]

* **Cone mode** — directory-based patterns (default/recommended).
* **Patterns** — include dirs like `apps/web` and always root files needed.
* **Init** — `sparse-checkout init --cone` then `set` / `add`.
* **Partial clone** — fetch blobs on demand with filters.
* **Disable** — `sparse-checkout disable` restores full tree.

## 💡 Examples [#-examples]

```shellscript
git clone --filter=blob:none --sparse git@github.com:org/monorepo.git
cd monorepo
git sparse-checkout set apps/web packages/ui

# Add more paths later
git sparse-checkout add packages/utils

# List / reapply
git sparse-checkout list
git sparse-checkout reapply

# Non-cone (legacy patterns) — avoid unless needed
git sparse-checkout init --no-cone
git sparse-checkout set "/*" "!/*/" "/apps/web/"

git sparse-checkout disable
```

## ⚠️ Pitfalls [#️-pitfalls]

* Tools expecting a full tree (some codegen, IDE indexes) may break — document required paths.
* Non-cone pattern syntax is easy to get wrong — prefer cone directories.
* Sparse + submodules needs explicit submodule paths checked out.
* CI must configure the same sparse set or use full checkout.
* Narrow checkouts can hide files from `git status` that still exist in history.

## 🔗 Related [#-related]

* [clone.md](/docs/git/clone)
* [status.md](/docs/git/status)
* [submodule.md](/docs/git/submodule)
* [worktree.md](/docs/git/worktree)
* [gitignore.md](/docs/git/gitignore)
* [fetch.md](/docs/git/fetch)


---

# squash (/docs/git/squash)



# squash [#squash]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

Squashing combines multiple commits into one (or fewer) for a cleaner history before merge. Common via interactive rebase, `merge --squash`, or soft reset. Prefer squashing on feature branches, not on shared long-lived branches.

## 🔧 Core concepts [#-core-concepts]

* **Interactive rebase** — `pick` + `squash`/`fixup` in `git rebase -i`.
* **Merge squash** — `git merge --squash feature` stages combined diff; you commit once.
* **Soft reset** — `git reset --soft main` then one new commit.
* **fixup** — like squash but discards the squashed commit’s message by default.
* **Autosquash** — `commit --fixup` + `rebase -i --autosquash`.

## 💡 Examples [#-examples]

```shellscript
# Interactive: last 5 commits
git rebase -i HEAD~5
# change pick → squash/fixup on commits to fold

# Soft reset onto main
git checkout feature
git reset --soft main
git commit -m "feat: add billing portal"

# Squash merge (keeps feature branch commits locally)
git checkout main
git merge --squash feature
git commit -m "feat: add billing portal"

# Fixup workflow
git commit --fixup abcdef1
git rebase -i --autosquash abcdef1^
```

## ⚠️ Pitfalls [#️-pitfalls]

* Squashing rewritten commits that were pushed needs force-with-lease.
* Losing detailed commit messages — keep a good final message / notes.
* Squash-merge on GitHub makes the PR branch diverge — delete/rebuild branches.
* Don’t squash commits that are merge bases for other work still in flight.
* Conflicts during rebase squash still need resolution per step.

## 🔗 Related [#-related]

* [rebase.md](/docs/git/rebase)
* [merge.md](/docs/git/merge)
* [amend.md](/docs/git/amend)
* [reset.md](/docs/git/reset)
* [commit.md](/docs/git/commit)
* [log.md](/docs/git/log)


---

# Stage (/docs/git/stage)



# Stage [#stage]

**Git · Reference cheat sheet**

***

## 📖 Overview [#-overview]

Staging selects which changes enter the next commit via the index (staging area). Use pathspecs and patch mode to craft focused commits instead of dumping the whole working tree.

## 🧩 Core concepts [#-core-concepts]

* **Index / staging area** — snapshot between working tree and `HEAD`.
* **`git add`** — stage new/modified files; `git add -u` stages tracked updates/deletes.
* **`git restore --staged`** — unstage while keeping working-tree edits.
* **Patch staging** — `git add -p` stages hunks interactively.
* **Intent to add** — `git add -N` tracks a new file as empty for diffing.
* **Status** — `git status` / `git diff --cached` inspect staged vs unstaged.

## 💡 Examples [#-examples]

```shellscript
# Stage specific paths
git add README.md src/app.ts
git add src/

# Stage all tracked modifications + deletes (not untracked)
git add -u

# Stage everything under the repo (respects .gitignore)
git add -A

# Interactive hunks
git add -p src/app.ts

# Unstage
git restore --staged src/app.ts
git restore --staged .

# Review
git status
git diff            # unstaged
git diff --cached   # staged vs HEAD
```

## ⚠️ Pitfalls [#️-pitfalls]

* `git add .` from a subdirectory only stages under that path — use repo-root awareness.
* Staging secrets (`.env`) is easy to miss — keep `.gitignore` current.
* `git add -A` can stage deletions you did not intend — review `git status` first.
* Partial staging can leave a file both staged and unstaged with different hunks.

## 🔗 Related [#-related]

* [Commit](/docs/git/commit)
* [Gitignore](/docs/git/gitignore)
* [Branch](/docs/git/branch)
* [Merge](/docs/git/merge)
* [Rebase](/docs/git/rebase)


---

# stash (/docs/git/stash)



# stash [#stash]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git stash` shelves uncommitted changes so you can switch branches cleanly, then restore them later. Prefer named stashes and explicit `pop`/`apply`; include untracked files when needed.

## 🔧 Core concepts [#-core-concepts]

* **Default** — stashes tracked modified + staged; working tree matches HEAD.
* **Untracked** — `-u` / `--include-untracked`; `-a` also ignored.
* **List / show** — `stash list`, `stash show -p`.
* **Restore** — `apply` keeps stash; `pop` applies and drops.
* **Branch** — `stash branch <name>` creates a branch from the stash base.

## 💡 Examples [#-examples]

```shellscript
git stash push -m "wip: login form"
git stash list
git stash show -p stash@{0}

git stash pop
git stash apply stash@{1}
git stash drop stash@{1}
git stash clear   # delete all — irreversible

# Include untracked
git stash push -u -m "wip: new files"

# Stash only some paths
git stash push -m "partial" -- src/a.ts src/b.ts

# Keep index (stash unstaged only)
git stash push --keep-index -m "keep staged"

git stash branch recover-wip stash@{0}
```

## ⚠️ Pitfalls [#️-pitfalls]

* `pop` can conflict; the stash entry may remain if apply fails (version-dependent).
* Stashing doesn’t include ignored files unless `-a`.
* Binary / submodule changes can make stash awkward — verify with `show -p`.
* Don’t rely on stash as backup — commit to a WIP branch instead for long work.
* `clear` / `drop` are hard to undo (reflog may help briefly).

## 🔗 Related [#-related]

* [status.md](/docs/git/status)
* [branch.md](/docs/git/branch)
* [conflict.md](/docs/git/conflict)
* [reflog.md](/docs/git/reflog)
* [clean.md](/docs/git/clean)
* [commit.md](/docs/git/commit)


---

# status (/docs/git/status)



# status [#status]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git status` shows the working tree vs index vs HEAD: staged, unstaged, and untracked files. Use short and porcelain formats in scripts; branch tracking info shows ahead/behind remotes.

## 🔧 Core concepts [#-core-concepts]

* **Sections** — staged (index), unstaged (worktree), untracked.
* **Branch** — current branch, upstream, ahead/behind counts.
* **Short** — `-s` / `--short`; `--branch` adds branch header.
* **Porcelain** — `-z` / `--porcelain=v1|v2` stable for scripts.
* **Ignore** — `--ignored` lists ignored files; respect `.gitignore`.

## 💡 Examples [#-examples]

```shellscript
git status
git status -sb              # short + branch
git status --porcelain=v1   # scripting

# Only untracked
git status -u

# Show ignored
git status --ignored

# Path limited
git status -- apps/web

# Useful aliases
# st = status -sb
git config alias.st "status -sb"
```

```plaintext
## main...origin/main [ahead 1]
M  staged-file.ts
 M unstaged-file.ts
?? new-file.ts
```

## ⚠️ Pitfalls [#️-pitfalls]

* “Clean” status doesn’t mean pushed — check ahead/behind or `git log @\{u\}..`.
* Renames show as delete+add unless similarity detection kicks in (`status` / `diff -M`).
* Submodule dirty state appears as modified content — inspect inside the submodule.
* Assume-unchanged / skip-worktree files can hide local edits.
* CRLF warnings may appear without listing as modified — check `core.autocrlf`.

## 🔗 Related [#-related]

* [stage.md](/docs/git/stage)
* [diff.md](/docs/git/diff)
* [commit.md](/docs/git/commit)
* [branch.md](/docs/git/branch)
* [clean.md](/docs/git/clean)
* [gitignore.md](/docs/git/gitignore)


---

# submodule (/docs/git/submodule)



# submodule [#submodule]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

Submodules embed another Git repo at a fixed commit inside a parent repo. The parent stores the submodule URL and pinned SHA. Prefer packages/monorepos when possible; use submodules for true multi-repo version pins.

## 🔧 Core concepts [#-core-concepts]

* **Record** — `.gitmodules` + gitlink (mode 160000) at a commit SHA.
* **Init/update** — after clone: `submodule update --init --recursive`.
* **Move forward** — cd into submodule, pull/commit, then commit new SHA in parent.
* **Remote clone** — `git clone --recurse-submodules`.
* **Deinit / remove** — deinit, remove config + gitlink + `.gitmodules` entry.

## 💡 Examples [#-examples]

```shellscript
git submodule add git@github.com:org/lib.git libs/lib
git commit -m "chore: add lib submodule"

git clone --recurse-submodules git@github.com:org/app.git
# or later:
git submodule update --init --recursive

# Update submodule to latest remote tracking branch
git submodule update --remote libs/lib
git add libs/lib
git commit -m "chore: bump lib submodule"

# Status
git submodule status
git submodule foreach 'git status -sb'

# Remove (high level)
git submodule deinit -f libs/lib
git rm -f libs/lib
rm -rf .git/modules/libs/lib
git commit -m "chore: remove lib submodule"
```

## ⚠️ Pitfalls [#️-pitfalls]

* Fresh clones without `--recurse-submodules` leave empty directories.
* Parent CI must init submodules or builds miss code.
* Detached HEAD inside submodule is normal — create a branch before committing there.
* Nested submodules need `--recursive`.
* Mixing submodule edits with parent WIP confuses reviews — bump SHA in a dedicated commit.

## 🔗 Related [#-related]

* [clone.md](/docs/git/clone)
* [remote.md](/docs/git/remote)
* [status.md](/docs/git/status)
* [commit.md](/docs/git/commit)
* [worktree.md](/docs/git/worktree)
* [sparse\_checkout.md](/docs/git/sparse-checkout)


---

# tag (/docs/git/tag)



# tag [#tag]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

Tags mark specific commits (releases, milestones). Lightweight tags are refs; annotated tags store message, author, and date (preferred for releases). Push tags explicitly to remotes.

## 🔧 Core concepts [#-core-concepts]

* **Lightweight** — `git tag v1.0.0` → pointer only.
* **Annotated** — `git tag -a v1.0.0 -m "…"` → full object (signing with `-s`).
* **List / show** — `git tag -l`, `git show v1.0.0`.
* **Move** — delete + recreate, or `-f` (force) carefully.
* **Remote** — tags don’t push by default; `git push origin v1.0.0` or `--tags`.

## 💡 Examples [#-examples]

```shellscript
git tag v1.2.0
git tag -a v1.2.0 -m "Release 1.2.0"
git tag -a v1.2.0 abcdef1 -m "Release 1.2.0"

git tag -l "v1.2.*"
git show v1.2.0

# Push one / all
git push origin v1.2.0
git push origin --tags

# Delete local + remote
git tag -d v1.2.0
git push origin :refs/tags/v1.2.0
# or: git push origin --delete v1.2.0

# Checkout (detached)
git switch --detach v1.2.0
```

## ⚠️ Pitfalls [#️-pitfalls]

* Moving a published tag confuses CI/CD and consumers — treat as immutable.
* `git push --tags` can push unintended local tags — push named tags instead.
* Lightweight tags lack metadata — use annotated for releases.
* Tagging the wrong commit — verify with `git log -1` before tagging.
* Signed tags need GPG/SSH signing configured.

## 🔗 Related [#-related]

* [log.md](/docs/git/log)
* [commit.md](/docs/git/commit)
* [push.md](/docs/git/push)
* [remote.md](/docs/git/remote)
* [branch.md](/docs/git/branch)
* [checkout via branch.md](/docs/git/branch)


---

# worktree (/docs/git/worktree)



# worktree [#worktree]

*Git · Reference cheat sheet*

***

## 📋 Overview [#-overview]

`git worktree` adds extra working directories linked to the same repository. Use them for parallel branches (hotfix while feature WIP continues) without stashing or cloning again.

## 🔧 Core concepts [#-core-concepts]

* **Main + linked** — one `.git` data store; each worktree has its own checkout.
* **Add** — `git worktree add <path> <branch>` (creates branch with `-b`).
* **List / remove** — `worktree list`, `worktree remove`, `prune`.
* **Lock** — prevent accidental prune of portable drives.
* **Constraint** — a branch can be checked out in only one worktree at a time.

## 💡 Examples [#-examples]

```shellscript
git worktree list

# New branch in sibling folder
git worktree add -b hotfix/login ../app-hotfix main
cd ../app-hotfix
# … fix, commit, push …
cd ../app
git worktree remove ../app-hotfix

# Existing branch
git worktree add ../app-review review/pr-42

# Detached
git worktree add --detach ../app-bisect abcdef1

git worktree prune
git worktree lock ../app-hotfix --reason "on USB"
```

## ⚠️ Pitfalls [#️-pitfalls]

* Can’t check out the same branch in two worktrees — use a new branch or detach.
* Deleting folders manually leaves stale records — run `worktree prune` / `remove`.
* IDE may open the wrong root — open the specific worktree path.
* Shared `node_modules` isn’t automatic — install per worktree or use shared caches carefully.
* Submodules need init/update inside each worktree.

## 🔗 Related [#-related]

* [branch.md](/docs/git/branch)
* [stash.md](/docs/git/stash)
* [clone.md](/docs/git/clone)
* [status.md](/docs/git/status)
* [bisect.md](/docs/git/bisect)
* [submodule.md](/docs/git/submodule)

