Git cheatsheet
Recipes
Sticky notes for commands that I keep forgetting.
Miscellaneous
Getting help
Optimize a repo
Warning
Don’t run git gc while another git gc or a
git maintenance
task is running,
If aggressive options are used, your local repo could be corrupted.
Git stores metadata as loose files until it chooses to consolidate them.
Run git gc manually before backups:
if [[ "$(uname)" == Darwin ]]; then
chflags -R nouchg .git/*
fi
git gc --prune=1.day
git fetch --prune
Editing – commit, rebase, etc.
Unstage a file
Danger
If you omit --staged, you’ll lose your changes.
To remove a file from the index without affecting the working directory, use
Amend without editing
To avoid repeating the message, use --no-edit:
Fix a commit you just pushed
Warning
Although --force-with-lease is much safer than --force,
this still rewrites your branch’s history, which can confuse and inconvenience collaborators.
if [[ "$(git branch --show-current)" =~ master|main ]]; then
printf >&2 \
"%bRefusing on ref '%s'.**\n%b" "\e[1;31m" \
"$(git rev-parse --abbrev-ref HEAD)" "\e[0m"
else
git commit --all --amend --no-edit
git push --force-with-lease
fi
Sign the commit
Use -S<id>, which is a single argument.
For example, if the GPG key is named git, use
Tag for release
Assuming tag.gpgSign is correct, -s/--sign is sufficient.
Example:
Diffs
Better diffs
Use --histogram (a much better diff algorithm) and --color-moved to show rearranged lines.
Only show modified files
To only show files that were edited (i.e. not added, deleted, etc.):
Find overly similar files
You can abuse Git’s copy-detection feature like this:
Regex search
Use -G'regex' to find (edited/added/deleted) lines that match regex.
For example, to diff only Markdown lines like - Category 1C [...], run
Plumbing commands
Common Git problems that require piping Git output.
Git distinguishes between
porcelain and plumbing commands,
where porcelain IO is human-readable and plumbing IO is machine-readable.
Unfortunately, for historical reasons, Git is extremely inconsistent about this distinction.
In fact, git status is a porcelain command, but git status --porcelain is plumbing.
See VonC’s explanation on StackOverflow.
Simple things
Is file $f checked in?
Table of branches
__git_branch_table() {
local sep=$'\x1F'
git for-each-ref \
--sort=-committerdate \
--format="%(refname:rstrip=-1)$sep%(committerdate:short)$sep%(authorname)$sep%(objectname:short)$sep%(subject)" \
refs/heads/ \
| column -t -s "$sep"
}
Tables
Refspec
Useless (redundant) syntax types use ~~strikethrough~~.
| Syntax | Meaning | Example | Valid in |
|---|---|---|---|
refname |
Branch/tag by full name | refs/heads/main |
log, diff, show, blame, rev-list |
refname |
Branch/tag by short name | main |
log, diff, show, blame, rev-list |
sha1 |
SHA-1 or abbreviated SHA-1 | f5c3e2a |
log, diff, show, blame, rev-list |
ref~n |
nth first-parent ancestor of ref |
HEAD~2 |
log, diff, show |
~~ref^~~ |
~~First parent of ref (equiv. to ref~1)~~ |
~~HEAD^~~ |
~~log, diff, show~~ |
ref^n |
nth parent of merge commit ref |
main^2 |
log, diff, show |
a..b |
Commits reachable from b but not a |
feat..main |
log, diff, rev-list |
a...b |
Commits reachable from a xor b |
feat...main |
log, diff |
ref^@ |
All parents of ref (equiv. to ref^1, …) |
HEAD^@ |
log, diff |
ref@{n} |
Value of ref in the reflog n moves ago |
HEAD@{3} |
log, reflog, show |
ref@{date} |
Value of ref at the specified date-time |
main@{now} |
log, show |
~~@{1}~~ |
~~HEAD~~ |
~~@{1}~~ |
~~log, show~~ |
@{-n} |
Value of HEAD in the reflog n moves ago |
@{-1} |
~~log, show |
ref^0 |
Underlying object for annotated tag ref |
v1^0 |
show, log, diff |
~~ref^{}~~ |
~~Underlying object for annotated tag ref~~ |
~~v1^{}~~ |
~~show, log, diff~~ |
ref -- path |
Commits reachable from ref that affect path |
HEAD -- src/ |
log, diff, blame |
†
All is log, diff, show, blame, rev-list.