Git Command Line Cheat Sheet
Sidebar
Programming ยท Git Command Line Cheat Sheet
The Git commands you use every day, grouped by task: setup, the daily loop, history, branches, merging and rebasing, undoing, remotes, stash and tags, searching, ignoring files and naming commits. Written for Git 2.49 on Windows, the version installed here; the commands and options were run in a scratch repository to check they work. This is the command-line companion to the VS Code Git and Source Control sheet, which covers the editor's settings.
Setup & Configuration
git --versionCheck the install (here: 2.49.0.windows.1)git config --global user.name "Your Name"Who your commits are from; also user.emailgit config --list --show-originEvery setting and the file it came from--system --global --localWhere a setting is stored: all users / your account (~/.gitconfig) / this repository (.git/config); local beats global beats systemgit config --global init.defaultBranch mainNew repositories start on this branch. Yours is currently master, set in Git's system configgit config --global alias.st "status -sb"Create a shortcut: then git st worksgit config --global core.editor "code --wait"Use VS Code for commit messagescore.autocrlfLine-ending conversion; true here (Windows), which causes the "LF will be replaced by CRLF" warningscredential.helpermanager here: Git Credential Manager remembers your loginsgit help <command> or git <command> -hFull manual page / one-screen summaryStarting a Repository
git initTurn the current folder into a repository; -b main (or --initial-branch) names the first branchgit clone <url> [folder]Copy a remote repositorygit clone --depth 1 <url>Only the latest commit: much faster for big repositoriesgit clone --branch <name> --single-branch <url>Only one branchgit clone --filter=blob:none <url>A partial clone: file contents are fetched when neededgit clone --recurse-submodules <url>Also fetch submodulesgit clone --bare / --mirrorServer-style copies with no working folderThe Daily Loop
git status -sbShort status with the branch and its upstream (-s short, -b branch)git add <file> git add . git add -uStage a file / everything here / only files Git already tracksgit add -pChoose which pieces of a file to stage, one hunk at a timegit diffChanges not yet stagedgit diff --staged (or --cached)Changes that are staged for the next commitgit diff --stat --name-only --word-diffSummary / just file names / word-level changes; git diff --check finds whitespace mistakesgit commit -m "message"Commit what is staged; -a also stages tracked files; -v shows the diff in the editorgit commit --amendChange the last commit; --no-edit keeps its message; only before you push itgit commit --allow-empty --signoff --fixup <sha>Empty commit / add a Signed-off-by line / mark a fix for a later autosquashgit rm <file> git rm --cached <file>Delete and stop tracking / stop tracking but keep the filegit mv old newMove or rename a tracked fileLooking at History
git log --oneline --graph --decorate --allThe classic compact picture of every branchgit log -p git log --statWith the changes / with a change summary; add -3 to limitgit log --author="Name" --since="2 weeks ago"Filter by author and dategit log --grep="fix"Commits whose message matchesgit log -S"text" git log -G"regex"Commits that added or removed that text / changed lines matching the patterngit log --follow -- <file>History of one file, through renamesgit log -L 10,20:<file>History of a range of linesgit log main..featureCommits on feature that are not on maingit log main...feature --left-rightCommits on either side but not bothgit log --first-parent --no-mergesFollow only the main line / hide merge commitsgit log --pretty=format:"%h %an %s"Your own layout: hash, author, subjectgit show <rev> git show <rev>:<path>One commit / a file as it was thengit blame -L 1,20 <file>Who last changed each linegit shortlog -snCommit counts per authorgit describe --tags --alwaysA readable name for the current commitBranches
git branchList local branches; -vv adds the last commit and upstream, -a includes remote ones, -r only remote onesgit branch --show-currentPrint just the current branch namegit switch <branch>Move to a branchgit switch -c <new>Create a branch and move to it (git checkout -b in older guides)git switch -Back to the previous branchgit switch --detach <rev>Look at an old commit without being on a branchgit branch <new>Create a branch without moving to itgit branch -m <old> <new>Rename a branchgit branch -d <b> git branch -D <b>Delete if fully merged / delete regardlessgit branch --merged --no-mergedWhich branches are already in the current one, and which are notMerging, Rebasing & Cherry-Picking
git merge <branch>Bring that branch into the current onegit merge --no-ff / --ff-only / --squashAlways make a merge commit / refuse unless it fast-forwards / combine everything into one change you commit yourselfgit merge --abortGive up a merge that has conflicts<<<<<<< ======= >>>>>>>Conflict markers in a file: edit the file, git add it, then git merge --continue (or commit)git mergetoolOpen your configured merge toolgit rebase mainReplay your commits on top of maingit rebase -i HEAD~3Edit the last three commits: pick, reword, edit, squash, fixup, dropgit rebase --autosquash --autostashFold --fixup commits automatically / stash and restore your changes around itgit rebase --onto <new> <old> <branch>Move a branch to a different basegit rebase --continue --skip --abortAfter fixing a conflict / skip this commit / go back to before the rebasegit cherry-pick <sha>Copy one commit here; -x notes where it came from, --no-commit leaves it stagedgit revert <sha>Make a new commit that undoes one (-m 1 for a merge commit)Do not rebase shared historyRebasing rewrites commits: only rebase branches that nobody else has pulledUndoing Things (from safest to riskiest)
git restore --staged <file>Unstage a file; your edits staygit restore <file>Discard your uncommitted edits to a file: they cannot be recoveredgit restore --source=HEAD~1 <file>Bring back a file as it was one commit agogit commit --amendFix the last commit (not yet pushed)git reset --soft HEAD~1Undo the last commit; changes stay stagedgit reset --mixed HEAD~1Undo the last commit; changes stay in your files, unstaged (the default)git revert <sha>Undo a commit you already pushed, safely, with a new commitgit reset --hard <rev>Throw away commits and uncommitted changes: use with great caregit reflogWhere HEAD has been: your safety net for "lost" commitsgit switch -c rescue <sha>Give a lost commit from the reflog a branch againgit clean -n -dDry run: which untracked files and folders would be deletedgit clean -fdDelete them (-x also removes ignored files)Remotes: Fetch, Pull & Push
git remote -vList remotes and their addressesgit remote add origin <url>Add one; set-url changes it, rename and remove also existgit remote show originDetails of a remote and how your branches track itgit fetch --prune --allDownload new commits and forget deleted remote branches; nothing in your files changesgit pullFetch and then merge; --rebase rebases instead, --ff-only refuses a merge, --autostash saves and restores your changesgit pushUpload the current branchgit push -u origin <branch>First push of a branch; -u (--set-upstream) remembers itgit push --force-with-leaseA forced push that fails if someone else pushed in the meantime: use this instead of --forcegit push --tags --follow-tagsUpload all tags / annotated tags that point at pushed commitsgit push origin --delete <branch>Delete a remote branchgit push --dry-runShow what would be pushedgit branch --set-upstream-to=origin/<b>Tell Git which remote branch this one followsStash & Tags
git stash push -u -m "wip"Put away your uncommitted work (-u includes untracked files)git stash listSee the stack of stashesgit stash show -p stash@{0}See what is in a stashgit stash pop git stash applyRestore the latest stash and remove it / restore it and keep itgit stash drop git stash clearDelete one stash / all of themgit stash branch <name>Make a branch from a stashgit tag v1.0A lightweight tag on the current commitgit tag -a v1.0 -m "Release 1.0"An annotated tag with a message (better for releases)git tag -l git tag -d v1.0List tags / delete onegit push origin v1.0Upload one tagSearching & Inspecting
git grep -n -i "text"Search tracked files; -c counts per filegit ls-files -m --others --exclude-standardModified files / untracked files that are not ignoredgit check-ignore -v <file>Which ignore rule applies to a filegit rev-parse --short HEAD --show-toplevelShort hash of the current commit / the repository's top foldergit ls-tree -r HEAD --name-onlyEvery file in a commitgit cat-file -p <sha>Show the raw contents of a Git objectgit bisect start / bad / good <sha>Binary-search for the commit that introduced a bug; finish with git bisect resetgit bisect run <command>Let a script decide good or bad automaticallygit archive --format=zip -o out.zip HEADMake a zip of a commit without the .git foldergit worktree add ../dir -b <branch>A second working folder for another branch; list, remove manage themgit sparse-checkout set <folders>Check out only some folders of a big repositorygit fsck git gc git maintenance runCheck, tidy and optimise the repositoryIgnoring Files & Line Endings
.gitignoreA file of patterns for files Git should not track*.logIgnore by patternbuild/A trailing slash means a folder/config.localA leading slash anchors it to the top folder**/tempMatch at any depth!keep.logA leading ! re-includes something an earlier pattern ignored# commentComment linegit rm --cached <file>A file already tracked stays tracked until you do this; adding it to .gitignore is not enoughcore.excludesFileA personal ignore file that applies to every repository.gitattributesPer-path rules, such as * text=auto or *.sh text eol=lf to fix line endings across machinesGit LFSInstalled here (filter.lfs.* in the system config): stores large files outside the normal historyNaming Commits & Ranges (revision syntax)
HEAD @The current commitHEAD~1 HEAD~3The parent / the great-grandparent along the first-parent lineHEAD^ HEAD^2First parent / second parent (the merged-in side of a merge)main@{upstream} @{u}The remote branch a local branch followsmain@{yesterday} main@{3}Where a branch was yesterday / three moves ago (from the reflog)A..BCommits in B but not in AA...BCommits in either but not both:/textThe most recent commit whose message contains the text<rev>:<path>A file as it was in that commitshort hashesThe first 7 or more characters of a hash are enough if they are uniqueHandy Aliases to Copy (my suggestions)
git config --global alias.st "status -sb"Short statusgit config --global alias.lg "log --oneline --graph --decorate --all"The graph in two lettersgit config --global alias.co "switch"A short name for switching branchesgit config --global alias.unstage "restore --staged"Say what you meangit config --global alias.last "log -1 HEAD --stat"Show the last commitgit config --global alias.amend "commit --amend --no-edit"Add staged changes to the last commitgit config --global pull.ff onlyMake git pull refuse anything but a fast-forward (a safe habit)git config --global push.autoSetupRemote trueFirst git push sets the upstream for youI made a mistake! Work down this ladder
1) Is it only an uncommitted edit? git restore <file> discards it for good, so be sure. 2) Is it staged by mistake? git restore --staged <file>. 3) Is it the last commit and not yet pushed? git commit --amend or git reset --soft HEAD~1. 4) Already pushed? git revert <sha> adds a new commit that undoes it, without rewriting shared history. 5) Think you lost commits? git reflog lists where HEAD has been for a long while: pick the hash and git switch -c rescue <sha>. Git rarely loses committed work, but it cannot bring back uncommitted changes you discarded.
master or main? Check your default branch
Many hosting sites now call the main branch main, but your Git installation's system settings still create master in new repositories (init.defaultBranch=master). Either name works, but if you push to a new repository on a site that expects main, rename with git branch -m main or set git config --global init.defaultBranch main before running git init.
Never force-push to a shared branch
git push --force overwrites the remote branch with yours and can destroy other people's commits. If you must update a branch you have rebased or amended, use --force-with-lease, which stops if someone else has pushed since you last fetched, and only do it on a branch that is yours alone.