Git Cheat Sheet
Commands, flags, examples and common errors
Config
Reads or sets Git configuration options at three levels: system, user (global) or repository (local).
git config --global user.name "John Doe" git config --global user.email "john.doe@example.com"
Defines how Git stores HTTPS credentials so it doesn't ask for a password on every push.
git config --global credential.helper manager
Sets a global .gitignore that applies to every repository.
git config --global core.excludesfile ~/.gitignore_global
Repositories
Creates a new Git repository in the current directory.
git init git init --initial-branch=main meu-projeto
Copies a remote repository to the local machine, including the full history.
git clone https://github.com/user/repo.git
Stage and commit
Shows the state of the working directory and the staging area: what is modified, staged or untracked.
git status
Moves changes from the working directory to the staging area, ready for the next commit.
git add src/components/Button.tsx git add .
Records the staged content as a new commit in the local repository with a message.
git commit -m "feat: adiciona git cheat sheet"
Restores files: takes them out of staging or discards changes in the working directory.
git restore --staged file.txt git restore file.txt
Removes files from the repository (and optionally from disk).
git rm secret.env
Renames or moves a tracked file, equivalent to mv + git add + git rm.
git mv old.tsx new.tsx
Branches
Lists, creates, renames or deletes branches.
git branch git branch feature/login
Legacy command to switch branches or restore files. Today git switch and git restore are recommended.
git checkout main git checkout -b feature/x
Modern replacement for checkout, dedicated to switching branches.
git switch main git switch -c feature/login
Merge and rebase
Merges changes from another branch into the current one, creating a merge commit when needed.
git switch main git merge feature/login
Reapplies the commits of the current branch on top of another base, rewriting history.
git switch feature git rebase main
Applies a specific commit from another branch onto the current one.
git cherry-pick a1b2c3d
Opens a graphical tool to resolve merge conflicts.
git mergetool --tool=meld
Remote
Manages the repository's remotes (origin, upstream, etc).
git remote -v
Downloads commits and refs from the remote without integrating them into the local branch.
git fetch origin
Equivalent to git fetch followed by git merge (or rebase) on the current branch.
git pull origin main
Sends local commits to the remote.
git push -u origin feature/login
Stash
Saves uncommitted changes onto a temporary stack to clean the working directory.
git stash push -m "WIP login"
Manipulating the stash stack.
git stash list git stash pop
Tags
Creates, lists, deletes or verifies tags. Tags mark points in history (releases).
git tag -a v1.2.0 -m "Release 1.2"
Returns a readable name based on the closest tag.
git describe --tags --always --dirty
Log
Shows the commit history with flexible filters and formatting.
git log --oneline --graph --decorate --all
Shows the contents of a commit, tag or object.
git show HEAD git show a1b2c3d:src/file.tsx
Shows differences between working dir, staging, commits or branches.
git diff git diff --cached git diff main feature
Shows who changed each line of a file and in which commit.
git blame -L 10,30 file.tsx
Summary grouped by author (useful for release notes).
git shortlog -sne
Local history of everything HEAD has touched. A lifesaver for recovering lost commits.
git reflog
git reset --hard HEAD@{2}Undo
Moves HEAD to another commit, optionally altering staging and the working dir.
git reset --soft HEAD~1 git reset --mixed HEAD~1 git reset --hard HEAD~1
Creates a new commit that undoes the changes of another. Safe on shared branches.
git revert a1b2c3d
Deletes untracked files from the working directory. Destructive operation.
git clean -nfd
Submodules
Adds a repository as a submodule inside the current one.
git submodule add -b main https://github.com/user/lib.git vendor/lib
Initializes and downloads submodules defined in .gitmodules.
git submodule update --init --recursive
Inspect status, run a command in each submodule, or deactivate one.
git submodule foreach 'git pull origin main'
Hooks
Create an executable file under .git/hooks/ named after the event (pre-commit, pre-push, commit-msg, post-merge, etc).
printf '#!/bin/sh\nnpm run lint\n' > .git/hooks/pre-commit chmod +x .git/hooks/pre-commit
Defines a shared hooks directory (versionable, outside .git).
git config core.hooksPath .githooks
JS tool that versions hooks in package.json and installs them automatically.
npx husky init echo "npm test" > .husky/pre-commit
Skips the pre-commit and commit-msg hooks (use sparingly).
git commit --no-verify -m "hotfix"
Advanced
Binary search through history to find the commit that introduced a bug.
git bisect start git bisect bad HEAD git bisect good v1.0 git bisect reset
Creates multiple working directories tied to the same .git, allowing you to work on several branches in parallel.
git worktree add ../proj-hotfix hotfix/urgente
Rewrites history: combine, reorder, edit or drop commits.
git rebase -i HEAD~5 # pick a1b2 feat: x # squash c3d4 fix typo # reword e5f6 chore: y # drop g7h8 wip
Bulk history rewriter, modern replacement for git filter-branch. Useful to remove sensitive files.
git filter-repo --path secrets.env --invert-paths
Creates a tarball or zip of a ref's contents, without .git.
git archive --format=zip --prefix=app/ -o release.zip v1.0
Packs commits into a single file that can be transferred offline.
git bundle create repo.bundle --all git clone repo.bundle nova-pasta
Resolves a reference into a full SHA, short SHA or name.
git rev-parse HEAD git rev-parse --abbrev-ref HEAD git rev-parse --short HEAD
Inspects Git objects (blobs, trees, commits, tags).
git cat-file -p HEAD git cat-file -t a1b2c3d
Lists tracked files (ls-files) or the contents of a tree (ls-tree).
git ls-files git ls-tree -r HEAD --name-only
Maintenance: garbage collection, integrity checks, pruning loose objects.
git gc --aggressive --prune=now git fsck --full
Lets you keep only a subset of the tree locally, useful for large monorepos.
git sparse-checkout init --cone git sparse-checkout set apps/web libs/ui
Adds notes to commits without changing their SHA.
git notes add -m "reviewed by QA" HEAD
Reference
┌──────────────┐ git add ┌────────────┐ git commit ┌─────────────┐ git push ┌──────────┐
│ Working Dir │ ───────────▶ │ Staging │ ───────────▶ │ Local Repo │ ──────────▶ │ Remote │
│ (files) │ ◀─────────── │ (index) │ ◀─────────── │ (.git) │ ◀────────── │ (origin) │
└──────────────┘ git restore └────────────┘ git reset └─────────────┘ git fetch └──────────┘
git pull = git fetch + git merge- untrackednew file, Git does not know it yet
- modifiedknown file has been changed
- stagedmarked for the next commit
- committedsaved in .git, part of history
- ignoredlisted in .gitignore
Shared branches, integrating large features while preserving context, release branches.
- Does not rewrite history
- Safe in any scenario
- Preserves the real timeline
- History with diamonds and noise
- Harder to read git log
Updating a local feature branch against main before opening a PR. Keeping history linear.
- Linear and clean history
- Readable git log
- More effective git bisect
- Rewrites SHAs (NEVER on public branches)
- Conflicts can be repetitive
- Loses temporal context
Before merging a feature with multiple 'wip' or 'fix typo' commits into main.
- 1 clean commit per feature
- Ultra-readable history on main
- Loses development granularity
- git bisect only locates the whole feature
Golden rule: rebase locally, merge publicly. Never rebase branches others are using.
--softKeeps staging and working dirMoves HEAD. Keeps staging and the working dir intact. Files remain staged.
Regroup commits without losing changes.
--mixedClears staging, keeps working dir(default) Moves HEAD. Clears staging but keeps the working dir. Files become unstaged.
Redo what was going into the next commit.
--hardWipes everything (destructive)Moves HEAD. Clears staging AND working dir. Wipes uncommitted changes. Destructive.
Return to the state of another commit, dropping everything.
fatal: refusing to merge unrelated historiesThe two repos do not share a common ancestor commit.
git pull origin main --allow-unrelated-histories
Updates were rejected because the remote contains work that you do not haveThe remote has commits the local branch does not know about.
git pull --rebase origin main then git push. Never push --force without --force-with-lease.
Please commit your changes or stash them before you switch branchesThere are local changes that would conflict when switching branches.
git stash, git switch other-branch, then git stash pop.
CONFLICT (content): Merge conflict in <file>Merge or rebase touched the same lines as another branch.
Edit between <<<<<<< ======= >>>>>>> then git add file followed by git merge --continue. To abort: git merge --abort.
detached HEADChecked out a SHA or tag instead of a branch.
To keep the work: git switch -c new-branch. To discard: git switch main.
Permission denied (publickey)SSH key not configured on GitHub or GitLab.
Run ssh-keygen -t ed25519 -C "email" and add ~/.ssh/id_ed25519.pub to the service's SSH keys.
fatal: Authentication failed (HTTPS)GitHub no longer accepts passwords, you need a Personal Access Token.
Generate a PAT on GitHub and use it as the password, or switch the remote to SSH.
Your branch and 'origin/main' have divergedBoth sides have different commits.
git pull --rebase on a local feature, or plain git pull on a shared main.
error: failed to push some refs (non-fast-forward)The remote moved on, you can't push without integrating first.
git pull --rebase then git push.
Deleted the wrong branch or did reset --hard and lost workDestructive operation with no backup.
git reflog to find the SHA, then git checkout -b recovered <sha>. Commits stick around for ~30 days before gc.
.gitignore is not workingThe file was already tracked before being ignored.
git rm --cached <file> then git commit -m "untrack". For directories: git rm -r --cached <folder>.
Committed a secret, password or .env fileReckless git add . without checking what was staged.
Rotate the secret, run git filter-repo --path .env --invert-paths, git push --force-with-lease, and tell the team to reclone.
LF will be replaced by CRLFLine ending differences between Windows and Unix.
git config --global core.autocrlf true on Windows, or input on Mac and Linux.
Filename too long (Windows)Windows 260-character limit.
git config --system core.longpaths true