// Copy & Paste

Git commands, ready to copy

Every snippet comes with a plain explanation and its risk level. Copy responsibly.

Risk

122 commands

Getting started

10 commands

Install Git, create a repository, make the first commit and put it on GitHub.

Is Git installed?

Prints the version. “command not found”? See the Academy lesson “Install Git”.

Safe
$ git --version

Install Git on Windows

With winget, built into Windows 10 and 11. Open a new terminal afterwards.

Safe
$ winget install --id Git.Git -e --source winget

Install Git on macOS

Installs Apple's command line tools, Git included. Or: brew install git.

Safe
$ xcode-select --install

Install Git on Debian / Ubuntu

Fedora: sudo dnf install git. Arch: sudo pacman -S git.

Safe
$ sudo apt install git

Create a repository

Turns the current folder into a Git repository. Once per project, at its root.

Safe
$ git init

Make the first commit

Add a .gitignore first, so node_modules and .env don't end up in it.

Safe
$ git add .
$ git commit -m "chore: initial commit"

Put a local project on GitHub

Create an empty repository on GitHub first. -u links main to origin for the next pushes.

Safe
$ git remote add origin git@github.com:OWNER/REPO.git
$ git push -u origin main

Download a project

Copies the whole repository and its history into a new folder.

Safe
$ git clone git@github.com:OWNER/REPO.git

Clone only the latest version

Downloads only the last commit: much faster for big repositories. Get the rest later with git fetch --unshallow.

Safe
$ git clone --depth 1 https://github.com/owner/repo.git

Clone a single branch

Downloads one branch and checks it out, ignoring the others.

Safe
$ git clone -b dev --single-branch https://github.com/owner/repo.git

Configuration

7 commands

Set Git up once, save time forever.

Tell Git who you are

Written into every commit. Drop --global to set it for one repository only.

Safe
$ git config --global user.name "Your Name"
$ git config --global user.email "you@example.com"

Name new branches main

Used by git init for every new repository.

Safe
$ git config --global init.defaultBranch main

Pull with rebase by default

No more “Merge branch 'main' of …” commits cluttering the history.

Safe
$ git config --global pull.rebase true

Create a readable log alias

Then just type git lg.

Safe
$ git config --global alias.lg "log --oneline --graph --decorate --all"

See your whole configuration

Every setting and the file it comes from. Great to debug a weird behaviour.

Safe
$ git config --list --show-origin

Use VS Code as Git's editor

Commit messages and interactive rebases open in VS Code instead of Vim. --wait makes Git wait until you close the tab.

Safe
$ git config --global core.editor "code --wait"

Line endings on Windows

Converts to CRLF when you check out, back to LF when you commit. On macOS/Linux use input.

Safe
$ git config --global core.autocrlf true

Basics

8 commands

Day-to-day commands to see where you stand and prepare a commit.

Where am I?

Short status with the current branch and how far ahead/behind the remote you are.

Safe
$ git status -sb

Stage only part of a file

Review each change interactively and pick what goes in the commit.

Safe
$ git add -p

See what you are about to commit

Shows the staged changes. Run it before every commit, your reviewers will love you.

Safe
$ git diff --staged

Rename or move a file

Git records the rename directly. Use -f to change only upper/lower case.

Safe
$ git mv old-name.ts new-name.ts

Delete a file and record it

Deletes it from disk and stages the deletion. --cached to keep it on disk.

Caution
$ git rm path/to/file

Summary of what changed

Files changed and number of lines added / removed, without the details.

Safe
$ git diff --stat

Stage and commit all modified files

-a stages every tracked file that changed. New (untracked) files are NOT included.

Safe
$ git commit -am "fix: message"

See changes word by word

Instead of whole lines, shows exactly which words changed. Great for text and docs.

Safe
$ git diff --word-diff

Undo

9 commands

Go back on a change, a commit or a push — from the gentlest to the most brutal.

Fix the last commit

Change the message or add forgotten files. Rewrites the commit: avoid if already pushed.

Caution
$ git commit --amend

Undo the last commit, keep the changes

The commit disappears, its changes stay staged. Perfect to redo a commit.

Caution
$ git reset --soft HEAD~1

Discard changes in a file

Puts the file back to its last committed state. Uncommitted changes are lost for good.

Destructive
$ git restore path/to/file

Unstage a file

Removes the file from the next commit, keeps your changes.

Safe
$ git restore --staged path/to/file

Cancel a pushed commit

Creates a new commit that does the opposite. History stays intact: the team-friendly undo.

Safe
$ git revert <commit>

Make my branch identical to the remote

Throws away local commits AND uncommitted changes. Create a backup branch first.

Destructive
$ git reset --hard origin/main

Bring back an old version of a file

Replaces the file in your working copy with its version from that commit. Commit it to keep it.

Caution
$ git restore --source=<commit> -- path/to/file

Undo a merge that was pushed

Creates a commit that cancels the merge. -m 1 keeps the main line (the branch you merged into).

Caution
$ git revert -m 1 <merge-hash>

Unstage everything

Removes every file from the index. Your changes stay on disk.

Safe
$ git restore --staged .

Branches

9 commands

Create, switch, clean up and move work between branches.

Create and switch to a branch

The modern equivalent of git checkout -b.

Safe
$ git switch -c feature/my-feature

List branches already merged

Find the branches you can safely delete.

Safe
$ git branch --merged main

Delete a merged branch

-d refuses if the branch is not merged. -D forces it (and you will end up on our Emergency page).

Caution
$ git branch -d feature/old

Rename the current branch

Local rename only. Push the new name and delete the old one on the remote if needed.

Safe
$ git branch -m new-name

Update my branch on top of main

Replays your commits on the latest main. Rewrites your branch: only on branches you own.

Caution
$ git fetch origin
$ git rebase origin/main

Copy a commit to the current branch

Applies the changes of one specific commit here.

Safe
$ git cherry-pick <commit>

Go back to the previous branch

Like cd - in a terminal: jumps back to the branch you were on before.

Safe
$ git switch -

List local and remote branches

Remote ones appear as remotes/origin/… Run git fetch first to be up to date.

Safe
$ git branch -a

Branches, most recent first

Finds the branch you worked on yesterday among fifty.

Safe
$ git branch --sort=-committerdate

History

17 commands

Understand what happened, when, and who did it.

See the whole history as a graph

The best way to understand what is going on before fixing anything.

Safe
$ git log --oneline --graph --decorate --all

Your last hope

Every position HEAD went through, even after resets and deleted branches.

Safe
$ git reflog

Who wrote this line?

Spoiler: it was probably you. -w ignores whitespace, -C follows moved code.

Safe
$ git blame -w -C path/to/file

Find when some code appeared

Lists commits that added or removed this string.

Safe
$ git log -S "functionName" --oneline

Find the commit that broke everything

Binary search through history. Finish with git bisect reset.

Safe
$ git bisect start
$ git bisect bad
$ git bisect good <commit>

See what a commit changed

Message, author and full diff of one commit.

Safe
$ git show <commit>

Compare a branch with main

Three dots: only what the branch added since it left main. Exactly what a PR shows.

Safe
$ git diff main...feature/my-feature

History of one file

--follow keeps going through renames.

Safe
$ git log --follow --oneline -- path/to/file

See a file as it was in an old commit

Prints it without touching your working copy. Redirect with > to save it.

Safe
$ git show <commit>:path/to/file

Commits by someone, over a period

Also works with --until, --grep="fix" to search messages.

Safe
$ git log --author="Alice" --since="2 weeks ago" --oneline

Who committed the most

Number of commits per author. Add --no-merges to skip merge commits.

Safe
$ git shortlog -sn

Search text in tracked files

Fast, ignores node_modules and other ignored files. Add a commit to search an old version.

Safe
$ git grep -n "TODO"

Commits not pushed yet

What you have and the server doesn't (after a git fetch).

Safe
$ git log origin/main..HEAD --oneline

What's new on the server

The commits you will get with your next pull, without pulling yet.

Safe
$ git fetch && git log HEAD..origin/main --oneline

Search commit messages

Every commit whose message contains the word. Add -i to ignore case.

Safe
$ git log --oneline --grep="login"

What happened recently

Commits of the last two weeks. Also works with “yesterday”, “2026-11-01”…

Safe
$ git log --since="2 weeks ago" --oneline --no-merges

Who wrote these lines

Blame only lines 10 to 30, with the commit and author of each.

Safe
$ git blame -L 10,30 path/to/file

Remote

12 commands

Talk to GitHub / GitLab: fetch, push, remotes and tags.

Where do I push?

Lists the remotes and their URLs.

Safe
$ git remote -v

Change the remote URL

After renaming a repo or switching from HTTPS to SSH.

Caution
$ git remote set-url origin git@github.com:OWNER/REPO.git

Tag a release

Tags are not pushed by default: push them explicitly.

Safe
$ git tag -a v1.2.0 -m "v1.2.0"
$ git push origin v1.2.0

Pull without merge commits

Keeps a linear history by replaying your local commits on top.

Caution
$ git pull --rebase

Push a new branch

Publishes the current branch and links it to the remote.

Safe
$ git push -u origin HEAD

Force push, but politely

Overwrites the remote only if nobody pushed since your last fetch. Never use plain --force.

Destructive
$ git push --force-with-lease

Forget deleted remote branches

Cleans up origin/* references that no longer exist on the server.

Safe
$ git fetch --prune

Delete a branch on the remote

The branch disappears for everyone. Its commits stay if merged elsewhere.

Destructive
$ git push origin --delete feature/old

Keep a fork up to date

upstream = the original project, origin = your fork.

Caution
$ git remote add upstream git@github.com:ORIGINAL/REPO.git
$ git fetch upstream
$ git rebase upstream/main

Test a GitHub pull request locally

Replace 123 with the PR number.

Safe
$ git fetch origin pull/123/head:pr-123
$ git switch pr-123

Pull only if nothing diverged

Refuses to create a merge commit: either it simply moves your branch forward, or it stops and lets you decide.

Safe
$ git pull --ff-only

Rename a remote

Handy after forking: the original becomes upstream, your fork becomes origin.

Safe
$ git remote rename origin upstream

Pull requests

14 commands

Open, update, review and clean up a pull request (or a GitLab merge request).

Start a pull request branch

Always from an up-to-date main, so the PR only contains your work.

Safe
$ git switch main
$ git pull
$ git switch -c feat/my-change

Push the branch to open the PR

Git prints a link to create the pull request. Then a plain git push updates it.

Safe
$ git push -u origin HEAD

Open a PR from the terminal (GitHub CLI)

--fill takes the title and description from your commits. Add --draft for a draft PR.

Safe
$ gh pr create --fill

Check out a PR to review it (GitHub CLI)

Works for PRs from forks too.

Safe
$ gh pr checkout 123

Status and checks of my PRs

Your open PRs, the reviews waiting for you, and CI results.

Safe
$ gh pr status
$ gh pr checks

Test a GitLab merge request locally

Replace 42 with the merge request number.

Safe
$ git fetch origin merge-requests/42/head:mr-42
$ git switch mr-42

What my PR changes

The three dots compare with where your branch started: exactly the PR's diff.

Safe
$ git diff --stat origin/main...HEAD

The commits of my PR

Should list only your work. Anything else? Your branch started from the wrong place.

Safe
$ git log --oneline origin/main..HEAD

Update my PR with main (merge)

Brings the latest main into your branch. No force push.

Safe
$ git fetch origin
$ git merge origin/main
$ git push

Update my PR with main (rebase)

Replays your commits on the latest main: linear history, needs a force push.

Caution
$ git fetch origin
$ git rebase origin/main
$ git push --force-with-lease

Tidy the PR's commits before merge

Folds your fixup! commits into the ones they fix.

Caution
$ git rebase -i --autosquash origin/main
$ git push --force-with-lease

Sync my fork with the original

Needs the original added as upstream (git remote add upstream …).

Safe
$ git fetch upstream
$ git switch main
$ git merge --ff-only upstream/main
$ git push origin main

Clean up after the PR is merged

After a squash merge, -d refuses: use -D once you checked the PR is merged.

Safe
$ git switch main
$ git pull
$ git branch -d feat/my-change

What changed after a force push

Compares two versions of a PR branch commit by commit: perfect for reviewers.

Safe
$ git range-diff origin/main old-head new-head

Stash

6 commands

Put unfinished work aside without committing it.

Hide your mess for later

Saves changes, including untracked files (-u), with a message you will thank yourself for.

Safe
$ git stash push -u -m "wip: something"

Bring the mess back

Applies the last stash and removes it. On conflict, the stash is kept.

Caution
$ git stash pop

List your stashes

stash@{0} is the most recent.

Safe
$ git stash list

See what's in a stash

The full diff of the stash, without applying it.

Safe
$ git stash show -p stash@{0}

Turn a stash into a branch

Creates a branch where the stash was made and applies it there: no conflict with what changed since.

Safe
$ git stash branch fix/from-stash stash@{0}

Delete a stash

Gone from the list. Recoverable for a while with git fsck if it was a mistake.

Caution
$ git stash drop stash@{0}

Cleanup

6 commands

Remove what Git should not track or keep.

Preview untracked files to delete

Dry run: shows what git clean would delete, deletes nothing.

Safe
$ git clean -nd

Delete all untracked files

Irreversible: Git never knew these files, so it cannot bring them back. Run the dry run first.

Destructive
$ git clean -fd

Stop tracking a committed folder

Removes it from Git, keeps it on disk. Add it to .gitignore right after.

Safe
$ git rm -r --cached node_modules

Why is this file ignored?

Prints the .gitignore file and line that match. No output: the file is not ignored.

Safe
$ git check-ignore -v path/to/file

Preview ignored files to delete (builds, caches)

Capital X: only files listed in .gitignore. Replace -n with -f to really delete.

Safe
$ git clean -ndX

Clean untracked files one by one

An interactive menu: you choose what to delete. Safer than clean -fd.

Caution
$ git clean -i

Tags & releases

6 commands

Mark versions, publish them, find which version you are on.

List tags, newest first

Filter with a pattern: git tag --list "v2.*".

Safe
$ git tag --list --sort=-creatordate

Create an annotated tag

Annotated tags store author, date and message: use them for releases.

Safe
$ git tag -a v1.3.0 -m "Release 1.3.0"

Push commits and their tags

Pushes annotated tags pointing to pushed commits.

Safe
$ git push --follow-tags

Delete a tag (local and remote)

Avoid it for published releases: people may depend on it.

Destructive
$ git tag -d v1.3.0
$ git push origin --delete v1.3.0

Look at the code of a version

Detached HEAD: read-only exploration. Create a branch if you want to fix something there.

Safe
$ git switch --detach v1.2.0

Which version am I on?

E.g. v1.2.0-4-g3f9a2c1 = 4 commits after v1.2.0.

Safe
$ git describe --tags

Rewrite history

6 commands

Clean up commits before sharing them: squash, reword, reorder. Only on commits not pulled by others.

Rewrite the last 5 commits

pick, reword, squash, fixup, drop, or reorder lines. Only on commits not shared yet.

Caution
$ git rebase -i HEAD~5

Fix an older commit cleanly

The fix is merged into the target commit automatically during the rebase.

Caution
$ git commit --fixup <commit>
$ git rebase -i --autosquash main

Add a forgotten file to the last commit

Keeps the message. Not pushed yet only.

Caution
$ git add forgotten-file.ts
$ git commit --amend --no-edit

Squash a whole branch into one commit

Every change since the branch left main, in one commit.

Caution
$ git reset --soft $(git merge-base HEAD main)
$ git commit -m "feat: my feature"

Move commits to another base

Takes the commits of my-branch after old-base and replays them on main.

Caution
$ git rebase --onto main old-base my-branch

Resolve the same conflict only once

Git remembers how you resolved a conflict and replays it next time.

Safe
$ git config --global rerere.enabled true

Advanced

12 commands

Worktrees, submodules, Git LFS, hooks, signing and maintenance.

Work on two branches at the same time

A second folder with another branch, sharing the same repository. No stash needed.

Safe
$ git worktree add ../hotfix main
$ git worktree list

Remove an extra worktree

Refuses if it has uncommitted changes (unless --force).

Caution
$ git worktree remove ../hotfix

Add a repository inside yours

Pins a specific commit of the other repository. Commit .gitmodules too.

Safe
$ git submodule add https://github.com/OWNER/lib.git vendor/lib

Download submodules after a clone

Or clone with --recurse-submodules from the start.

Safe
$ git submodule update --init --recursive

Version big files with Git LFS

The repository stores a pointer; the file lives on the LFS server.

Safe
$ git lfs install
$ git lfs track "*.psd"
$ git add .gitattributes

Share Git hooks with the team

Hooks in .githooks/ (versioned) instead of .git/hooks/ (not versioned).

Safe
$ git config core.hooksPath .githooks

Export the project as a zip

Only tracked files, without .git.

Safe
$ git archive --format=zip -o release.zip HEAD

Repository size and clean-up

gc compresses the database. Never use --prune=now while recovering lost commits.

Safe
$ git count-objects -vH
$ git gc

Sign commits with your SSH key

Add the key as a “Signing key” on GitHub to get the Verified badge.

Safe
$ git config --global gpg.format ssh
$ git config --global user.signingkey ~/.ssh/id_ed25519.pub
$ git config --global commit.gpgsign true

Check the repository's integrity

Finds corrupt or missing objects, and lost commits (dangling).

Safe
$ git fsck --full

Find the guilty commit automatically

Git tests commits by binary search with your command, then names the first bad one. Finish with git bisect reset.

Safe
$ git bisect start HEAD v1.0.0
$ git bisect run npm test

Only check out some folders (monorepo)

The other folders disappear from your disk (not from the repository). git sparse-checkout disable brings everything back.

Safe
$ git sparse-checkout set apps/web packages/ui