Git Commands Cheat Sheet
git status # what changed?
git add -p # stage changes interactively
git commit -m "Fix login timeout" # commit staged changes
git switch -c feature/login # create and switch to a branch
git pull --rebase # update from the remote, linear history
git push -u origin feature/login # push a new branch and track it
Install Git and set it up first: see installing and configuring Git on Linux. For pushing to GitHub or GitLab over SSH, you need a key: set up SSH keys. Commands here use the modern git switch and git restore; older tutorials use git checkout for both.
Setup and config
| Command | What it does |
|---|---|
git config --global user.name "Your Name" | Name recorded in commits |
git config --global user.email [email protected] | Email recorded in commits |
git config --global init.defaultBranch main | Name new repositories' first branch main |
git config --global core.editor vim | Editor for commit messages |
git config --global pull.rebase true | Make git pull rebase instead of merge |
git config --global push.autoSetupRemote true | First git push on a new branch sets upstream automatically |
git config --global alias.lg "log --oneline --graph --all" | Create a shortcut: git lg |
git config --list --show-origin | All settings and the file each comes from |
git init | Turn the current directory into a repository |
git clone URL [dir] | Copy a remote repository |
git clone --depth 1 URL | Shallow clone: latest commit only, much faster |
Staging and committing
| Command | What it does |
|---|---|
git status -sb | Short status with branch info |
git add file | Stage a file |
git add . | Stage all changes in the current directory and below |
git add -p | Choose hunks to stage interactively |
git restore --staged file | Unstage a file (keep the change in the working tree) |
git commit -m "message" | Commit what is staged |
git commit -am "message" | Stage all tracked modified files and commit (new files are not included) |
git commit --amend | Change the last commit's message or add forgotten changes |
git commit --amend --no-edit | Add staged changes to the last commit, same message |
git rm file | Delete a file and stage the deletion |
git rm --cached file | Stop tracking a file but keep it on disk |
git mv old new | Rename and stage |
Branches
| Command | What it does |
|---|---|
git branch | List local branches (-a includes remote ones, -vv shows tracking) |
git switch name | Switch to a branch |
git switch -c name | Create a branch and switch to it |
git switch - | Switch back to the previous branch |
git switch --detach v1.2.0 | Check out a tag or commit without a branch |
git branch -m new-name | Rename the current branch |
git branch -d name | Delete a merged branch (-D forces) |
git branch --merged main | Branches already merged into main |
git worktree add ../hotfix hotfix-branch | Check out another branch in a second directory at the same time |
Merging and rebasing
| Command | What it does |
|---|---|
git merge feature | Merge feature into the current branch |
git merge --no-ff feature | Always create a merge commit |
git merge --squash feature | Stage all of feature's changes as one commit to make |
git merge --abort | Give up a merge with conflicts |
git rebase main | Replay current branch's commits on top of main |
git rebase -i HEAD~5 | Edit, squash, reorder or drop the last 5 commits |
git rebase --continue / --abort | After fixing conflicts / give up the rebase |
git cherry-pick abc1234 | Apply one commit from elsewhere onto the current branch |
git diff --name-only --diff-filter=U | List files that still have conflicts |
git mergetool | Open a configured merge tool for conflicts |
Remotes: fetch, pull, push
| Command | What it does |
|---|---|
git remote -v | List remotes and their URLs |
git remote add origin [email protected]:user/repo.git | Add a remote |
git remote set-url origin URL | Change a remote's URL (e.g. HTTPS to SSH) |
git fetch | Download new commits without changing your branches |
git fetch --prune | Also remove references to deleted remote branches |
git pull | Fetch and integrate the upstream branch |
git pull --rebase | Fetch and rebase local commits on top |
git push | Push the current branch to its upstream |
git push -u origin name | Push a new branch and set its upstream |
git push --force-with-lease | Overwrite the remote branch only if nobody else pushed meanwhile |
git push origin --delete name | Delete a remote branch |
git push --tags | Push all tags |
Undoing things
Committed work can almost always be recovered with git reflog. Uncommitted changes discarded with restore, reset --hard or clean are gone. Commit or stash first if in doubt.
| Command | What it does |
|---|---|
git restore file | Discard unstaged changes to a file |
git restore --source=HEAD~2 file | Get a file as it was two commits ago |
git reset --soft HEAD~1 | Undo the last commit, keep changes staged |
git reset HEAD~1 | Undo the last commit, keep changes unstaged (--mixed, the default) |
git reset --hard HEAD~1 | Undo the last commit and throw its changes away |
git reset --hard origin/main | Make the branch exactly match the remote (local work lost) |
git revert abc1234 | New commit that reverses a commit (safe for pushed history) |
git clean -n then git clean -fd | Preview, then delete untracked files and directories |
git reflog | Every position HEAD has been in; find "lost" commits |
git reset --hard HEAD@{2} | Go back to a reflog entry |
Stash, history and diffs
| Command | What it does |
|---|---|
git stash | Set aside uncommitted changes to tracked files |
git stash -u -m "wip login" | Include untracked files and add a description |
git stash list | List stashes |
git stash pop | Reapply the latest stash and remove it |
git stash apply stash@{1} | Reapply a stash and keep it |
git log --oneline --graph --all | Compact history graph of all branches |
git log -p file | History of one file with diffs |
git log -S 'functionName' | Commits that added or removed a string |
git log --since='2 weeks ago' --author=alice | Filter by date and author |
git diff | Unstaged changes |
git diff --staged | Staged changes (what will be committed) |
git diff main...feature | Changes on feature since it branched from main |
git show abc1234 | One commit with its diff |
git blame -L 10,30 file | Who last changed lines 10-30 |
git bisect start, bad, good v1.0 | Binary-search for the commit that introduced a bug |
git tag -a v1.0 -m "Release 1.0" | Create an annotated tag |
Common recipes
Start a feature, keep it up to date, and push it:
git switch main && git pull
git switch -c feature/search
# ...work and commit...
git fetch origin
git rebase origin/main
git push -u origin feature/search
Committed to main by mistake? Move the commit to a new branch:
git branch feature/oops # new branch points at your commit
git reset --hard origin/main # move main back to the remote state
git switch feature/oops
Squash your last 3 commits into one before opening a pull request:
git reset --soft HEAD~3
git commit -m "Add search feature"
git push --force-with-lease
Stop tracking a file that is now in .gitignore:
echo '.env' >> .gitignore
git rm --cached .env
git commit -m "Stop tracking .env"
Switch a repository from HTTPS to SSH:
git remote set-url origin [email protected]:user/repo.git
ssh -T [email protected] # test the key
Recover a branch you deleted:
git reflog | grep 'feature/x'
git branch feature/x abc1234
Clean up merged local branches:
git fetch --prune
git branch --merged main | grep -vE '^\*|^\s*main$' | xargs -r git branch -d
Gotchas
- "fatal: detected dubious ownership in repository". Git refuses to work in a repository owned by another user (common with sudo, Docker volumes and shared drives). See fixing dubious ownership; don't blindly set
safe.directory '*'. - Don't rewrite pushed history.
reset,rebaseand--amendcreate new commits. If others pulled the old ones, userevert. When you must force-push your own branch, use--force-with-lease, never plain--force. git commit -askips new files. Untracked files must be added withgit addfirst.HEAD~1vsHEAD^. They're the same for one step;HEAD^2means the second parent of a merge, whileHEAD~2means two commits back.- Divergent branches warning on pull. Git asks you to choose. Set
git config --global pull.rebase true(orpull.ff only) once. - Line endings. Files edited on Windows show every line as changed. On Linux set
core.autocrlf input, or add a.gitattributeswith* text=auto. - Secrets in history. Deleting a committed password in a new commit doesn't remove it from history. Rotate the secret; rewriting history needs
git filter-repo.
Reference: the official Git documentation and the free Pro Git book. Containers next: Docker commands cheat sheet.
Frequently asked questions
How do I undo the last commit but keep my changes?
git reset --soft HEAD~1 removes the commit and leaves the changes staged. If you already pushed it, use git revert HEAD instead so you don't rewrite shared history.
What is the difference between git switch and git checkout?
git switch only changes branches and git restore only restores files; together they split up the overloaded git checkout. Both have existed since Git 2.23 and are what git status suggests in its hints.
How do I delete a branch locally and on the remote?
git branch -d name deletes it locally (-D forces it if unmerged) and git push origin --delete name deletes it on the remote.
What is the difference between merge and rebase?
Merge joins two histories with a merge commit and keeps everything as it happened. Rebase replays your commits on top of another branch for a linear history, but rewrites those commits, so don't rebase commits others have already pulled.
How do I discard all local changes?
git restore . discards unstaged changes to tracked files and git clean -fd deletes untracked files. git reset --hard also discards staged changes. These can't be undone, so check git status first.
Spotted a mistake or a command that no longer works? Send a correction — pages are re-checked when reports come in.