A complete git commands cheatsheet with more than 60 commands organized into 11 practical categories. Every entry includes a concise description, a real-world example, and a one-click copy button. The live search at the top filters across names, descriptions, and examples so you can jump directly to what you need. Whether you're setting up your first repository, untangling a messy history, rebasing a feature branch, or managing submodules on a large monorepo, this page is designed to be the single page you keep open in a tab. Skim the 10-step learning path if you're new.
git configgit init or clone onegit addGit is the distributed version control system that powers nearly every open-source project, every internal company codebase, and every modern deployment pipeline. It was created by Linus Torvalds in 2005 to manage Linux kernel development after the team lost access to BitKeeper, and its design reflects that origin: it's built to handle thousands of contributors working across disconnected forks with no central authority, and it's ruthlessly fast at operating on full histories of hundreds of thousands of commits. Learning git well is one of the highest-leverage investments a developer can make. Most engineers get by knowing five commands: clone, add, commit, push, and pull. That's enough to function, but it leaves you helpless when anything goes wrong — a bad merge, a lost commit, a branch you can't remember creating. The engineers who can debug git state, cherry-pick fixes across branches, and rewrite history safely are disproportionately valuable on any team.
Git is not a pile of patches. It's a content-addressable filesystem with a version control interface bolted on top. Every file you commit is stored as a blob identified by a SHA-1 hash of its contents. Every directory snapshot is a tree that references blobs by hash. A commit is an object that references one tree (the state of the whole project), plus its parent commit(s), plus author metadata. A branch is just a movable pointer to a commit — nothing more. A tag is a fixed pointer. Remote-tracking branches like origin/main are pointers that mirror what the remote had at the last fetch. Once this model clicks, everything else follows. git reset moves a branch pointer. git merge creates a new commit with two parents. git rebase rewrites a series of commits so they have different parents. git cherry-pick copies the diff from one commit onto another branch as a new commit with a new hash.
Unlike Subversion or Mercurial, git has a three-layer structure: your working directory (the files on disk), the index or staging area (a snapshot of what the next commit will contain), and the repository (the committed history). You move changes between layers with git add (working → staged), git reset (staged → working), and git commit (staged → committed). The staging area feels like extra friction when you're starting out, but it becomes indispensable when you need to split a messy working directory into several small, focused commits. Use git add -p to stage individual hunks interactively — it's one of the most underused features in git.
Never rebase commits that exist outside your local repository. When you rebase, you're rewriting history — new commits are created with new SHAs, and the old commits become orphaned. If someone else has already pulled the old commits and based work on them, your rebased history will create a painful divergence that's hard to reconcile. The safe pattern: rebase your local feature branch onto the latest main before opening a PR (so history is linear), but once the PR is under review and other people may have pulled it, prefer merge commits. Some teams adopt a stricter "merge-only" policy on main to avoid any history rewriting in public branches.
Git almost never loses data. Commits that are no longer reachable from any branch or tag stay in the object database for at least 30 days (controlled by gc.reflogExpire) before garbage collection. The git reflog command shows every change to HEAD — every commit, checkout, reset, and merge — giving you a way to recover from almost anything. If you accidentally reset --hard and lose work, run git reflog, find the SHA of the state you want, and git reset --hard <sha> back to it. This is one of the most reassuring features in the whole tool, and it's why you should never be afraid to experiment with git commands.
The two dominant strategies are trunk-based development (everyone commits to main with short-lived feature branches, protected by CI) and Git Flow (long-lived develop and release branches, hotfix branches, and semver tags). Trunk-based suits teams with strong test automation and continuous deployment; Git Flow suits teams shipping versioned software to customers on slower release cadences. GitHub Flow is a lightweight variant — main is always deployable, and every change happens through a feature branch and PR. Pick the simplest model your team's release cadence supports.
git bisect performs a binary search through history to find the commit that introduced a bug. You mark a known-good commit and a known-bad commit, then git checks out the middle commit; you test it and mark good or bad; git narrows down, and within log₂(n) steps you've found the culprit. git blame shows who last modified each line of a file — invaluable for archaeology. git log --oneline --graph --all draws an ASCII graph of the full branch topology. git show <sha> displays a commit's diff and metadata. git diff --stat summarizes changes across many files. Master these and you can navigate any codebase's history fluently.
A few config settings make daily git much nicer. git config --global init.defaultBranch main uses main instead of master. git config --global pull.rebase true rebases instead of merging on pull (avoids noisy merge commits). git config --global core.editor "code --wait" uses VS Code for commit messages. Set up ~/.gitignore_global for editor files and OS clutter. Add SSH key authentication to GitHub/GitLab to skip password prompts. Enable commit signing with GPG or SSH to prove commits are yours. These take ten minutes to set up once and save hours over a career.
The cheat-sheet above covers the commands. This section covers the patterns: how teams actually use git day to day, the recovery moves that pull you out of any mess, the conventional-commits / semantic-release pipeline that has become standard, and the security practices around signed commits and protected branches that show up in any audited codebase.
| Convention | Example | Used by |
|---|---|---|
| Conventional Commits | feat(auth): add OAuth login | Most modern repos. Drives semantic-release and changelog generation. |
| Angular style | fix(http): handle 504 retries | Older Angular projects; ancestor of Conventional Commits. |
| Gitmoji | :sparkles: Add OAuth login | Smaller repos that want visual scanability in git log. |
| Linear / Imperative | Add OAuth login (LIN-1234) | Linear- and Jira-driven teams. Ticket ID upfront. |
| "Fix typo"-style | Fix typo | Avoid. Useless in git log 6 months later. |
The 2026 default for serious projects is Conventional Commits, because it pairs with semantic-release, release-please, or changesets to auto-generate changelogs and version bumps. The format:
type(scope): summary in present tense
Optional body explaining why, not what.
Wraps at ~72 chars per line.
Optional footer:
BREAKING CHANGE: removed deprecated `oldFunction`.
Refs: LIN-1234, #567
Types: feat (new feature → minor version bump), fix (bug fix → patch), docs, refactor, test, chore, perf, ci, build, style. BREAKING CHANGE in the footer triggers a major bump.
| Situation | Recovery command |
|---|---|
Accidentally reset --hard and lost work | git reflog → find the SHA → git reset --hard <sha> |
| Committed to wrong branch | git reset --soft HEAD~1 → switch branch → git commit |
| Want to undo a pushed commit safely | git revert <sha> → push the inverse commit |
| Want to remove last N commits locally | git reset --hard HEAD~N (private branches only) |
| Want to combine last N commits into one | git reset --soft HEAD~N → git commit |
| Need to find when a bug was introduced | git bisect start → git bisect bad → git bisect good <old-sha> |
| Accidentally committed a secret | git filter-repo (preferred over BFG since 2021); rotate the secret immediately |
| Want to restore a single file from another commit | git checkout <sha> -- path/to/file |
| Pull is failing because local has divergent history | git pull --rebase or git fetch && git rebase origin/main |
| Detached HEAD with valuable work | git switch -c new-branch while in detached state |
Since git 2.23 (2019), there are two new commands that disambiguate checkout's historic dual personality:
git switch — change branches. Replaces git checkout <branch>.git restore — restore files. Replaces git checkout -- file (working tree) and git reset HEAD file (staging).git checkout still works for backward compatibility. New scripts and tutorials should use switch/restore — they're clearer to readers.
Production-ready GitHub/GitLab repos set up branch protection on main to prevent the easy mistakes:
By default, anyone can author a commit with any name and email. The git config user.email setting is purely cosmetic. Signed commits cryptographically prove the commit was made by someone holding the private key.
Two signing methods:
git config commit.gpgsign true. Verified signatures appear with a green badge in the UI.git config gpg.format ssh and git config user.signingKey ~/.ssh/id_ed25519.pub.Required for SOC 2 audits and increasingly common in financial-services and healthcare codebases.
# Editor / OS
.DS_Store
Thumbs.db
.idea/
.vscode/
*.swp
*~
# Dependencies
node_modules/
__pycache__/
*.pyc
vendor/
target/
# Build output
dist/
build/
*.log
# Secrets — NEVER commit these
.env
.env.local
.env.*.local
*.pem
*.key
secrets.json
# Coverage
coverage/
.nyc_output/
# OS-level
.bash_history
.zsh_history
Even with .gitignore, secrets occasionally slip through. Tools like git-secrets, truffleHog, gitleaks, and GitHub's native secret scanning catch them in CI.
Git triggers scripts at well-defined moments. The most useful hooks:
| Hook | Fires | Common use |
|---|---|---|
pre-commit | Before git commit creates the commit | Run lint, format, simple tests |
commit-msg | After commit message is entered | Validate Conventional Commits format |
pre-push | Before git push sends commits | Run unit tests, prevent push to main |
post-merge | After successful merge / pull | Auto-install new dependencies |
Manage them with husky + lint-staged (Node ecosystem), pre-commit (Python ecosystem), or lefthook (cross-language). Native git hooks live in .git/hooks/ but aren't shared across the team — always use a hook manager.
Once a repo grows past ~10 GB or has thousands of contributors, raw git starts to slow down. The fixes:
git clone --depth 1) — pull only the latest commit. Useful in CI.git clone --filter=blob:none) — defer downloading file contents until needed.git sparse-checkout init --cone) — work on a subset of the directory tree..env with real secrets. Even after deletion, the secret is in history. Rotate it; use git filter-repo or BFG if you must scrub history.--force-with-lease; never force-push to main.git pull with merge instead of rebase. Produces noisy "Merge branch 'main' of …" commits. Set git config pull.rebase true globally.git fetch before git rebase. Rebases on stale base; conflicts on push.Search results for "git cheatsheet", "git commands list", and "git commands pdf" return many static cheat-sheets but most are outdated (no git switch or git restore from 2.23+), incomplete (missing rebase --autosquash, sparse-checkout, worktree), or don't surface the modern recovery patterns (reflog, fsck) that pull you out of real git messes. Here's how the most-used git references compare in 2026:
| Resource | Modern verbs (switch/restore) | Recovery patterns | Searchable | Cost |
|---|---|---|---|---|
| FreeDevTool Git Cheatsheet | Yes | reflog + fsck + cherry-pick recovery | Live filter | Free |
| GitHub git cheatsheet PDF | Limited | Basics only | No (PDF) | Free |
| Atlassian git cheatsheet | Yes | Limited | No | Free |
| git-scm.com Pro Git book | Yes | Full | No (browse) | Free, OSS |
| Oh My Git! (game) | Yes | Interactive | N/A | Free |
| Command | Affects | Safe on shared branch? | Use case |
|---|---|---|---|
git reset --hard HEAD~1 | Branch pointer + working tree + staging | ❌ NEVER | Throw away local commits before push |
git reset --soft HEAD~1 | Branch pointer only | ❌ NEVER | Keep changes staged, redo last commit |
git reset --mixed HEAD~1 | Branch pointer + staging | ❌ NEVER | Default reset; unstage but keep changes |
git revert HEAD | Creates new inverse commit | ✅ YES | Undo a pushed commit on shared branch |
git restore --staged file | Unstages a file (modern syntax) | ✅ YES | Replace git reset HEAD file |
git restore file | Discards working tree changes | ✅ YES | Replace git checkout -- file |
git switch branch | Move HEAD to branch | ✅ YES | Replace git checkout branch |
Decision rule: locally only → reset is fine. Pushed already → always revert. Modern syntax (since git 2.23, late 2019) prefers switch + restore over the overloaded checkout. Update muscle memory.
Three recovery commands cover 95% of git accidents. One: git reflog shows every change to HEAD over the last 90 days, including deleted branches and reset commits. Find your lost commit's SHA, then git checkout -b recovered-branch <SHA>. Two: git fsck --lost-found walks the object database and surfaces dangling commits not reachable from any branch — useful when a commit was made then the branch was deleted before push. Three: git cherry-pick <SHA> applies a single commit from anywhere (including reflog SHAs) onto your current branch. As long as you haven't run git gc --prune=now, lost commits stay in the object database for ~14 days minimum (default gc.pruneExpire).
git switch and git restore (introduced 2019); most static PDFs still teach the overloaded git checkout for both branch-switching and file-restoring.Pair the git cheatsheet with the Chmod Calculator for SSH-key permission errors (chmod 600 ~/.ssh/id_rsa), the Cron Expression Parser for scheduled git pulls, and the DevOps Tools hub for the broader CLI utility toolkit.
revert on shared branches where other people may have pulled the commits you want to undo; reset is only safe on private branches nobody else has seen.git reset --soft HEAD~1 keeps your changes staged, git reset --mixed HEAD~1 (the default) keeps them unstaged but in your working tree, and git reset --hard HEAD~1 discards them entirely. If you've already pushed, don't reset — use git revert HEAD to create an inverse commit that's safe to push on shared branches. To fix just the commit message, git commit --amend opens your editor to edit the previous commit.git stash pop (applies the top stash and removes it from the stack) or git stash apply (applies without removing). Add untracked files with git stash -u, and name stashes with git stash push -m "message".<<<<<<< HEAD, =======, and >>>>>>> branch-name surrounding the conflicting regions. Open each conflicted file, edit it to the desired final state (removing all markers), then git add the file to mark the conflict resolved. When all conflicts are resolved, git commit completes the merge. To bail out, git merge --abort returns to the pre-merge state. For rebases, use git rebase --continue or git rebase --abort.git push --force-with-lease (safer than --force because it fails if someone else pushed in the meantime), and make sure everyone re-clones or runs git fetch && git reset --hard origin/branch after. For routine history cleanup, squash locally before pushing.All tools run in your browser, no signup required, nothing sent to a server.