tallge

Reference / Git by task

Git commands by task

Commands are grouped by intent rather than by subcommand. Where two commands do the same job, the newer and narrower one is listed first.

Set up once

TaskCommand
Name for commitsgit config --global user.name "Your Name"
Email for commitsgit config --global user.email "<email>"
Default branch for new repositoriesgit config --global init.defaultBranch main
Rebase instead of merge on pullgit config --global pull.rebase true
Show the effective setting and where it came fromgit config --show-origin --get pull.rebase

Settings live in three places: --system, --global (your user) and the repository's .git/config. The most specific one wins.

Start or copy a repository

TaskCommand
New repository in the current directorygit init
Copy an existing repositorygit clone <url> [directory]
Copy only recent historygit clone --depth 1 <url>
Add a remote to an existing repositorygit remote add origin <url>

See what changed

TaskCommand
Short status with branch infogit status -sb
Unstaged changesgit diff
Staged changes (what will be committed)git diff --staged
Changes in one file against the last commitgit diff HEAD -- path/to/file
Word-level diff for prosegit diff --word-diff

Stage and commit

TaskCommand
Stage a filegit add path/to/file
Stage parts of files interactivelygit add -p
Unstage, keep the editsgit restore --staged path/to/file
Commit staged changesgit commit -m "Describe the change"
Fix the last commit (message or content)git commit --amend
Add forgotten changes to the last commit, same messagegit commit --amend --no-edit

Amend only commits you have not pushed. Amending rewrites the commit id, and anyone who already pulled the old one will see diverged history.

Branches

TaskCommand
List local and remote branchesgit branch -a
Create a branch and switch to itgit switch -c feature/x
Switch to an existing branchgit switch main
Rename the current branchgit branch -m new-name
Delete a merged branchgit branch -d feature/x
Merge a branch into the current onegit merge feature/x
Replay the current branch on top of maingit rebase main
Squash or reorder the last 4 commitsgit rebase -i HEAD~4

git switch and git restore split the two jobs of the older git checkout: changing branches and restoring files. checkout still works, but a typo in it can overwrite a file when you meant to change branch.

Work with a remote

TaskCommand
Download without changing your branchesgit fetch --prune
Fetch and integrate the upstream branchgit pull
Push and set the upstream the first timegit push -u origin feature/x
Push after a rebase, refusing to overwrite others’ workgit push --force-with-lease
Show remotes and their URLsgit remote -v
Delete a remote branchgit push origin --delete feature/x

Prefer --force-with-lease over --force. It refuses the push if the remote branch moved since your last fetch, so a colleague's commit is not silently dropped.

Read history

TaskCommand
Compact graph of all branchesgit log --oneline --graph --all
Commits touching one file, following renamesgit log --follow -p -- path/to/file
Who last changed each linegit blame -w path/to/file
Commits whose diff adds or removes a stringgit log -S "functionName" --oneline
Show one commitgit show <commit>
Commits on this branch that main does not havegit log main..HEAD --oneline

Undo things

SituationCommandEffect
Discard unstaged edits to a filegit restore path/to/fileedits are gone for good
Undo the last commit, keep changes stagedgit reset --soft HEAD~1rewrites history
Undo the last commit, keep changes unstagedgit reset HEAD~1rewrites history
Throw away the last commit and its changesgit reset --hard HEAD~1rewrites history, deletes work
Undo a pushed commitgit revert <commit>new commit that reverses it
Find a commit you lost with reset or rebasegit reflogread-only
Abort a merge or rebase in progressgit merge --abort / git rebase --abortback to the state before

git reflog records where HEAD has pointed. Entries are kept for 90 days by default (gc.reflogExpire), or 30 days once the commit is no longer reachable from any branch (gc.reflogExpireUnreachable), and are pruned when git gc or git reflog expire runs. After a bad reset, git reset --hard HEAD@{1} usually brings the previous state back. Uncommitted work that --hard discarded is not in the reflog.

Put work aside

TaskCommand
Stash tracked changesgit stash push -m "wip: parser"
Stash including untracked filesgit stash push -u
List stashesgit stash list
Apply the latest stash and drop itgit stash pop
Apply a specific stash, keep itgit stash apply stash@{2}

Find the commit that broke something

git bisect start
git bisect bad                 # current commit is broken
git bisect good v1.4.0         # this tag was fine
# test, then mark each step:
git bisect good   # or: git bisect bad
git bisect reset               # when done

With a script that exits 0 for good and non-zero for bad, git bisect run ./test.sh does the stepping for you. Exit code 125 means "cannot test this commit, skip it".

Clean up

TaskCommand
Show untracked files that would be deletedgit clean -n
Delete untracked files and directoriesgit clean -fd
Also delete ignored files (build output)git clean -fdx
Stop tracking a file but keep it on diskgit rm --cached path/to/file

Always run git clean -n first. Files deleted by clean were never in git, so there is nothing to recover them from.

Sources