Git Cheatsheet
A comprehensive quick reference for Git commands, workflows, and best practices. Perfect for developers who need fast access to Git syntax and common operations.
Table of Contents
- Prerequisites
- Configuration
- Repository Initialization
- Staging & Commits
- Branch Management
- Remote Repositories
- History & Inspection
- Undoing Changes
- Stashing
- Tags
- Merging & Rebasing
- Advanced Operations
- Common Workflows
- Troubleshooting
- Best Practices
Prerequisites
Git Version: This cheatsheet requires Git 2.23+. Some commands use newer syntax (e.g., git restore, git switch) introduced in Git 2.23.
# Check Git versiongit --version# β git version 2.43.0
# Verify minimum version (2.23+)git --version | grep -oE '[0-9]+\.[0-9]+' | awk -F. '{if ($1 > 2 || ($1 == 2 && $2 >= 23)) exit 0; else exit 1}'Installation:
- macOS:
brew install gitor download from git-scm.com - Linux:
sudo apt install git(Debian/Ubuntu) orsudo yum install git(RHEL/CentOS) - Windows: Download Git for Windows from git-scm.com
Configuration
Initial Setup π§
# Set username and email (required for commits)git config --global user.name "Your Name"git config --global user.email "your.email@example.com"
# Verify configurationgit config --global user.name# β Your Name
# Set default branch name (Git 2.28+)git config --global init.defaultBranch main
# Set default editorgit config --global core.editor "code --wait" # VS Codegit config --global core.editor "vim" # Vimgit config --global core.editor "nano" # Nano
# Set default pull strategygit config --global pull.rebase false # merge (default)git config --global pull.rebase true # rebaseConfiguration Levels
# System-wide (all users on machine)git config --system <key> <value># Example: git config --system core.editor vim
# Global (current user, all repos)git config --global <key> <value># Example: git config --global user.name "John Doe"
# Local (current repository only)git config --local <key> <value># Example: git config --local user.email "work@company.com"
# View all settingsgit config --listgit config --list --show-origin # Show where each setting comes from
# View specific settinggit config user.namegit config --global user.email
# Remove settinggit config --global --unset user.nameUseful Aliases β‘
# Common shortcutsgit config --global alias.co checkoutgit config --global alias.br branchgit config --global alias.ci commitgit config --global alias.st statusgit config --global alias.unstage 'reset HEAD --'
# Advanced aliasesgit config --global alias.last 'log -1 HEAD'git config --global alias.visual 'log --graph --oneline --all --decorate'git config --global alias.lg 'log --oneline --graph --all --decorate'git config --global alias.amend 'commit --amend --no-edit'
# Use aliasesgit st # β git statusgit co main # β git checkout maingit ci -m "message" # β git commit -m "message"Common Configuration Options
# Enable colored outputgit config --global color.ui auto
# Set line ending handling (Windows)git config --global core.autocrlf true# macOS/Linuxgit config --global core.autocrlf input
# Set default push behaviorgit config --global push.default simple # Push current branch onlygit config --global push.default current # Push current branch to matching name
# Enable credential helper (cache credentials)git config --global credential.helper cachegit config --global credential.helper 'cache --timeout=3600' # 1 hour
# Set merge toolgit config --global merge.tool vimdiffgit config --global diff.tool vimdiffRepository Initialization
Create New Repository π
# Initialize in current directorygit init# β Initialized empty Git repository in /path/to/repo/.git/
# Initialize with specific branch namegit init --initial-branch=maingit init -b main # Shorthand
# Create new directory and initializegit init project-name# β Creates project-name/ directory and initializes repo
# Initialize with initial commitgit init && git commit --allow-empty -m "Initial commit"Clone Existing Repository
# Basic clone (creates repo/ directory)git clone https://github.com/user/repo.git# β Cloning into 'repo'...
# Clone into specific directorygit clone https://github.com/user/repo.git my-folder# β Cloning into 'my-folder'...
# Clone specific branchgit clone -b branch-name https://github.com/user/repo.gitgit clone --branch branch-name https://github.com/user/repo.git
# Shallow clone (faster, less history)git clone --depth 1 https://github.com/user/repo.gitgit clone --depth 5 https://github.com/user/repo.git # Last 5 commits
# Clone without checking out working directorygit clone --no-checkout https://github.com/user/repo.git
# Clone with submodulesgit clone --recurse-submodules https://github.com/user/repo.gitgit clone --recursive https://github.com/user/repo.git # ShorthandVerify Repository Status
# Check if directory is a Git repositorygit rev-parse --is-inside-work-tree# β true (if inside repo) or error (if not)
# Show repository rootgit rev-parse --show-toplevel# β /path/to/repository
# Check repository statusgit statusStaging & Commits
Basic Operations πΎ
# Check status (detailed)git status# β On branch main# β Changes not staged for commit: ...
# Short status formatgit status -s# β M file.txt (Modified)# β A new.txt (Added)# β D old.txt (Deleted)# β ?? untracked.txt (Untracked)
# Stage specific filegit add filename.txt
# Stage multiple filesgit add file1.txt file2.txt
# Stage all changes in current directorygit add .
# Stage all changes in repositorygit add -Agit add --all
# Stage with pattern matchinggit add *.js # All .js filesgit add src/**/*.ts # All .ts files in src/
# Interactive staging (patch mode) - review changesgit add -pgit add --patch# β Stage this hunk [y,n,q,a,d,/,e,?]?
# Unstage files (Git 2.23+)git restore --staged filename.txt
# Unstage files (older syntax)git reset HEAD filename.txtgit reset HEAD -- filename.txt # Safer with --
# Unstage all filesgit restore --staged .git reset HEAD .Committing Changes
# Basic commitgit commit -m "Add user authentication"
# Commit with detailed messagegit commit -m "feat: add user authentication" -m "Implements JWT-based auth with refresh tokens"
# Stage and commit in one step (only tracked files)git commit -am "Update dependencies"# Equivalent to: git add -A && git commit -m "..."
# Amend last commit (change message or add files)git commit --amend -m "New commit message"git commit --amend --no-edit # Keep same message, add staged changes
# Amend with file changesgit add forgotten-file.txtgit commit --amend --no-edit
# Empty commit (useful for CI triggers)git commit --allow-empty -m "Trigger CI build"
# Commit with specific author (override config)git commit -m "Message" --author="John Doe <john@example.com>"
# Commit with date overridegit commit -m "Message" --date="2024-01-01T00:00:00"Commit Message Best Practices
| Type | Format | Example |
|---|---|---|
| feat: | New feature | feat: add user authentication |
| fix: | Bug fix | fix: resolve null pointer exception |
| docs: | Documentation | docs: update API documentation |
| style: | Formatting | style: format code with prettier |
| refactor: | Code refactoring | refactor: simplify payment logic |
| test: | Tests | test: add unit tests for user service |
| chore: | Maintenance | chore: update dependencies |
| perf: | Performance | perf: optimize database queries |
| ci: | CI/CD | ci: add GitHub Actions workflow |
Conventional Commits Format:
<type>(<scope>): <subject>
<body>
<footer>Example:
feat(auth): add JWT token refresh
Implement automatic token refresh mechanism to improveuser experience and security. Tokens refresh 5 minutesbefore expiration.
Closes #123Branch Management
Creating & Switching Branches πΏ
# List local branchesgit branch# β * main# β feature/login
# List remote branchesgit branch -r# β origin/main# β origin/feature/login
# List all branches (local + remote)git branch -a# β * main# β feature/login# β remotes/origin/main
# List with last commit infogit branch -v# β * main abc1234 Initial commit# β feature/login def5678 Add login form
# List branches merged into current branchgit branch --merged
# List branches not merged into current branchgit branch --no-merged
# Create new branch (doesn't switch)git branch feature-name
# Switch to branch (Git 2.23+)git switch feature-name
# Switch to branch (older syntax)git checkout feature-name
# Create and switch in one command (Git 2.23+)git switch -c feature-namegit switch --create feature-name
# Create and switch (older syntax)git checkout -b feature-name
# Create branch from specific commitgit branch feature-name abc123git switch -c feature-name abc123
# Create branch from remote branchgit branch feature-name origin/feature-namegit switch -c feature-name origin/feature-name
# Create branch tracking remotegit branch --track feature-name origin/feature-namegit switch --track origin/feature-name # Auto-name branchDeleting Branches
# Delete local branch (safe - only if merged)git branch -d branch-namegit branch --delete branch-name
# Force delete local branch (even if not merged)git branch -D branch-namegit branch --delete --force branch-name
# Delete remote branchgit push origin --delete branch-namegit push origin :branch-name # Older syntax
# Delete multiple remote branchesgit push origin --delete branch1 branch2 branch3
# Prune remote-tracking branches (delete local refs to deleted remote branches)git fetch --prunegit fetch -p # ShorthandRenaming Branches
# Rename current branchgit branch -m new-namegit branch --move new-name
# Rename specific branchgit branch -m old-name new-name
# Update remote after renamegit push origin -u new-namegit push origin --delete old-name
# Rename and update trackinggit branch -m old-name new-namegit push origin -u new-namegit push origin --delete old-nameBranch Information
# Show current branch namegit branch --show-current# β main
# Show branch tracking infogit branch -vv# β * main abc1234 [origin/main] Initial commit# β feature def5678 [origin/feature: ahead 2] Add feature
# Show which branches contain a commitgit branch --contains abc123git branch -r --contains abc123 # Remote branches onlyRemote Repositories
Managing Remotes π
# List remotesgit remote# β origin
# List remotes with URLsgit remote -v# β origin https://github.com/user/repo.git (fetch)# β origin https://github.com/user/repo.git (push)
# Show remote detailsgit remote show origin# β * remote origin# β Fetch URL: https://github.com/user/repo.git# β Push URL: https://github.com/user/repo.git# β HEAD branch: main
# Add remotegit remote add origin https://github.com/user/repo.gitgit remote add upstream https://github.com/original/repo.git
# Change remote URLgit remote set-url origin https://github.com/user/new-repo.git
# Change remote URL for specific operationgit remote set-url --push origin https://github.com/user/repo.git
# Remove remotegit remote remove origingit remote rm origin # Shorthand
# Rename remotegit remote rename origin upstream
# Update remote URL (HTTPS to SSH)git remote set-url origin git@github.com:user/repo.gitFetching & Pulling
# Fetch updates from remote (doesn't merge)git fetch origin# β Fetching origin...# β remote: Counting objects: 5, done.
# Fetch all remotesgit fetch --allgit fetch -a # Shorthand
# Fetch specific branchgit fetch origin main
# Fetch and prune (remove deleted remote branches)git fetch --prune origingit fetch -p origin # Shorthand
# Pull updates (fetch + merge)git pull origin main
# Pull current branch from tracked remotegit pull
# Pull with rebase instead of mergegit pull --rebase origin maingit pull -r origin main # Shorthand
# Pull specific branchgit pull origin feature-branch
# Pull with no fast-forward (always create merge commit)git pull --no-ff origin main
# Pull and squash commitsgit pull --squash origin mainPushing Changes
# Push to remotegit push origin main
# Push current branch to tracked remotegit push
# Push and set upstream (first push)git push -u origin maingit push --set-upstream origin main
# Push all branchesgit push --all origin
# Push all tagsgit push --tagsgit push origin --tags
# Push specific taggit push origin v1.0.0
# Force push (use with caution!) β οΈgit push --force origin maingit push -f origin main # Shorthand
# Safer force push (fails if remote has new commits)git push --force-with-lease origin main
# Push with specific remote branch namegit push origin local-branch:remote-branch
# Push and delete remote branchgit push origin :remote-branchβ οΈ Warning:
git push --forcerewrites remote history and can cause data loss. Use--force-with-leaseinstead, which fails if someone else has pushed commits you donβt have locally.
History & Inspection
Viewing History π
# Basic log (full details)git log
# Compact one-line formatgit log --oneline# β abc1234 feat: add authentication# β def5678 fix: resolve login bug
# Graph view with all branchesgit log --oneline --graph --all# β * abc1234 (HEAD -> main) feat: add auth# β | * def5678 (feature/login) fix: login bug# β |/# β * ghi9012 Initial commit
# Last N commitsgit log -n 5git log -5 # Shorthandgit log --oneline -5
# Specific authorgit log --author="John Doe"git log --author="John" # Partial match
# Date rangegit log --since="2024-01-01"git log --after="2 weeks ago"git log --before="2024-01-01"git log --since="2024-01-01" --until="2024-01-31"
# File historygit log -- filename.txtgit log --follow -- filename.txt # Includes renames
# Search commit messagesgit log --grep="bug fix"git log --grep="bug" -i # Case insensitive
# Search code contentgit log -S "function_name"git log -S "TODO" --source --all
# Commits affecting specific line rangegit log -L 10,20:filename.txtgit log -L :function_name:filename.txtAdvanced Log Formatting
# Pretty formatting with custom formatgit log --pretty=format:"%h - %an, %ar : %s"# β abc1234 - John Doe, 2 hours ago : Add feature
# Common format placeholders# %h = abbreviated commit hash# %an = author name# %ar = author date, relative# %s = subject (commit message)# %d = ref names# %cr = committer date, relative
# Custom graph view with colorsgit log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
# Show files changedgit log --stat# β Shows file names and line counts
git log --name-only# β Shows only file names
git log --name-status# β Shows file names with status (A/M/D)
# Combine optionsgit log --oneline --graph --all --decorate --statInspecting Changes
# Show specific commit (full diff)git show abc123
# Show commit without diffgit show --stat abc123git show --name-only abc123
# Show commit message onlygit show --no-patch abc123git show -s abc123 # Shorthand
# Diff between commitsgit diff abc123 def456
# Diff between branchesgit diff main feature-branch
# Diff staged changesgit diff --stagedgit diff --cached # Alias
# Diff working directory vs stagedgit diff
# Diff specific filegit diff HEAD filename.txtgit diff HEAD~1 HEAD -- filename.txt
# Word-level diff (instead of line-level)git diff --word-diff
# Ignore whitespace in diffgit diff -wgit diff --ignore-all-space
# Show summary of changesgit diff --statgit diff --shortstatFinding Commits
# Find commit that introduced a bug (use bisect)git bisect startgit bisect bad # Current commit is badgit bisect good abc123 # This commit was good# Git checks out middle commit, test it:git bisect good # or git bisect bad# Repeat until foundgit bisect reset # Return to original branch
# Search commits by contentgit log --all --full-history -- "path/to/file"git log --all --grep="search term"
# Find when a line was added/removedgit log -p -S "search string" -- filename.txtgit log -p --all -S "function_name"Undoing Changes
Discarding Changes β©οΈ
# Discard changes in working directory (Git 2.23+)git restore filename.txtgit restore . # All files
# Discard changes (older syntax)git checkout -- filename.txtgit checkout -- . # All files
# Discard changes in specific directorygit restore src/git checkout -- src/
# Unstage file (Git 2.23+)git restore --staged filename.txtgit restore --staged . # All files
# Unstage file (older syntax)git reset HEAD filename.txtgit reset HEAD -- filename.txt # Safer
# Discard both staging and working directory changesgit restore --source=HEAD --staged --worktree filename.txtReverting Commits
# Create new commit that undoes changes (safe for shared history)git revert abc123# β Creates new commit that reverses abc123
# Revert without committing (stage changes only)git revert --no-commit abc123git revert --no-commit abc123 def456 # Multiple commitsgit commit -m "Revert changes"
# Revert multiple commits (in order)git revert abc123..def456git revert --no-commit abc123^..def456
# Revert merge commitgit revert -m 1 abc123 # -m 1 keeps first parent (main branch)git revert -m 2 abc123 # -m 2 keeps second parent (feature branch)
# Revert with custom messagegit revert -m "Revert: reason for revert" abc123Resetting Commits
# Soft reset (keep changes staged)git reset --soft HEAD~1# β Moves HEAD back, keeps changes in staging area
# Mixed reset (keep changes unstaged) - DEFAULTgit reset HEAD~1git reset --mixed HEAD~1# β Moves HEAD back, keeps changes in working directory
# Hard reset (discard all changes) β οΈgit reset --hard HEAD~1# β Moves HEAD back, discards all changes
# Reset to specific commitgit reset --hard abc123git reset --soft abc123git reset --mixed abc123
# Reset specific file to HEADgit reset HEAD filename.txtgit checkout HEAD -- filename.txt
# Reset to remote branch stategit reset --hard origin/main
# Undo reset with refloggit reflog# β abc1234 HEAD@{0}: reset: moving to HEAD~1# β def5678 HEAD@{1}: commit: previous commitgit reset --hard HEAD@{1} # Restore to before resetβ οΈ Warning:
git reset --hardpermanently deletes uncommitted changes. Always commit or stash important work before using hard reset. Usegit reflogto recover from accidental resets.
Recovering Lost Commits
# View reflog (history of HEAD movements)git reflog# β abc1234 HEAD@{0}: commit: latest commit# β def5678 HEAD@{1}: reset: moving to HEAD~1# β ghi9012 HEAD@{2}: commit: previous commit
# Recover commit from refloggit checkout abc1234git checkout -b recovered-branch abc1234
# Recover deleted branchgit reflog | grep "branch-name"git branch recovered-branch abc1234Stashing
Save Work in Progress π¦
# Stash changes (default message)git stashgit stash save # Explicit
# Stash with messagegit stash save "Work in progress on feature X"
# Stash including untracked filesgit stash -ugit stash --include-untracked
# Stash including ignored filesgit stash -agit stash --all
# Stash specific filesgit stash push -m "message" -- file1.txt file2.txt
# List stashesgit stash list# β stash@{0}: WIP on main: abc1234 Latest commit# β stash@{1}: On feature: def5678 Previous commit
# Show stash contents (summary)git stash showgit stash show stash@{0}
# Show stash diffgit stash show -pgit stash show -p stash@{0}Applying Stashes
# Apply most recent stash (keeps stash)git stash applygit stash apply stash@{0}
# Apply specific stashgit stash apply stash@{2}
# Apply and remove stashgit stash popgit stash pop stash@{0}
# Apply stash to different branchgit checkout other-branchgit stash apply stash@{0}
# Create branch from stashgit stash branch new-branch-name stash@{0}# β Creates branch, applies stash, deletes stash if successfulManaging Stashes
# Delete specific stashgit stash drop stash@{0}
# Delete most recent stashgit stash drop
# Delete all stashesgit stash clear
# Show stash as patch (for sharing)git stash show -p stash@{0} > stash.patch
# Apply patch filegit apply stash.patchTags
Creating Tags π·οΈ
# Lightweight tag (just a pointer)git tag v1.0.0
# Annotated tag (recommended - includes metadata)git tag -a v1.0.0 -m "Release version 1.0.0"
# Tag specific commitgit tag -a v1.0.0 abc123 -m "Tag message"
# Tag with signature (GPG)git tag -s v1.0.0 -m "Signed release"
# Verify tag signaturegit tag -v v1.0.0
# List tagsgit tag# β v1.0.0# β v1.1.0# β v2.0.0
# List tags with pattern matchinggit tag -l "v1.*"# β v1.0.0# β v1.1.0
# List tags sorted by versiongit tag -l --sort=-version:refname "v*"Managing Tags
# Show tag detailsgit show v1.0.0
# Show tag message onlygit tag -l -n1 v1.0.0git tag -l -n3 # Show first 3 lines of each tag
# Push tag to remotegit push origin v1.0.0
# Push all tagsgit push --tagsgit push origin --tags
# Push all tags with commitsgit push --follow-tags
# Delete local taggit tag -d v1.0.0git tag --delete v1.0.0
# Delete remote taggit push origin --delete v1.0.0git push origin :refs/tags/v1.0.0 # Older syntax
# Checkout tag (creates detached HEAD)git checkout v1.0.0
# Create branch from taggit checkout -b release-1.0.0 v1.0.0Tagging Best Practices
Semantic Versioning:
MAJOR.MINOR.PATCH(e.g.,1.2.3)- MAJOR: incompatible API changes
- MINOR: backwards-compatible functionality
- PATCH: backwards-compatible bug fixes
# Example: Tagging a releasegit tag -a v1.2.3 -m "Release 1.2.3: Bug fixes and performance improvements"git push origin v1.2.3Merging & Rebasing
Merging Branches π
# Merge branch into current branchgit merge feature-branch
# Merge with commit messagegit merge feature-branch -m "Merge feature X into main"
# Merge without fast-forward (always create merge commit)git merge --no-ff feature-branch
# Merge with fast-forward only (fails if not possible)git merge --ff-only feature-branch
# Squash merge (combine all commits into one)git merge --squash feature-branchgit commit -m "Add feature X"
# Abort merge (during conflicts)git merge --abort
# Continue after resolving conflictsgit add resolved-file.txtgit merge --continuegit commit # AlternativeHandling Merge Conflicts
# Check conflict statusgit status# β Unmerged paths:# β both modified: file.txt
# See conflicts in files# Look for conflict markers:# <<<<<<< HEAD# current branch changes# =======# incoming branch changes# >>>>>>> feature-branch
# After manually resolving conflictsgit add resolved-file.txtgit commitgit merge --continue
# Use theirs strategy (accept incoming changes)git checkout --theirs filename.txtgit add filename.txt
# Use ours strategy (keep current changes)git checkout --ours filename.txtgit add filename.txt
# Abort merge and return to pre-merge stategit merge --abort
# List conflicted filesgit diff --name-only --diff-filter=URebasing β‘
# Rebase current branch onto maingit rebase main
# Rebase onto specific branchgit rebase origin/main
# Interactive rebase (last 3 commits)git rebase -i HEAD~3
# Interactive rebase from specific commitgit rebase -i abc123
# Abort rebasegit rebase --abort
# Continue after resolving conflictsgit add resolved-file.txtgit rebase --continue
# Skip commit during rebasegit rebase --skip
# Edit commit during rebasegit rebase -i HEAD~3# Change 'pick' to 'edit' for commit# Make changes, then:git add .git commit --amendgit rebase --continueInteractive Rebase Commands
| Command | Action |
|---|---|
pick | Keep commit as is |
reword | Change commit message |
edit | Pause to amend commit |
squash | Combine with previous commit |
fixup | Like squash, discard message |
drop | Remove commit |
exec | Run command |
Example Interactive Rebase:
git rebase -i HEAD~3# Opens editor with:# pick abc1234 First commit# reword def5678 Second commit# squash ghi9012 Third commitβ οΈ Warning: Never rebase commits that have been pushed to a shared branch. Rebasing rewrites history and can cause issues for other developers.
Advanced Operations
Cherry Picking π
# Apply specific commit to current branchgit cherry-pick abc123
# Cherry-pick multiple commitsgit cherry-pick abc123 def456git cherry-pick abc123..def456 # Range (exclusive of abc123)
# Cherry-pick without committinggit cherry-pick --no-commit abc123git add .git commit -m "Custom message"
# Cherry-pick and edit commit messagegit cherry-pick -e abc123git cherry-pick --edit abc123
# Abort cherry-pickgit cherry-pick --abort
# Continue after resolving conflictsgit add resolved-file.txtgit cherry-pick --continue
# Skip commit (if conflicts can't be resolved)git cherry-pick --skipBisect (Find Bugs) π
# Start bisect sessiongit bisect start
# Mark current commit as badgit bisect badgit bisect bad HEAD # Explicit
# Mark known good commitgit bisect good abc123git bisect good v1.0.0 # Can use tag
# After testing each commitgit bisect good # Current commit is goodgit bisect bad # Current commit is bad
# Automate with scriptgit bisect run test-script.sh# Script should exit 0 for good, non-zero for bad
# Skip commit (can't test)git bisect skip
# Visualize bisect progressgit bisect log
# End bisect and return to original branchgit bisect resetSubmodules
# Add submodulegit submodule add https://github.com/user/repo.git path/to/submodule
# Clone repo with submodulesgit clone --recurse-submodules https://github.com/user/repo.gitgit clone --recursive https://github.com/user/repo.git # Shorthand
# Initialize submodules in existing clonegit submodule initgit submodule update
# Initialize and update in one commandgit submodule update --init --recursive
# Update all submodules to latestgit submodule update --remote
# Update specific submodulegit submodule update --remote path/to/submodule
# Remove submodulegit submodule deinit path/to/submodulegit rm path/to/submodulerm -rf .git/modules/path/to/submodulegit commit -m "Remove submodule"
# Show submodule statusgit submodule statusWorking with Archives
# Create ZIP archivegit archive --format=zip --output=project.zip main
# Create tarballgit archive --format=tar.gz --output=project.tar.gz main
# Create tar archivegit archive --format=tar --output=project.tar main
# Archive specific commitgit archive --format=zip abc123 --output=snapshot.zip
# Archive with prefix (adds directory prefix)git archive --format=zip --prefix=project-v1.0/ --output=project.zip v1.0.0
# Archive specific directorygit archive --format=zip main --output=src.zip src/Git Hooks
# List available hooksls .git/hooks/# β applypatch-msg.sample# β pre-commit.sample# β post-commit.sample# β ...
# Create pre-commit hook (example)cat > .git/hooks/pre-commit << 'EOF'#!/bin/sh# Run linter before commitnpm run lintEOFchmod +x .git/hooks/pre-commit
# Bypass hooks (use with caution)git commit --no-verifygit push --no-verifyCommon Workflows
Feature Branch Workflow π
# 1. Create feature branch from maingit checkout maingit pull origin maingit checkout -b feature/new-feature
# 2. Make changes and commitgit add .git commit -m "feat: implement new feature"
# 3. Keep branch updated with maingit fetch origingit rebase origin/main# Or merge: git merge origin/main
# 4. Push to remotegit push -u origin feature/new-feature
# 5. After PR approval, merge to maingit checkout maingit pull origin maingit merge --no-ff feature/new-featuregit push origin main
# 6. Clean up local and remote branchesgit branch -d feature/new-featuregit push origin --delete feature/new-featureHotfix Workflow π₯
# 1. Create hotfix from main/productiongit checkout maingit pull origin maingit checkout -b hotfix/critical-bug
# 2. Fix and commitgit add .git commit -m "fix: resolve critical security issue"
# 3. Test thoroughly, then merge to maingit checkout maingit merge --no-ff hotfix/critical-bug
# 4. Tag releasegit tag -a v1.0.1 -m "Hotfix release v1.0.1"
# 5. Merge to develop (if using Git Flow)git checkout developgit merge hotfix/critical-bug
# 6. Push everythinggit push origin main develop --tagsgit branch -d hotfix/critical-buggit push origin --delete hotfix/critical-bugSync Fork with Upstream β¬οΈ
# 1. Add upstream remote (one-time setup)git remote add upstream https://github.com/original/repo.git
# 2. Verify remotesgit remote -v# β origin https://github.com/your-username/repo.git (fetch)# β origin https://github.com/your-username/repo.git (push)# β upstream https://github.com/original/repo.git (fetch)# β upstream https://github.com/original/repo.git (push)
# 3. Fetch upstream changesgit fetch upstream
# 4. Merge into local maingit checkout maingit merge upstream/main
# 5. Push to your forkgit push origin main
# Alternative: Rebase instead of mergegit checkout maingit rebase upstream/maingit push origin main --force-with-leaseRelease Workflow π―
# 1. Create release branch from maingit checkout maingit pull origin maingit checkout -b release/v1.2.0
# 2. Update version numbers, changelog, etc.# Edit files, then:git add .git commit -m "chore: bump version to 1.2.0"
# 3. Merge to maingit checkout maingit merge --no-ff release/v1.2.0
# 4. Tag releasegit tag -a v1.2.0 -m "Release version 1.2.0"
# 5. Merge to developgit checkout developgit merge --no-ff release/v1.2.0
# 6. Push everythinggit push origin main develop --tags
# 7. Clean upgit branch -d release/v1.2.0Troubleshooting
Common Issues & Solutions π§
Problem: Committed to wrong branch
# Move commits to new branchgit branch new-branch # Create branch at current commitgit reset --hard HEAD~3 # Remove 3 commits from current branchgit checkout new-branch # Switch to new branch with commits
# Alternative: Cherry-pick approachgit checkout correct-branchgit cherry-pick abc123 def456 ghi789 # Pick commits from wrong branchgit checkout wrong-branchgit reset --hard HEAD~3 # Remove commits from wrong branchProblem: Need to edit commit history
# Interactive rebase (edit last 5 commits)git rebase -i HEAD~5# Change 'pick' to 'edit' for commits to modify# Make changes, then:git add .git commit --amendgit rebase --continueProblem: Pushed sensitive data
# Remove file from history (Git 2.23+)git filter-repo --path secrets.txt --invert-paths
# Or use filter-branch (older method)git filter-branch --tree-filter 'rm -f secrets.txt' HEADgit filter-branch --index-filter 'git rm --cached --ignore-unmatch secrets.txt' HEAD
# Force push (coordinate with team!)git push origin --force --allgit push origin --force --tags
# Better: Use BFG Repo-Cleaner (faster)bfg --delete-files secrets.txtgit reflog expire --expire=now --allgit gc --prune=now --aggressiveProblem: Detached HEAD state
# Create branch from detached HEADgit checkout -b new-branch
# Or return to previous branchgit checkout maingit checkout - # Switch to previous branch
# Find which branch you were ongit reflog | grep checkoutProblem: Large repository / performance issues
# Clean up unnecessary filesgit gc # Garbage collectiongit prune # Remove unreachable objects
# Aggressive cleanupgit gc --aggressive --prune=now
# Clean up refloggit reflog expire --expire=now --allgit gc --prune=now
# Find large files in historygit rev-list --objects --all | \ git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \ awk '/^blob/ {print substr($0,6)}' | \ sort --numeric-sort --key=2 | \ tail -10Problem: Merge conflict in binary file
# Use theirs versiongit checkout --theirs binary-file.pdfgit add binary-file.pdf
# Use ours versiongit checkout --ours binary-file.pdfgit add binary-file.pdf
# Or manually resolve and add# (download correct version, then:)git add binary-file.pdfProblem: Accidentally deleted branch
# Find commit hash from refloggit reflog | grep "branch-name"
# Recreate branchgit branch branch-name abc1234Useful Inspection Commands π
# View commit graphgit log --graph --oneline --all --decorate
# Find commit that introduced buggit bisect startgit bisect badgit bisect good abc123
# Search commits by messagegit log --all --grep="bug fix"
# Search commits by code contentgit log -S "function_name" --all
# Find who changed a line (blame)git blame filename.txtgit blame -L 10,20 filename.txt # Specific line range
# Show file history with renamesgit log --follow -- filename.txt
# Show branch relationshipsgit show-branch
# View reflog (recovery tool)git refloggit reflog show branch-name
# Find large filesgit rev-list --objects --all | \ git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \ awk '/^blob/ {print substr($0,6)}' | \ sort --numeric-sort --key=2 --reverse | head -10Best Practices
Doβs β
- β Write clear, descriptive commit messages following Conventional Commits
- β Commit often with logical, atomic changes
- β Push regularly to backup your work
- β Use branches for features, fixes, and experiments
- β
Review changes before committing (
git diff,git status) - β Pull before starting new work to stay updated
- β
Use
.gitignorefor build artifacts, dependencies, and IDE files - β
Tag releases with semantic versioning (e.g.,
v1.2.3) - β Keep commits focused on a single concern
- β Write meaningful commit messages (what and why, not just what)
- β
Use
--force-with-leaseinstead of--forcewhen force pushing - β Test before pushing to shared branches
- β Use pull requests for code review
- β Keep main/master branch stable and deployable
Donβts β
- β Commit large binary files (use Git LFS or external storage)
- β Force push to shared branches (rewrites history)
- β Commit credentials, secrets, or API keys
- β Make changes directly on main/master branch
- β Use
git add .without reviewing changes first - β Rewrite public/shared history (causes issues for others)
- β Ignore merge conflicts (resolve them properly)
- β Commit commented-out code or debug statements
- β Write vague commit messages like βfixβ or βupdateβ
- β Mix unrelated changes in a single commit
- β Commit generated files or dependencies
- β Skip testing before pushing
- β Delete branches others might be using
Common Pitfalls β οΈ
β οΈ Force Pushing: Never force push to shared branches. It rewrites history and can cause serious issues for other developers. If you must force push, use
--force-with-leasewhich fails if someone else has pushed commits.
β οΈ Hard Reset:
git reset --hardpermanently deletes uncommitted changes. Always commit or stash important work before using hard reset. Usegit reflogto recover from accidental resets.
β οΈ Rebasing Shared Branches: Never rebase commits that have been pushed to a shared branch. Rebasing rewrites commit history and will cause conflicts for anyone who has pulled those commits.
β οΈ Credentials in History: If you accidentally commit secrets, they remain in Git history even if deleted in later commits. Use
git filter-repoor BFG Repo-Cleaner to remove them, then force push (coordinate with your team first!).
Real-World Examples π
Example 1: Feature Development
# Start featuregit checkout -b feature/user-profile main# Make changes, commitgit commit -am "feat: add user profile page"# Keep updatedgit fetch origin && git rebase origin/main# Push for reviewgit push -u origin feature/user-profile# After PR merge, clean upgit checkout main && git pull && git branch -d feature/user-profileExample 2: Hotfix
# Emergency fixgit checkout -b hotfix/security-patch main# Fix and testgit commit -am "fix: patch security vulnerability"# Merge and taggit checkout maingit merge --no-ff hotfix/security-patchgit tag -a v1.0.1 -m "Security patch"git push origin main --tagsExample 3: Recovering Lost Work
# Accidentally deleted branchgit reflog | grep "deleted branch"# β abc1234 HEAD@{5}: checkout: moving from deleted-branch to maingit branch recovered-branch abc1234Quick Reference Tables
Git States
| State | Description | Command to reach |
|---|---|---|
| Working Directory | Modified files, not staged | edit file |
| Staging Area | Files ready to commit | git add |
| Local Repository | Committed changes | git commit |
| Remote Repository | Shared commits | git push |
Common Git Aliases
| Alias | Full Command | Purpose |
|---|---|---|
git st | git status | Check status |
git co | git checkout | Switch branches |
git br | git branch | List branches |
git ci | git commit | Commit changes |
git unstage | git reset HEAD -- | Unstage files |
git last | git log -1 HEAD | Show last commit |
git visual | git log --graph --oneline --all | Visual history |
Git vs GitHub/GitLab
| Git | GitHub/GitLab |
|---|---|
| Version control system | Web-based hosting service |
| Runs locally | Runs on remote servers |
| Command-line tool | Web interface + CLI |
| Core functionality | Additional features (PR, Issues, CI/CD) |
| Open source | Proprietary (GitHub) / Open source (GitLab) |
Commit Message Types
| Type | Use Case | Example |
|---|---|---|
feat | New feature | feat: add dark mode toggle |
fix | Bug fix | fix: resolve memory leak |
docs | Documentation | docs: update README |
style | Formatting | style: format with prettier |
refactor | Code refactoring | refactor: extract auth logic |
test | Tests | test: add unit tests |
chore | Maintenance | chore: update dependencies |
perf | Performance | perf: optimize queries |
ci | CI/CD | ci: add GitHub Actions |
Additional Resources π
- Official Git Documentation - Comprehensive reference
- Pro Git Book - Free online book covering all Git concepts
- GitHub Git Cheat Sheet - Quick reference PDF
- Oh My Git! - Interactive Git learning game
- Learn Git Branching - Visual Git tutorial and practice
- Git Flight Rules - Guide to common Git problems
- Conventional Commits - Commit message convention
Git Version: Commands in this cheatsheet are compatible with Git 2.23+. Some commands use newer syntax (e.g., git restore, git switch) introduced in Git 2.23. For older Git versions, use the alternative syntax provided in comments.