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.
Last updated: March 2026git 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.
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.