Git Command Reference
runs in your browserGit commands by what you want to do — undo the last commit, rename a branch, recover a deleted one — each marked safe, rewrites history or can lose work.
- risk: safeChanges nothing you cannot get back.
- risk: rewrites historyReplaces commits with new ones. Fine on commits only you have; once pushed, others must recover from it.
- risk: can lose workThrows away work that Git may not be able to give back.
Your names0 of 21 filled
Type a name once and every command shown uses it, quoted where the shell needs it.
Commands
75 of 75Every task. Copy all takes them as a cheat sheet.
Set your name and email for every repository
risk: safegit config --global user.name <name>git config --global user.email <email>
Every commit records an author. --global sets it for your user; run the same commands without --global inside one repository to use a different identity there, such as a work email. Commits already made keep the old author.
Start a repository in the current folder
risk: safegit initgit init -b mainnaming the first branch
Creates the .git folder that holds the history. Nothing is tracked until you add and commit files. -b names the first branch; without it Git uses init.defaultBranch, or master if that is not set, a default Git has announced will become main in Git 3.0.
Copy a repository from a URL
risk: safegit clone <url>git clone -b <branch> <url>starting on another branch
git clone --depth 1 <url>only the latest commit, for a quick download
Clone makes a folder named after the repository, downloads its history and checks out the default branch, with the source set up as the remote called origin. A shallow clone also fetches only one branch; git fetch --unshallow brings back that branch’s history, and the other branches need git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" and a git fetch.
Make new repositories start on main
risk: safegit config --global init.defaultBranch main
Sets the name git init gives the first branch from now on (Git 2.28 and later). Repositories that already exist keep their branch names.
Make a short alias for a command
risk: safegit config --global alias.<alias> <command>
After git config --global alias.st status, git st runs git status. The command can carry options, such as "log --oneline --graph".
See every setting and where it comes from
risk: safegit config --list --show-origin --show-scope
Lists each setting with its scope (system, global or local; --show-scope needs Git 2.26) and the file it was read from. Where a setting appears more than once, local wins over global, and global over system.
Stop line endings changing between Windows and Mac or Linux
risk: safegit config --global core.autocrlf trueon Windows
git config --global core.autocrlf inputon Mac and Linux
git add --renormalize .after adding a .gitattributes file
With these, files are stored with LF line endings and Windows checkouts get CRLF. A .gitattributes file holding "* text=auto" makes the repository store LF for everyone who clones it, whatever their settings; renormalize then re-stages files already committed with CRLF.
See what has changed
risk: safegit statusgit status -sone line per file
Shows the current branch, files staged for the next commit, changes not yet staged, and files Git is not tracking.
Stage changes for the next commit
risk: safegit add <file>git add -pchoose piece by piece
git add -Aevery change, new and deleted files included
Staging picks what goes into the next commit. git add -p walks through each changed hunk and asks; y stages it, n leaves it, s splits it smaller.
Commit the staged changes
risk: safegit commit -m <message>
Records what is staged as a new commit on the current branch. Without -m, Git opens your editor for the message, where the first line is the summary and a blank line separates the body.
Stage every tracked change and commit in one go
risk: safegit commit -am <message>
-a stages changes to files Git already tracks before committing. New files are not included; add those with git add first.
See exactly what changed
risk: safegit diffchanges not yet staged
git diff --stagedwhat the next commit holds
git diff HEADboth together
Shows line-by-line changes. --staged (or its older name --cached) compares the staged files with the last commit; plain git diff compares your files with what is staged.
Delete or rename a tracked file
risk: safegit rm <file>delete it and stage the deletion
git mv <file> <to>rename or move it
Both change the file and stage the change in one go, ready to commit. Deleting or renaming in your file manager works too; git add -A then stages it, and Git works out a rename from the content.
Make an empty commit, to trigger a build
risk: safegit commit --allow-empty -m <message>
A commit with no changes, still pushed and still seen by CI. Useful to re-run a pipeline without touching a file.
Unstage a file, keeping the changes
risk: safegit restore --staged <file>git restore --staged .everything
Takes the file out of the next commit; your edits stay in the file. The older spelling, still common in answers online, is git reset HEAD <file>. Before the first commit there is no HEAD to restore from, so use git rm --cached <file> instead.
Throw away changes you have not committed
risk: can lose workgit restore <file>one file or folder
git restore .every file
Puts files back as they are in the staging area, which is the last commit unless you staged something since. Edits never committed are not in the reflog, so they are lost for good. The older spelling is git checkout -- <file>. New files Git does not track are left alone; git clean removes those.
Undo the last commit, keeping its changes staged
risk: rewrites historygit reset --soft HEAD~1
Moves the branch back one commit and leaves that commit’s changes staged, ready to commit again. If the commit was already pushed, others may have it; use git revert instead.
Undo the last commit, keeping its changes in your files
risk: rewrites historygit reset HEAD~1
Moves the branch back one commit and unstages its changes, which stay in your files. --mixed is the default, so this is the same as git reset --mixed HEAD~1.
Undo the last commit and throw its changes away
risk: can lose workgit reset --hard HEAD~1
Moves the branch back one commit and makes your tracked files match, discarding that commit and any uncommitted changes to tracked files. The commit can be found again through git reflog for a while; the uncommitted changes cannot.
Undo a merge, pull, rebase or reset you just did
risk: rewrites historygit reset --keep ORIG_HEADafter a merge, pull, rebase or reset --hard
git reset ORIG_HEADafter a plain or --soft reset, whose changes are still in your files
git reset --soft 'HEAD@{1}'after git commit --amend, keeping what you added staged
Merge, pull, rebase and reset save where the branch was in ORIG_HEAD, so this puts it back. --keep refuses rather than overwrite uncommitted changes in files it would touch. HEAD@{1} is the previous entry in the reflog; check git reflog first if you have done more since. A merge or rebase that stopped on a conflict is undone with git merge --abort or git rebase --abort instead.
Change the message of the last commit
risk: rewrites historygit commit --amend -m <message>
Replaces the last commit with one that has the new message. Anything staged goes in too, so check git status first. A pushed commit then needs a force push.
Add a forgotten file to the last commit
risk: rewrites historygit add <file>git commit --amend --no-editkeeps the message
Replaces the last commit with one that also holds the file. The new commit has a different ID, so a pushed commit then needs a force push.
Change the author of the last commit
risk: rewrites historygit commit --amend --reset-author --no-editto your current name and email
git rebase -r <commit> --exec "git commit --amend --no-edit --reset-author"every commit after <commit>
Fix your name and email with git config first, then reset the author to them. To set someone else, use --author "Name <email>" instead of --reset-author. Each changed commit gets a new ID.
Undo a pushed commit without rewriting history
risk: safegit revert <commit>git revert -m 1 <commit>a merge commit, keeping the side it was merged into
Makes a new commit that does the opposite of the one given, so history stays as it was and nobody else has to recover from a force push. After reverting a merge, merging that branch again does not bring its changes back; revert the revert first.
Make the branch match the remote exactly
risk: can lose workgit fetch origingit reset --hard origin/<branch>
Throws away local commits and changes on this branch and makes it identical to the remote’s copy. Untracked files are left alone; git clean removes those.
Get back a commit or branch you lost
risk: safegit reflogfind the commit you were on
git switch -c <branch> <commit>put a branch on it
The reflog lists every commit HEAD has pointed at, including ones left behind by a reset, an amend or a bad rebase, and the tips of deleted branches you had checked out. Entries are kept for 90 days by default, or 30 for commits the branch no longer contains, and only in your own clone. git branch -D prints the commit the branch was at, which works too.
Bring back a file as it was in an earlier commit
risk: can lose workgit restore --source <commit> --staged --worktree <file>
Puts the file back as it was at that commit, in your folder and staged, ready to commit. Your current changes to that file are lost. The older spelling is git checkout <commit> -- <file>.
Bring back a file that was deleted
risk: safegit log --diff-filter=D -- <file>find the commit that deleted it
git restore --source <commit>~1 --staged --worktree <file>from just before it
A deleted file is still in every commit before the deletion. If you deleted it but have not committed that yet, git restore <file> is enough.
Stop tracking a file but keep it on disk
risk: safegit rm -r --cached <file>git commit -m <message>
Removes the file (or folder, which is what -r is for) from the repository from the next commit on, leaving your copy alone. Add it to .gitignore so it is not added again: .gitignore only affects files Git is not already tracking. Anyone who pulls this commit has the file deleted from their folder.
Delete untracked files
risk: can lose workgit clean -ndlist what would go
git clean -fddelete files and folders
Removes files Git does not track. Files matched by .gitignore are kept unless you add -x. Always run -nd first, which lists folders too: deleted untracked files are not in Git, so it cannot bring them back.
Back out of a merge or rebase that went wrong
risk: can lose workgit merge --abortgit rebase --abort
Returns the branch to where it was before the merge or rebase began, and nothing committed is lost. Conflict fixes made so far are, and a merge cannot always restore uncommitted changes you had when it started, so commit or stash before merging.
List branches
risk: safegit branchgit branch -rremote branches
git branch -vvwith the remote each one follows
git branch --show-currentjust the current one
The current branch is marked with *. Remote branches show as origin/…, as of the last fetch; git branch -a lists both kinds together.
Create a branch and switch to it
risk: safegit switch -c <branch>
Starts the branch at the current commit and moves onto it; uncommitted changes come along. The older spelling is git checkout -b <branch>.
Switch to another branch
risk: safegit switch <branch>git switch -back to the previous one
git switch --track origin/<branch>a remote branch, when several remotes have one of that name
Changes your files to the branch’s latest commit. If you have no branch of that name but exactly one remote does, as of your last git fetch, Git creates a local one that follows it. Git refuses when uncommitted changes would be overwritten; commit or stash them first.
Get out of a detached HEAD
risk: safegit switch -c <branch>keep commits made here on a new branch
git switch -or go back to the branch you were on
Detached HEAD means you checked out a commit or tag rather than a branch. You can look around and even commit, but commits made here belong to no branch and are easy to lose once you switch away; put a branch on them first.
Rename a branch
risk: safegit branch -m <new>the branch you are on
git push -u origin <new>push the new name
git push origin --delete <branch>remove the old name there
git branch -m renames only your local branch; the two pushes do the same on the remote, so git fetch first and check origin/<branch> has nothing you lack. For master to main, change the default branch in your host’s settings before deleting master there; others then run git branch -m master main, git fetch --prune, git branch -u origin/main and git remote set-head origin -a.
Delete a local branch
risk: can lose workgit branch -d <branch>only if it is merged
git branch -D <branch>even if it is not
-d refuses unless the branch is merged into its upstream, or into the current branch if it has none; -D deletes it anyway. Git prints the commit the branch was at, and git branch <branch> <that commit> brings it back.
Delete a branch on the remote
risk: can lose workgit push origin --delete <branch>
Removes the branch from the remote for everyone. Other people’s clones keep their copy of origin/<branch> until they run git fetch --prune.
Merge another branch into this one
risk: safegit merge <branch>
Brings the other branch’s commits into the current one, with a merge commit unless the current branch can simply move forward. On a conflict, fix the files, git add them and run git commit, or git merge --abort.
List branches already merged into this one
risk: safegit branch --mergedgit branch --no-mergedgit branch --merged | grep -vE '^[*+]|^ (main|master|develop)$' | xargs -r git branch -ddelete every merged one but the current and the main ones
--merged lists branches whose commits are all in the current branch. Pull requests merged by squash or rebase do not show here, since their commits were copied rather than merged; delete those with -D. The last line is for bash and zsh, and -d still refuses any branch it judges unmerged.
See what a branch has that another does not
risk: safegit log <base>..<branch>the commits
git diff <base>...<branch>the changes since it split off
With two dots, git log lists commits on <branch> that are not on <base>. With three dots, git diff compares <branch> with the point where it left <base>, which is what a pull request shows.
Push a new branch and set it to track the remote
risk: safegit push -u origin <branch>git push origin HEAD:<branch>the current branch under another name
git branch -u origin/<branch>change which remote branch it follows
Creates the branch on the remote and remembers it, so later a plain git push and git pull know where to go.
Get the latest changes from the remote
risk: safegit pullgit pull --rebasereplay your commits on top instead of merging
git pull origin <branch>a given branch into the current one
git pull is git fetch followed by a merge, or a rebase with --rebase. When both sides have new commits Git stops and asks you to choose: pass --rebase or --no-rebase, or set git config --global pull.rebase true (or false) once.
Download from the remote without changing your branch
risk: safegit fetch --prunegit fetch --all --pruneevery remote
Updates origin/… to match the remote and, with --prune, drops the ones deleted there. Your branches and files do not change until you merge or rebase.
Update a fork from the original repository
risk: rewrites historygit remote add upstream <url>once, with the original’s URL
git fetch upstreamgit rebase upstream/mainor git merge upstream/main
git pushwith --force-with-lease if the rebase moved pushed commits
Your fork does not follow the original by itself. With the original added as upstream, fetch its commits and replay your branch on top of them, then push to your fork.
Push after rewriting history, safely
risk: rewrites historygit push --force-with-lease --force-if-includes
Overwrites the remote branch with yours, but refuses if it has commits you have not seen, which plain --force would wipe out. An editor that fetches in the background makes commits count as seen; --force-if-includes (Git 2.30) also checks they are in your branch. Others who have the old commits will need to reset onto the new ones.
Add a remote
risk: safegit remote add <remote> <url>git remote -vcheck
Gives a name to another copy of the repository, which you can then fetch from and push to by that name.
Change, rename or remove a remote
risk: safegit remote set-url <remote> <url>point it somewhere else
git remote -vsee each remote and its URL
git remote rename <remote> <new>git remote remove <remote>
set-url is for a repository that moved, or to switch between HTTPS and SSH. Renaming moves its remote branches too, origin/… becoming <new>/….
See the history as a graph
risk: safegit log --oneline --graph --all
One line per commit, with lines drawing how branches split and merge, across every branch. Leave out --all for the current branch only.
See what a commit changed
risk: safegit show <commit>git show --stat <commit>files only
Shows the commit’s author, date, message and diff. A short ID such as a1b2c3d is enough.
See a file as it was at a commit
risk: safegit show <commit>:<file>
Prints the file’s content at that commit without touching your copy. The path is from the top of the repository, or start it with ./ to make it relative to where you are.
See the history of one file
risk: safegit log --follow -p -- <file>
Every commit that touched the file, with its changes. --follow keeps going back past a rename.
See who last changed each line
risk: safegit blame <file>git blame -L <start>,<end> <file>only some lines
Shows the commit, author and date behind each line. Add -w to ignore whitespace changes, and -C to see past code moved from another file.
Find the commit that added or removed some text
risk: safegit log -S <text>in the code
git log --grep <text>in commit messages
-S lists commits that change how many times the text appears, which finds when a function was added or deleted. Add -p to see the changes.
Search the tracked files for some text
risk: safegit grep -n -e <text>
Like grep, but only in files Git tracks, so build output and dependencies are skipped. -n shows line numbers, and -e lets the text start with a dash.
Find the commit that introduced a bug
risk: safegit bisect startgit bisect badthe current commit has the bug
git bisect good <commit>a commit without it
git bisect resetwhen it names the culprit
Git checks out the commit halfway between good and bad; test it and say git bisect good or git bisect bad, and it halves again until one commit is left. git bisect run with a test script does it unattended.
Count commits by author
risk: safegit shortlog -sn HEAD
One line per author with the number of commits, most first. HEAD makes it read the history even in a script, where without one it waits for input instead. Use --all for every branch.
Squash the last few commits into one
risk: rewrites historygit reset --soft HEAD~<n>keep the changes, drop the commits
git commit -m <message>
Replaces the last <n> commits with a single one holding all their changes. git rebase -i HEAD~<n>, marking all but the first as squash, does the same while letting you keep their messages.
Edit, reorder or reword older commits
risk: rewrites historygit rebase -i HEAD~<n>
Opens the last <n> commits in your editor, oldest first. Change pick to reword, edit, squash, fixup or drop, or move lines to reorder, then save. Every commit from the first one changed onward gets a new ID.
Replay this branch on top of another
risk: rewrites historygit rebase <base>git fetch originor onto the remote’s latest
git rebase origin/<base>
Moves this branch’s commits so they start from the tip of <base>, as if you had begun the work there, giving a straight history. On a conflict, fix it, git add the file and git rebase --continue.
Copy one commit onto this branch
risk: safegit cherry-pick <commit>git cherry-pick --abortgive up on a conflict
Applies the changes of that commit here as a new commit with a new ID; the original stays where it was. Add -x to note the original ID in the message. A range such as A^..B copies A through B.
Move the last commits to a new branch
risk: rewrites historygit branch <branch>a new branch keeps the commits
git reset --keep HEAD~<n>take them off this one
git switch <branch>
For commits made on main that belonged on a branch. The commits are kept on the new branch. --keep refuses rather than overwrite uncommitted changes in files it would touch.
Resolve a conflicted file by taking one side whole
risk: can lose workgit checkout --ours <file>keep the branch you are on
git checkout --theirs <file>keep the incoming one
git add <file>
During a merge, ours is your branch and theirs is the one being merged. During a rebase they swap: ours is the branch you are rebasing onto and theirs is your own commit being replayed.
List the files with conflicts
risk: safegit diff --name-only --diff-filter=U
U is unmerged: files Git still counts as conflicted because they have not been git add-ed since the conflict, whether or not the <<<<<<< markers are still in them.
Put changes aside to work on something else
risk: safegit stash push -m <message>git stash push -u -m <message>untracked files too
git stash push -m <message> -- <file>one file
Saves your uncommitted changes and makes your files match the last commit, so you can switch branches. Without -u, new files that are not tracked stay behind.
See and bring back stashed changes
risk: safegit stash listgit stash show -p <stash>what a stash holds
git stash popthe latest, removing it from the list
git stash apply <stash>a given one, keeping it
pop applies the most recent stash and drops it if that worked; on a conflict it keeps the stash. Number 0 is the latest, 1 the one before; stash@{1} is the same thing spelled out.
Delete a stash
risk: can lose workgit stash drop <stash>git stash clearevery stash
Removes the stash from the list. Git prints the dropped stash’s ID, and git stash apply <that ID> brings it back. Without it, git fsck --unreachable lists candidates, which is slow going.
Tag a release
risk: safegit tag -a <tag> -m <message>git push origin <tag>tags are not pushed on their own
An annotated tag (-a) records who tagged it, when and why, which is what releases want; git tag <tag> alone makes a lightweight one. Add a commit after the name to tag an older one.
List tags
risk: safegit tag -lgit tag -l --sort=-v:refnamenewest version first
git describe --tagsthe nearest tag to here
git tag -l lists tags alphabetically, so v1.10 comes before v1.2; sorting by v:refname orders them as versions. git describe names the current commit by the nearest tag and how many commits past it; --tags lets it use lightweight tags too.
Move a tag to another commit
risk: rewrites historygit tag -a -f <tag> <commit> -m <message>git push --force origin refs/tags/<tag>
-a keeps it an annotated tag; without it, -f would make a lightweight one. Others who fetched the old tag keep it, since git fetch does not replace a tag it already has; they need git fetch --tags --force. That is why a published release usually gets a new version number instead.
Delete a tag
risk: safegit tag -d <tag>git push origin --delete refs/tags/<tag>on the remote
Git prints the ID the tag pointed at, so git tag <tag> <that ID> makes it again. refs/tags/ makes sure a branch of the same name is not deleted instead. Clones that already fetched the tag keep it.
Check out a second branch in another folder
risk: safegit worktree add <path> <branch>git worktree remove <path>when done
Gives a branch its own folder sharing the same repository, so you can fix something on another branch without stashing. A branch can be checked out in one worktree at a time.
Fetch the submodules of a repository
risk: safegit submodule update --init --recursive
Clones and checks out every submodule at the commit the repository records, nested ones too. git clone --recurse-submodules does it while cloning.
Remove a file from the whole history, such as a leaked secret
risk: rewrites historygit filter-repo --invert-paths --path <file>in a fresh clone
git remote add origin <url>filter-repo removes it on purpose
git push --force --allgit push --force --tags
git filter-repo is a separate tool you install first, and the one Git’s own documentation recommends over filter-branch. It rewrites every commit, so everyone must re-clone, and a host may keep old commits in pull requests and caches until its support removes them. A leaked secret must be revoked anyway: it has already been seen.
Export the files at a commit as a zip
risk: safegit archive --format=zip -o <zip> <commit>
Writes the tracked files as they were at that commit, without the .git folder. Use HEAD for the current commit, or a tag.
about this tool
A Git cheat sheet you search by task
Type what you are trying to do, in your own words — undo the last commit, delete a remote branch, find who changed a line — and only the tasks that match are shown, best match first. Each task gives the exact commands, what they do, and the older spelling where answers online still use it. Common words such as how, the and git are ignored; every other word has to match the start of a word in the task, the other words people use for it, its commands or its explanation, so "rebas" finds rebase. A word no task mentions is set aside and named; when no task has every other word, the ones with the most of them are shown, and the page says so.
Fill in your branch, file or commit once under your names and every command on the page uses it; a number that is not one, or a name starting with a dash that Git would read as an option, is pointed out and left out of the commands until it is fixed. Values are quoted for bash, zsh and Git Bash when they need it, so a message with spaces or an apostrophe pastes as one argument; PowerShell and the Windows command prompt quote differently. Copy all takes the tasks on screen as a plain-text cheat sheet.
Safe, rewrites history, or can lose work
Every task carries one of three labels:
- safe changes nothing you cannot get back. Even a merge can be undone with git reset --keep ORIG_HEAD straight after, and a cherry-pick with git reset --keep HEAD~1.
- rewrites history replaces commits with new ones: amend, reset, rebase, squash, a force push. That is fine on commits only you have. Once they are pushed, anyone who pulled them has to recover, so on a shared branch prefer git revert, which undoes a commit with a new one.
- can lose work throws away something Git may not be able to give back:
uncommitted changes discarded by
reset --hardorrestore, untracked files removed bygit clean, a stash dropped.
Commits are harder to lose than they look. git reflog lists every commit
your HEAD has pointed at, and deleting a branch prints the commit it was at,
so a branch deleted or reset by mistake can usually be put back. What reflog
cannot bring back is work that was never committed.
What it covers
Setting up, everyday staging and committing, undoing, branches, remotes,
reading history (blame, the pickaxe search git log -S, bisect), rewriting
it, stashes, tags, worktrees, submodules and removing a file from history.
The commands are the forms current Git documents, git switch and
git restore included (Git 2.23 and later), and each built-in one was run
against Git 2.54 in a test repository. Removing a file from all history uses
git filter-repo, a separate tool Git's own documentation recommends over
filter-branch.
Nothing you type is stored or sent anywhere. For the files a new repository needs, the .gitignore and licence generator builds both.
questions
- How do I undo the last commit in Git?
- It depends on what you want to keep. git reset --soft HEAD~1 removes the commit and leaves its changes staged; git reset HEAD~1 leaves them in your files but unstaged; git reset --hard HEAD~1 throws them away. All three rewrite history, so if the commit is already pushed, use git revert <commit> instead, which adds a new commit that undoes it.
- What is the difference between git reset --soft, --mixed and --hard?
- All three move the branch to another commit. --soft stops there, so the changes from the commits you moved past stay staged. --mixed, the default, also unstages them but leaves your files alone. --hard also makes your tracked files match, discarding uncommitted changes to them, which the reflog cannot bring back.
- Is it safe to force push?
- Only on a branch nobody else is working on, and better with git push --force-with-lease --force-if-includes. --force-with-lease refuses if the remote has commits you have not seen; an editor that fetches in the background makes them count as seen, and --force-if-includes (Git 2.30 and later) also checks they are in your branch. Plain --force overwrites them. Anyone who already pulled the old commits has to reset or rebase onto the new ones.
- Can I get back a branch or commit I deleted?
- Usually, from your own clone. git branch -D prints the commit the branch was at, and git reflog lists every commit HEAD has pointed at, including ones left behind by a reset, a rebase or an amend; git switch -c <name> <commit> puts a branch back on one. Reflog entries last 90 days by default, or 30 for commits the branch no longer contains. Changes that were never committed are not in the reflog; if they had been staged, git fsck --lost-found may still find the file contents.
- Should I use git switch and git restore or git checkout?
- Either works. Git 2.23 split checkout’s two jobs into switch (change branches) and restore (bring back files), which are harder to mix up: git checkout <name> switches if <name> is a branch and overwrites a file if it is a path. This reference uses the newer commands and gives the checkout spelling where you will still meet it.
- How do I rename a branch locally and on the remote?
- git branch -m <new> renames the branch you are on (git branch -m <old> <new> for another). Then git push -u origin <new> creates the new name on the remote and tracks it, and git push origin --delete <old> removes the old one. When the branch is the repository’s default, such as master to main, change the default in the host’s settings before deleting the old name.