Git Commands List: The 40 Commands You Actually Need, With Examples (2026)

Git Commands List: The 40 Commands You Actually Need, With Examples (2026)

On our server, git help -a lists exactly 165 Git commands. In day-to-day work we use maybe fifteen of them. The rest are either specialist tools or internal plumbing you never have to touch directly. That is exactly why a Git commands list is useful: it separates what you type every day from what you look up once a year.

This Git commands list is sorted by situation, not alphabetically. First setup, then the daily loop, then branches, then undoing things, then working with other people, and finally the emergency and detective commands. Every command comes with an example you can copy. All output and numbers come from our own tests on 18 October 2026 with Git 2.43 on our Ubuntu server: on a test repository with 100 commits and on a fresh clone of Express.js with 6,182 commits.

If you are not sure yet what a commit or a branch actually is, read our primer What is Git? first. It explains the model behind everything. This article is about the commands.

If you prefer to watch the commands in action first: Conner Ardman’s “Every GIT Command You’ll EVER Need” (May 2026) walks through most of this list in order. The video is for following along, this page is for looking things up.

The Git commands list at a glance

If all you need is a table, here it is. Details for every command follow below.

SituationCommandWhat it does
One-time setupgit config --global user.name "Name"Set your name for commits
New projectgit initCreate a repository in the current folder
Get a projectgit clone <url>Copy an existing repository completely
What’s going on?git statusShow changed, staged and new files
Look at changesgit diffShow line-by-line differences
Stagegit add <file>Put a file into the staging area
Savegit commit -m "message"Create a snapshot with a message
Historygit log --onelineList commits compactly
Create branchgit switch -c <name>Create a new branch and switch to it
Switch branchgit switch <name>Move to an existing branch
Combinegit merge <branch>Bring another branch into the current one
Uploadgit pushSend local commits to the server
Downloadgit pullFetch new commits and integrate them
Just lookgit fetchFetch new commits, change nothing
Put asidegit stashShelve unfinished work
Discard file changesgit restore <file>Throw away uncommitted changes
Undo a commitgit revert <commit>Create an inverse commit, history stays
Jump backgit reset --hard <commit>Move branch and files to an old state
Fix last commitgit commit --amendChange message or content of the last commit
Safety netgit reflogEvery movement of HEAD in recent weeks
Find a buggit bisectBinary search for the guilty commit
Who wrote this?git blame <file>Show the last commit for every line

That is 22 rows. Those commands get you through 95 percent of working days. Below we explain each in detail, plus around 20 more variants and options worth knowing.

A circular conveyor of platforms carrying blocks from a workbench to a tray, into a vault and on to a server, illustrating the daily Git command loop of add, commit and push

Setup: commands for day one

You type these once per machine and then never again.

git config: who are you?

git config --global user.name "Fabian Budde"
git config --global user.email "fabian@example.com"
git config --global init.defaultBranch main
git config --global pull.rebase false

Name and email go into every commit. Without them Git refuses to commit. init.defaultBranch main makes new repositories start with main instead of master. In our test, git init without this setting still started on master, even though GitHub, GitLab and most teams have used main for years. Not a disaster, but an unnecessary source of confusion when your local branch is master and the server’s is main.

pull.rebase false answers a question Git will otherwise ask you sooner or later (more on that below). git config --list --show-origin shows every active setting and the file it comes from.

git init and git clone: starting a repository

# New project in the current folder
git init

# Copy an existing project
git clone https://github.com/expressjs/express.git

# Latest snapshot only, without the full history
git clone --depth 1 https://github.com/expressjs/express.git

git init creates a hidden .git folder that holds the entire memory of the project. git clone fetches someone else’s repository in full, every commit since the beginning.

The difference to a shallow clone with --depth 1 is measurable. Full Express.js clone: 12 MB in .git, done in 0.97 seconds. With --depth 1: 392 KB in 0.54 seconds. For a CI server that only needs to build, the shallow clone is perfect. For development, use the full one, otherwise git log, git blame and git bisect have no data to work with.

The daily loop: status, add, commit

Ninety percent of your Git time is spent in a loop of four commands: look, stage, save, upload.

git status: the most important command

git status
git status -s      # short form

If you only memorise one Git command, make it this one. It tells you which branch you are on, which files are modified, which are staged, and which Git does not know about yet. It is also fast: on the Express repository it took 8 milliseconds. There is no reason not to type it constantly.

The short form -s shows two columns: left is the staging area, right is the working directory. M means modified, A added, ?? untracked.

git diff: what exactly did I change?

git diff                 # working directory vs. staging area
git diff --staged        # staging area vs. last commit
git diff main..feature   # compare two branches
git diff --stat HEAD~3   # summary of the last three commits

The most common beginner surprise: you have already staged files with git add, and now git diff shows nothing. That is correct. Without options, git diff only compares what has not been staged. For staged changes you need --staged.

git add: staging

git add index.html        # one file
git add src/              # a whole folder
git add -A                # everything, including deletions
git add -p                # pick changes piece by piece

git add -p is the most underrated command on this list. Git shows you every change individually and asks whether it belongs in the next commit. That lets you turn one messy afternoon into two clean commits: one for the bug fix, one for the new feature.

git commit: saving

git commit -m "Login form now validates email addresses"
git commit -am "Fix typo"                  # add + commit for tracked files
git commit --amend -m "Better message"     # replace the last commit

-am is handy but has a trap: it only includes files Git already tracks. A newly created file stays out. You usually notice when a colleague reports something missing.

--amend replaces the last commit. The important part: it does not modify it, it builds a new one. In our test, commit 012eb1d became 18a7889 after the amend. A new ID means a different commit as far as Git is concerned. Before you push, that is fine. After you push, it causes trouble, because your history and the server’s no longer match.

git log: the history

git log --oneline
git log --oneline --graph --all
git log -p file.txt               # changes to one file
git log --since="2 weeks ago"
git log --author="Fabian"
git shortlog -sn                  # commits per person

git log is surprisingly fast. All 6,182 Express.js commits were listed by git log --oneline in 40 milliseconds. git shortlog -sn showed 399 authors, led by TJ Holowaychuk with 1,891 commits. With --graph --all you see branches as an ASCII tree, which during merge trouble often helps more than any GUI.

Branches: working in parallel

In Git a branch is just a note containing a commit ID. That is why branches are so cheap, and why you should use them generously.

git branch, git switch, git checkout

git branch                    # all local branches
git branch -a                 # including remote branches
git switch -c feature/login   # create and switch
git switch main               # back to main
git branch -d feature/login   # delete (only if merged)
git branch -D experiment      # delete, even if unmerged

git checkout used to do everything: switch branches, create branches, reset files. Since Git 2.23 there are two separate commands for this: git switch for branches and git restore for files. checkout still works but is ambiguous. In our test we created a branch and a file both named dev. git checkout dev then has to guess what you mean. git switch dev can only mean a branch. For beginners the rule is simple: switch for branches, restore for files, checkout only so you can read old tutorials.

Both commands protect you equally well, by the way: with uncommitted changes to a file that differs on the target branch, checkout and switch both refuse with “Your local changes … would be overwritten”. You lose nothing.

git merge: combining

git switch main
git merge feature/login
git merge --abort          # on conflicts, go back

git merge brings another branch’s commits into the current one. If nothing overlaps, it happens silently. If both sides changed the same line, Git reports a conflict and marks the spot in the file with <<<<<<<, ======= and >>>>>>>. You decide what stays, run git add and git commit. And if it gets too much: git merge --abort restores the exact state before the merge. We walk through that in detail in What is Git?.

git rebase: tidying history

git switch feature/login
git rebase main             # replay your commits on top of the latest main
git rebase -i HEAD~3        # edit the last three commits
git rebase --abort

rebase replays your commits as if you had started just now. The result is a straight history without merge commits. With -i (interactive) you can squash, reword or reorder commits. In our test we squashed three commits named “fixup 4/5/6” into one. The history shrank from eight to six commits.

The golden rule: never rebase commits other people already have. Like --amend, rebase creates new commit IDs. For your local feature branch before the first push, that is ideal. For main, it is off limits.

git cherry-pick: taking a single commit

git cherry-pick a1b2c3d

Sometimes you need exactly one commit from a branch, say a bug fix, without the rest. cherry-pick copies it onto your current branch. Again, it is a copy with a new ID, not a reference.

Undoing things: the part everyone is afraid of

This is where beginners mix up commands most often. The distinction becomes clear if you ask: What do I want to take back, and does anyone else already have it?

A mechanism of interlocking gears and a curved track of light leading back to an earlier glowing block, illustrating Git undo commands such as reset, revert and restore

git restore: discarding file changes

git restore index.html              # discard an uncommitted change
git restore --staged index.html     # unstage, keep the change
git restore --source=HEAD~2 app.js  # file as it was two commits ago

git restore is the safest undo command because it only touches files, never history. But what you throw away with git restore file was never committed. Git has no copy of it. That is one of the few ways to genuinely lose work in Git.

git reset: moving the branch back

git reset --soft HEAD~1    # commit gone, changes stay staged
git reset HEAD~1           # commit gone, changes stay (unstaged)
git reset --hard HEAD~1    # commit gone, changes gone

We tested the three variants side by side, each on a repository with three commits where the last commit created the file f3:

VariantCommits aftergit status afterFile f3
--soft2A f3 (staged)still there
--mixed (default)2?? f3 (untracked)still there
--hard2cleandeleted

Memory aid: --soft is “un-commit, keep everything else”, --hard is “everything back to how it was”. All three move the branch, so they rewrite history. That makes them the wrong tool for commits you have already pushed.

git revert: undoing without rewriting history

git revert a1b2c3d
git revert --no-edit HEAD

revert deletes nothing. It creates a new commit that exactly inverts the old one. In our test, git revert took the commit count from 103 to 104, and the commit was automatically named Revert "feat". This is the right choice for anything already on the server: colleagues simply receive one more commit and have nothing to repair.

A small gotcha from testing: git revert --no-edit HEAD -q fails, because revert simply does not accept -q. Other commands like commit or stash pop do. Git is not consistent here.

The rule of thumb

I want to …Command
throw away an uncommitted file changegit restore file
take a file out of the next commitgit restore --staged file
redo my last local commitgit reset --soft HEAD~1 or git commit --amend
undo a pushed commitgit revert <id>
throw everything away and start overgit reset --hard origin/main

git stash: putting work aside

git stash                 # shelve changes
git stash -u              # including new, untracked files
git stash list
git stash pop             # restore and delete the stash
git stash apply           # restore, keep the stash
git stash drop

The classic case: you are halfway through a feature and suddenly a bug fix is needed on main. git stash clears your desk, you switch, fix, come back and bring everything back with git stash pop.

We hit the trap right away in testing. After a plain git stash, git status still showed ?? neu.txt. New files Git does not track yet are not included by git stash without an option. They simply stay where they are and may end up in the wrong commit after a branch switch. Only git stash -u packed the file away; it vanished from the folder and came back with pop. If you do not want to remember that, set an alias (see below).

git clean: deleting untracked files

git clean -n    # show what would be deleted
git clean -fd   # actually delete, including folders

git clean deletes files Git does not track: build leftovers, temp files. There is no trash bin and no reflog for this. So always run -n (dry run) first. In our test it neatly reported “Would remove a.tmp” and “Would remove b.tmp” without touching anything.

git rm —cached: stop tracking a file

git rm --cached .env
echo ".env" >> .gitignore
git commit -m "Stop tracking .env"

This makes Git stop tracking the file while it stays on your disk. What many people miss: the file stays in the history. In our test, git log --all -- .env still showed the commit that added it. If you ever committed a password, treat it as burned and change it. git rm --cached is housekeeping, not damage control.

Collaboration: remote, push, pull, fetch

As soon as a second person or a server is involved, you need the remote commands.

Two floating islands with a laptop and a server, connected by a glowing bridge with cubes travelling both ways, illustrating the Git commands push, pull and fetch

git remote: where does the repository belong?

git remote -v
git remote add origin git@github.com:name/project.git
git remote set-url origin git@github.com:name/new.git

origin is just a nickname for a URL, a convention rather than a rule. For SSH access you need a key; our guide on how to generate an SSH key covers that.

git push

git push                        # upload current branch
git push -u origin feature/x    # first push of a new branch, with tracking
git push --tags
git push --force-with-lease     # careful overwrite

You only need -u on the first push of a branch. After that Git knows where the branch belongs and a plain git push is enough.

—force vs. —force-with-lease: our most important test

If you rewrote an already pushed commit with --amend or rebase, the server rejects a normal push. The temptation is git push --force. That blindly overwrites the server state, even if a colleague pushed something in the meantime. Their work is then gone from the server.

--force-with-lease is considered the safe alternative: Git only overwrites if the server still looks the way you last saw it. We reproduced this with a local bare repository and two clones:

  1. A colleague pushes a new commit.
  2. We amend our last commit and try git push --force-with-lease.
  3. Result: ! [rejected] HEAD -> master (stale info). Good, the protection works.
  4. Then we do what everyone does reflexively when a push fails: git fetch.
  5. Again git push --force-with-lease: + f214804...60af982 HEAD -> master (forced update). The colleague’s commit is overwritten on the server.

--force-with-lease only compares against the state your last fetch saw. A fetch “acknowledges” the foreign commit without you ever looking at it. Since Git 2.30 there is --force-if-includes, which additionally checks whether the remote state is actually contained in your local history. We tested that too: after the same fetch, git push --force-with-lease --force-if-includes refused with ! [rejected] (remote ref updated since checkout). Our recommendation:

git push --force-with-lease --force-if-includes

Even better: never force on main at all, and block force pushes there via branch protection on GitHub or GitLab.

git fetch vs. git pull

git fetch                # fetch new commits, change nothing
git pull                 # fetch + merge
git pull --rebase        # fetch + rebase

git fetch is risk-free. It downloads new commits and updates origin/main, your files stay untouched. git pull then also performs a merge or rebase. In our test the server and the local branch had different commits. git pull downloaded them but then stopped with “You have divergent branches and need to specify how to reconcile them”. Git wants you to decide once: merge (pull.rebase false) or rebase (pull.rebase true). That is why the setting appears in the setup section.

git tag: marking versions

git tag v1.2.0
git tag -a v1.2.0 -m "Release 1.2.0"
git push origin v1.2.0

Tags are branches that never move. Express.js has 306 of them, one for every released version. Tags are not uploaded automatically by git push, which is easy to forget.

Detective and emergency commands

You rarely need these. When you do, they save hours.

git reflog: the safety net

git reflog
git reset --hard HEAD@{2}

Every time HEAD moves (commit, switch, reset, rebase, cherry-pick), Git writes an entry to the reflog. In our small test repository there were 120 entries after an hour of experimenting. If you accidentally typed git reset --hard, you find the old state here and get it back with a second reset. The reflog is local and keeps entries for 90 days by default. It rescues commits, not changes that were never committed.

git bisect: finding the guilty commit

git bisect start
git bisect bad              # current state is broken
git bisect good v1.0        # this state was fine
# … Git checks out the middle, you test and say good or bad …
git bisect reset

# or automatically with a test command:
git bisect run npm test

Bisect is binary search over your history. In our test a bug sat in commit 51 out of 100. git bisect run with a one-line test script found it in 6 steps and 0.05 seconds. With 1,000 commits it would take 10 steps, with a million 20. If “it used to work” describes your problem, this is the command.

A long row of glowing crystals repeatedly split in half by beams of light until a single red crystal remains, illustrating binary bug search with git bisect

git blame: who wrote this line?

git blame lib/application.js
git blame -L 40,60 lib/application.js

The name suggests finger-pointing, but it is about tracing. git blame shows for every line which commit last changed it. Express’s lib/application.js took 33 milliseconds. With the commit ID you then go to git show and read why the line is the way it is.

git log -S: when did this text enter the project?

git log -S "trust proxy" --oneline

The so-called pickaxe does not search commit messages but the content of every change. In Express it found 28 commits that added or removed the string “trust proxy”, across all 6,182 commits in 0.38 seconds. It also finds passwords that were committed and later deleted, which shows why deleted secrets are not safe.

git show: looking at a commit

git show a1b2c3d
git show HEAD~2:src/app.js     # show a file in an old state

git gc: housekeeping

git gc
git count-objects -vH

Git occasionally packs its data on its own. Our test repository had 320 loose objects and a 2.2 MB .git folder after 100 commits. After git gc it was 264 KB, all in one 33 KB pack file. Running it manually is almost never necessary, but it shows how efficiently Git stores data internally.

Aliases: your own Git commands list

What you type daily, you may abbreviate. We use these aliases ourselves:

git config --global alias.st "status -s"
git config --global alias.lg "log --oneline --graph --all --decorate"
git config --global alias.undo "reset --soft HEAD~1"
git config --global alias.save "stash push -u"
git config --global alias.pushf "push --force-with-lease --force-if-includes"

After that, git lg gives you the tree and git save stashes including new files. The stash trap from above is permanently solved.

Common error messages and the matching command

MessageMeaningFix
Please tell me who you areName/email missinggit config --global user.name …
fatal: not a git repositoryYou are in the wrong foldercd into the project or git init
Your local changes would be overwrittenUncommitted changes block the switchgit stash -u, then switch
rejected … (fetch first)Server has newer commitsgit pull, then git push
divergent branchesBoth sides have their own commitsset git config pull.rebase false or true
CONFLICT (content)Same line changed on both sidesedit file, git add, git commit or git merge --abort
You are in 'detached HEAD' stateYou are on a commit, not a branchgit switch -c new-branch to keep your work

Git in practice: where we actually use these commands

On our servers practically everything lives in Git: websites, config files, deploy scripts. A typical day looks like git status, git add -p, git commit, git push. For releases we add git tag, and for live systems a separate worktree on a fixed tag, so nobody accidentally keeps developing on production. That is why we type git switch --detach v2.1.0 more often than you might think.

For automated tasks on the server, such as nightly git pull runs, we combine Git with cron jobs. How to set those up reliably is covered in how to create a cron job. And if you are setting up a new server from scratch, Git is one of the first steps in our Linux server setup guide.

A lesson we learned the hard way: Git is not a backup. A git push to the same server that holds your working copy does not protect you from a disk failure. That is what the 3-2-1 backup strategy is for.

Short and to the point: Thetips4you’s “Git Explained in 10 Minutes” (August 2026) is a compact video cheat sheet that pairs well with the tables on this page.

Conclusion: which Git commands do you really need?

Of the 165 commands, you need exactly eight at the start: status, add, commit, log, switch, merge, push and pull. With those you work cleanly alone and in a team. The next level is the undo commands restore, revert, reset and stash, and here it pays to genuinely understand the difference instead of copying commands from forums. At the top sit reflog, bisect, blame and log -S: rarely needed, but priceless when you do.

Two things from our tests we would tell everyone. First: git stash without -u leaves new files behind. Second: --force-with-lease only protects you until your next fetch, so add --force-if-includes. Neither shows up in most Git commands lists, and both can cost you work.

Bookmark the table at the top. After a few weeks you will not need it anymore.

FAQ: Git commands list

Which Git commands are used most often?

git status, git add, git commit, git push, git pull and git switch. Those six handle most of the daily work. git log and git diff join them for looking things up.

How many Git commands are there?

git help -a lists exactly 165 commands in Git 2.43. Many are internal “plumbing” commands you never use directly. For daily work, 20 to 40 are enough.

What is the difference between git reset and git revert?

git reset moves the branch to an older commit and therefore rewrites history. git revert creates a new commit that inverts an old one and leaves history intact. Use revert for pushed commits and reset for local ones.

What is the difference between git fetch and git pull?

git fetch downloads new commits from the server but changes neither your files nor your branch. git pull additionally merges or rebases, bringing the new commits straight into your work.

Should I use git checkout or git switch?

git switch for branches, git restore for files. Both exist since Git 2.23 and are clearer than the old git checkout, which did both and has to guess when a branch and a file share a name.

How do I undo the last commit?

If it has not been pushed: git reset --soft HEAD~1. The changes stay staged, only the commit is gone. If you only want to change the message: git commit --amend. If it is already on the server: git revert HEAD.

How do I recover a deleted commit?

Use git reflog to find the ID of the old state, then git reset --hard <id> or git switch -c rescue <id>. The reflog keeps entries for 90 days by default, but only locally on your machine.

Does git stash include new files?

Not without an option. A plain git stash only saves changes to files Git already tracks. New files stay in the folder. git stash -u includes them.

Is git push —force-with-lease safe?

Safer than --force, but not foolproof. It only compares against the state of your last git fetch. If you fetch first, you will still overwrite other people’s commits; we reproduced that. Adding --force-if-includes makes the protection considerably better.

Is there a Git commands cheat sheet as a PDF?

The official reference is git help <command> right in the terminal, or the documentation on git-scm.com. GitHub offers a free cheat sheet PDF. You can save the table at the top of this page as a PDF using your browser’s print function.

Do I need the command line, or is a GUI enough?

For daily work a GUI like VS Code’s Git integration or GitHub Desktop is enough. It is still worth learning the commands in the terminal once: every GUI runs exactly these commands under the hood, and error messages refer to them.