# Check out main in a separate directory:git worktree add ../project-main main
# Now you can work on both branches simultaneously# List all worktrees:git worktree list
Note Worktrees let you have multiple branches checked out at once in different directories, sharing the same .git database. Huge time-saver when you need to quickly fix a bug on main without stashing your feature work.
worktreemultiple checkoutswork on two branchesparallel branches
# Add a submodule:git submodule add https://github.com/lib/shared-utils.git libs/shared# After cloning a repo with submodules:git submodule update--init --recursive# Update submodule to latest:cd libs/shared && git pull origin main
cd ../.. && git add libs/shared && git commit -m "Update shared-utils submodule"
Note Submodules are notoriously tricky. Each submodule is pinned to a specific commit. Collaborators must run git submodule update --init after cloning or they'll have empty directories. Consider alternatives like package managers when possible.
Note Only checks out specified directories from a large repo. Extremely useful for monorepos where you only need a small portion. --filter=blob:none avoids downloading file content you don't need.
# Remove a file from entire history (e.g., accidentally committed secret):git filter-repo --invert-paths --path secrets.env# Extract a subdirectory into its own repo:git filter-repo --path src/auth/
Note WARNING: This rewrites ALL commit hashes. Every collaborator must re-clone. git-filter-repo is a separate tool (pip install git-filter-repo) that replaces the deprecated git filter-branch. Back up your repo before using this.
remove file from historyrewrite historyfilter-reporemove secret from gitextract subdirectory
Git Hooks
syntax
# Hooks live in .git/hooks/# Common hooks: pre-commit, pre-push, commit-msg, post-merge
example
# Create a pre-commit hook that runs linting:# File: .git/hooks/pre-commit#!/bin/sh
npm run lint
if [ $? -ne 0 ]; thenecho"Linting failed. Commit aborted."
exit 1fi# Make it executable:
chmod +x .git/hooks/pre-commit
Note Hooks in .git/hooks/ are local and not committed to the repo. Use tools like Husky (Node) or pre-commit (Python) to share hooks via the repo. The hook must be executable and must exit 0 to allow the action to proceed.
git hookspre-commit hookpre-push hookautomate checksrun tests before commit
# Find your GPG key:
gpg --list-secret-keys --keyid-format=long# Configure Git to sign:git config --global user.signingkey ABC123DEF456git config --global commit.gpgsign true# Verify a signed commit:git log --show-signature -1
output
gpg: Signature made Mon 30 Mar 14:22:01 2026
gpg: Good signature from "Samira Khan <samira@example.com>"
Note Signing proves you actually authored a commit. GitHub shows a 'Verified' badge for signed commits. You can also use SSH keys for signing (Git 2.34+): git config --global gpg.format ssh
git config --global rerere.enabled true# Now when you resolve a merge conflict, Git remembers.# Next time the same conflict appears, Git resolves it automatically.
output
Recorded resolution for 'src/config.js'.
...
Resolved 'src/config.js' using previous resolution.
Note rerere = 'reuse recorded resolution'. Incredibly useful when you repeatedly rebase a long-lived branch and keep hitting the same conflict. Enable it globally — there's no downside.
# Create .git-blame-ignore-revs in the repo root:# Content: one commit hash per line# a1b2c3d4e5f6... (bulk prettier formatting)git config blame.ignoreRevsFile .git-blame-ignore-revs
git blame src/app.js
Note After running a bulk formatting tool (Prettier, Black, etc.), every line shows you as the author in blame. This file tells Git to skip those commits, preserving meaningful blame history. GitHub also respects this file automatically.
ignore formatting commitblame ignore revsskip bulk commit in blamemeaningful blame
# Bundle the entire repo:git bundle create repo.bundle --all# Bundle just the last 10 commits on main:git bundle create recent.bundle -10 main
# Clone from a bundle (offline transfer):git clone repo.bundle my-project
Note Bundles are single-file snapshots of a repo that can be transferred via USB, email, etc. Useful for air-gapped environments or when network access is limited.
bundle repooffline gittransfer repoexport repogit without network