Git Cheat Sheet
A practical reference covering day-to-day Git usage, config templates, and bulk automation scripts for GitHub and Azure DevOps.
Versions: Git 2.40+ · gh CLI 2.x
Last reviewed: May 2026
Setup & Configuration
Linux / WSL .gitconfig 🏠 Personal config
Place this at ~/.gitconfig. The credential helper paths assume gh CLI is installed at /usr/bin/gh - adjust if your install location differs.
[alias]
a = add --all
c = commit
p = push
[core]
editor = nano
longpaths = true
[credential]
helper = /mnt/c/Users/<you>/scoop/apps/git/current/mingw64/bin/git-credential-manager.exe
useHttpPath = true
azreposCredentialType = oauth
[user]
name = Your Name
email = you@example.com
[filter "lfs"]
process = git-lfs filter-process
required = true
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
[credential "https://github.com"]
helper =
helper = !/usr/bin/gh auth git-credential
[credential "https://gist.github.com"]
helper =
helper = !/usr/bin/gh auth git-credentialWindows .gitconfig 🏠 Personal config
Place this at %USERPROFILE%\.gitconfig. The gh.exe path assumes Scoop - adjust to your package manager.
[alias]
a = add --all
c = commit
p = push
[core]
editor = nano
longpaths = true
[credential]
useHttpPath = true
azreposCredentialType = oauth
[user]
name = Your Name
email = you@example.com
[filter "lfs"]
process = git-lfs filter-process
required = true
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
[credential "https://github.com"]
helper =
helper = !'C:\Users\<you>\scoop\apps\gh\current\bin\gh.exe' auth git-credential
[credential "https://gist.github.com"]
helper =
helper = !'C:\Users\<you>\scoop\apps\gh\current\bin\gh.exe' auth git-credentialUseful global config one-liners
Quick commands to configure Git globally without editing the file manually.
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global core.editor nano
git config --global init.defaultBranch main
git config --global pull.rebase false # merge on pull (safe default)
git config --global core.autocrlf input # LF on commit, leave checkouts alone (Linux/macOS)
git config --global core.autocrlf true # CRLF on checkout, LF on commit (Windows)Signing commits (GPG) ✅
Signed commits prove authorship and integrity - GitHub shows a Verified badge and branch protection can require signatures. Use the same email for the key, your Git config, and your verified account identity, or verification fails.
1. Generate a key
# Linux / WSL / macOS (gnupg is usually preinstalled; else `sudo apt install gnupg`)
gpg --full-generate-key
# Choose: (1) RSA and RSA · 4096 bits · expiry to taste · your name + commit email# Windows - install Gpg4win (bundles gpg + Kleopatra), then generate the key
winget install GnuPG.Gpg4win # or: scoop install gpg4win
gpg --full-generate-key2. Find the key ID and export the public key
# Key ID is the hex after the algorithm, e.g. rsa4096/ABCD1234EF567890
gpg --list-secret-keys --keyid-format=long
KEYID=ABCD1234EF567890 # substitute yours (PowerShell: $KEYID="...")
gpg --armor --export "$KEYID" # PUBLIC key - paste into the platform
gpg --armor --export "$KEYID" > public-key.asc
gpg --armor --export-secret-keys "$KEYID" > private-key.asc # PRIVATE key - back up securely, never commit3. Add the public key to the platform
- GitHub: Settings → SSH and GPG keys → New GPG key (paste the block), or
gh gpg-key add public-key.asc. - Azure DevOps (Azure Repos): no GPG key upload or Verified badge - the signature is still embedded in the commit and checkable locally with
git verify-commit.
4. Sign automatically
git config --global user.signingkey "$KEYID"
git config --global commit.gpgsign true # sign every commit
git config --global tag.gpgsign true # sign every annotated tag
# Windows: point Git at the gpg binary if it isn't auto-detected
git config --global gpg.program "C:/Program Files (x86)/GnuPG/bin/gpg.exe"
# WSL / headless: let gpg prompt for the passphrase
echo 'export GPG_TTY=$(tty)' >> ~/.bashrc5. Verify
git commit -S -m "signed commit" # -S is implicit once commit.gpgsign=true
git log --show-signature -1 # expect "Good signature"
git verify-commit HEADLighter alternative - SSH signing. Git 2.34+ can sign with an existing SSH key (no GPG):
git config --global gpg.format sshandgit config --global user.signingkey ~/.ssh/id_ed25519.pub, then add it to GitHub as a Signing key. Simpler to manage; reach for GPG when you need keyservers, X.509/S-MIME, or a hardware token (YubiKey).
Core Operations
Daily workflow
git status # what's changed
git diff # unstaged changes
git diff --staged # staged changes ready to commit
git add . # stage everything
git add -p # interactively stage hunks
git commit -m "your message"
git commit --amend --no-edit # add staged changes to last commit (unpushed only)
git push
git push -u origin main # push and set upstream on first push
git pullInitialise a repo
git init
git init --bare # bare repo (for remotes/servers)
git clone https://github.com/org/repo.git
git clone --depth 1 https://github.com/org/repo.git # shallow clone (faster, no history)Branching & Merging
git branch # list local branches
git branch -a # list all branches (local + remote)
git branch feature/my-feature # create branch
git switch feature/my-feature # switch to branch
git switch -c feature/my-feature # create and switch in one step
git merge feature/my-feature # merge into current branch
git merge --no-ff feature/my-feature # always create a merge commit
git branch -d feature/my-feature # delete merged branch
git branch -D feature/my-feature # force delete (even if unmerged)
git push origin --delete feature/my-feature # delete remote branchRebase
git rebase main # rebase current branch onto main
git rebase -i HEAD~3 # interactively squash/edit last 3 commits
git rebase --abort # bail out of an in-progress rebase
git rebase --continue # continue after resolving a conflictRemote Operations
git remote -v # list remotes
git remote add origin https://github.com/org/repo.git
git remote set-url origin https://github.com/org/new-repo.git
git fetch origin # download without merging
git fetch --all # fetch all remotes
git pull origin main
git push origin main
git push --force-with-lease # ✅ safer force push - fails if remote has moved since last fetchUndoing Changes
Discard working directory changes
git restore file.txt # discard unstaged changes to a file
git restore . # discard ALL unstaged changes
git clean -fd # delete untracked files and directoriesUnstage files
git restore --staged file.txt # unstage a file (keep working copy)
git reset HEAD file.txt # older equivalentUndo commits
git revert HEAD # create a new commit that undoes HEAD (safe for shared branches)
git reset --soft HEAD~1 # undo last commit, keep changes staged
git reset --mixed HEAD~1 # undo last commit, keep changes unstaged (default)
git reset --hard HEAD~1 # 🚨 undo last commit and discard all changes (destructive)Recover lost commits (git reflog) ✅
reflog records every move of HEAD - including commits “lost” to a hard reset, a botched rebase, or a deleted branch. It is the primary undo-almost-anything tool. Entries are local-only and expire (≈90 days for reachable, 30 for unreachable), so recover sooner rather than later.
git reflog # every position HEAD has held, newest first
git reflog show feature/my-feature # reflog for a specific branch
# Undo a bad reset/rebase - move HEAD back to where it was N moves ago
git reset --hard HEAD@{1}
# Recover a specific dropped commit onto a fresh branch (non-destructive)
git checkout -b recovered HEAD@{2}
# Restore an accidentally deleted branch: find its old tip, then recreate it
git reflog | grep "branch-name"
git branch branch-name <sha-from-reflog>History & Inspection
git log # full commit history
git log --oneline --graph --all # visual branch graph
git log --oneline -20 # last 20 commits, one line each
git log -- path/to/file # history for a specific file
git show HEAD # show last commit diff
git show abc1234 # show a specific commit
git diff main..feature/my-feature # diff between two branches
git diff HEAD~2 HEAD # diff between commits
git blame file.txt # annotate each line with its last commit
git bisect start # binary search for a bug-introducing commitStashing
git stash # stash current changes
git stash push -m "wip: my description"
git stash list # list all stashes
git stash pop # apply latest stash and drop it
git stash apply stash@{2} # apply a specific stash without dropping
git stash drop stash@{0} # delete a specific stash
git stash clear # delete all stashesTags
git tag # list tags
git tag v1.0.0 # create lightweight tag on HEAD
git tag -a v1.0.0 -m "Release 1.0.0" # annotated tag with message
git push origin v1.0.0 # push a specific tag
git push origin --tags # push all tags
git tag -d v1.0.0 # delete local tag
git push origin --delete v1.0.0 # delete remote tag.gitignore Reference
A general-purpose .gitignore covering Python projects, Terraform, and common IDE artefacts.
# IDE
.idea/
.vscode/
# Python
__pycache__/
*.py[cod]
*.so
.Python
build/
dist/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
pip-log.txt
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
*.cover
.hypothesis/
.pytest_cache/
.mypy_cache/
.dmypy.json
dmypy.json
.pyre/
.python-version
.env
.venv
env/
venv/
ENV/
# Terraform
**/.terraform/*
*.tfstate
*.tfstate.*
crash.log
crash.*.log
*.tfvars
*.tfvars.json
override.tf
override.tf.json
*_override.tf
*_override.tf.json
.terraformrc
terraform.rc
# Jupyter
.ipynb_checkpoints
# macOS
.DS_StoreSee also: Security - Git Secret Hunting for scanning history and detecting credentials that slipped through.
Automation Scripts
Clone all repos in a GitHub org 🏠 Personal workflow helper
Uses the gh CLI - run gh auth login first.
#!/usr/bin/env bash
org="libre-devops"
gh repo list "${org}" --limit 1000 | while read -r repo _; do
gh repo clone "$repo" "$repo"
doneClone all repos in an Azure DevOps project 🏠 Personal workflow helper
Uses the az CLI with the azure-devops extension. The script logs in if needed and skips repos that are already cloned locally.
#!/usr/bin/env pwsh
$Org = "https://dev.azure.com/your_org"
$Proj = "your_project"
if ($Org -notmatch '^https?://dev\.azure\.com/[\w-]+') {
$Org = "https://dev.azure.com/$Org"
}
$AccountInfo = az account show 2>&1
try {
$AccountInfo = $AccountInfo | ConvertFrom-Json -ErrorAction Stop
} catch {
az login --allow-no-subscriptions
}
$DevOpsExtension = az extension list --query '[?name == ''azure-devops''].name' -o tsv
if ($null -eq $DevOpsExtension) {
$null = az extension add --name 'azure-devops'
}
$Repos = az repos list --organization $Org --project $Proj | ConvertFrom-Json
foreach ($Repo in $Repos) {
if (-not (Test-Path -Path $Repo.name -PathType Container)) {
Write-Warning "Cloning $Proj\$($Repo.name)"
git clone $Repo.webUrl
}
}See also: Bash for scripting bulk Git operations. Azure - Azure DevOps CLI for
az reposequivalents when working with Azure DevOps instead of GitHub.
Advanced
Reset git history to a single initial commit 🚨
Rewrites the entire branch history to a single commit. Useful for sanitising a repo before making it public. This is destructive and rewrites remote history - only use it on repos where you control all forks or there are none.
git checkout --orphan temp_branch \
&& git add -A \
&& git commit -m "Initial commit" \
&& git branch -D main \
&& git branch -m main \
&& git push -f origin mainFind which commit introduced a string
git log -S "function myFunction" --oneline
git log --all --full-history -- "**/my-file.ts"Cherry-pick a commit from another branch
git cherry-pick abc1234 # apply a single commit to the current branch
git cherry-pick abc1234^..def5678 # apply a range inclusive of abc1234 through def5678
git cherry-pick --no-commit abc1234 # apply changes without committingWork on multiple branches at once (git worktree)
A worktree checks another branch out into a separate directory that shares the same .git - no stashing, no second clone. Ideal for reviewing a PR or hotfixing main while a long build or test run holds your main checkout.
git worktree add ../app-hotfix main # check out main into a sibling directory
git worktree add -b fix/bug ../app-bug # create and check out a new branch there
git worktree list # show all linked worktrees
git worktree remove ../app-hotfix # remove when done
git worktree prune # clean up stale entries (manually deleted dirs)Anti-patterns
- 🚨
git push --forcewithout--lease- can overwrite commits pushed by others since your last fetch. Always use--force-with-lease, which fails if the remote has moved. - ⚠️ Amending or rebasing already-pushed commits - rewrites history that others may have fetched; causes divergence and requires force-pushing. Only rewrite commits that have never left your machine.
- 🚨 Committing secrets or credentials - once pushed, they’re in history forever (and likely cached by forks/mirrors). Use environment variables or a vault, and rotate immediately if leaked.
- ⚠️ Committing directly to
main/master- bypasses review and CI. Use short-lived feature branches and PRs even for solo projects; it preserves a clean audit trail. - 🔬
git stashas long-term storage - stashes are local and unnamed by default; easy to lose track of or apply to the wrong branch. Use a WIP branch instead for anything lasting more than a few minutes. - 🚨
git clean -fdwithout-n(dry-run) first - irreversibly deletes untracked files and directories including build artefacts you might want. Always run-nto preview first. - 🚨
git reset --hardwith uncommitted work - permanently discards all changes with no recovery path. Stash or commit first.