Question Mentor Logo Question Mentor
Practice With AI
Home » Directory » Cheat Sheets » Comprehensive Git Cheat Sheet

Comprehensive Git Cheat Sheet

Git Complete Cheat Sheet 2024-2025 | QuestionMentor

Git Complete Cheat Sheet

Master Version Control – Commands, Workflows & Best Practices

Updated November 2024 5000+ Words 15+ Sections 50+ Commands
QuestionMentor
What is Git?

Git is a distributed version control system created by Linus Torvalds in 2005. It’s the most widely used modern version control system in the world, powering millions of projects from small personal repositories to massive enterprise applications. Git tracks changes in source code during software development, enabling multiple developers to work together on non-linear development.

Unlike centralized version control systems, Git gives every developer a complete copy of the project history, making most operations extremely fast and allowing work to continue even when offline. This distributed nature makes Git incredibly powerful for collaboration, branching, and merging workflows.

Fast & Efficient

Lightning-fast operations with local repository access

Distributed

Every clone is a full backup of all data

Data Integrity

Cryptographic hashing ensures data authenticity

1. Installation & Setup

Installing Git

Windows Installation
  1. Download Git from git-scm.com
  2. Run the installer and follow the setup wizard
  3. Select “Git Bash Here” and “Git GUI Here” context menu options
  4. Choose default editor (VS Code, Vim, Notepad++, etc.)
  5. Select “Use Git from the command line and also from 3rd-party software”
  6. Verify installation:
git --version # Output: git version 2.43.0.windows.1
macOS Installation

Using Homebrew (Recommended):

# Install Homebrew first if not installed /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # Install Git brew install git # Verify installation git --version

Alternative: Xcode Command Line Tools

xcode-select --install
Linux Installation

Debian/Ubuntu:

sudo apt update sudo apt install git

Fedora/RHEL/CentOS:

sudo dnf install git # or for older versions sudo yum install git

Arch Linux:

sudo pacman -S git

Initial Configuration

After installation, configure your identity. This information is used in every commit:

# Set your name git config --global user.name "Your Name" # Set your email git config --global user.email "your.email@example.com" # Set default branch name to 'main' git config --global init.defaultBranch main # Set default editor git config --global core.editor "code --wait" # VS Code # git config --global core.editor "vim" # Vim # git config --global core.editor "nano" # Nano # Enable colored output git config --global color.ui auto # View all configurations git config --list # View specific configuration git config user.name
Pro Tip: Use –global for user-level settings, –local for repository-specific settings, or –system for system-wide settings.
2. Git Basics & Core Concepts

The Three States

Git has three main states that your files can be in:

Modified

You have changed the file but haven’t committed it yet to your database.

Staged

You have marked a modified file to go into your next commit snapshot.

Committed

The data is safely stored in your local database (repository).

The Three Areas

Area Description Purpose
Working Directory A single checkout of one version of the project Where you modify files
Staging Area (Index) A file storing information about what will go into your next commit Prepare commits selectively
Git Directory (Repository) Where Git stores metadata and object database Store project history

Key Terminology

Repository (Repo): A directory containing your project work, along with a .git directory that stores all the version control information.
Commit: A snapshot of your repository at a specific point in time, identified by a unique SHA-1 hash.
Branch: A lightweight movable pointer to a commit, allowing parallel development.
HEAD: A reference to the current branch or commit you’re working on.
Remote: A version of your repository hosted on the internet or network.
Clone: Creating a copy of a remote repository on your local machine.
Fork: Creating a personal copy of someone else’s repository on a hosting platform.
Pull Request (PR): A method of submitting contributions to a project.

Basic Workflow

# 1. Initialize a new repository git init # 2. Check status of your files git status # 3. Add files to staging area git add filename.txt git add . # Add all files # 4. Commit staged changes git commit -m "Descriptive commit message" # 5. View commit history git log # 6. Connect to remote repository git remote add origin https://github.com/username/repo.git # 7. Push changes to remote git push -u origin main
3. Essential Git Commands

Repository Creation & Cloning

# Initialize a new Git repository git init git init project-name # Creates directory and initializes # Clone an existing repository git clone https://github.com/username/repository.git git clone https://github.com/username/repository.git new-folder-name # Clone a specific branch git clone -b branch-name https://github.com/username/repository.git # Clone with depth (shallow clone - faster for large repos) git clone --depth 1 https://github.com/username/repository.git

File Status & Changes

# Check status of working directory git status git status -s # Short format git status -b # Show branch info # View differences git diff # Unstaged changes git diff --staged # Staged changes git diff HEAD # All changes since last commit git diff branch1..branch2 # Compare branches git diff commit1 commit2 # Compare commits # View file at specific commit git show commit-hash:path/to/file

Adding & Committing

# Add files to staging area git add filename.txt # Add specific file git add . # Add all files in current directory git add *.js # Add all JavaScript files git add -A # Add all changes (new, modified, deleted) git add -u # Add only modified and deleted files (not new) git add -p # Interactive staging (patch mode) # Remove files from staging area git reset HEAD filename.txt # Unstage specific file git reset HEAD . # Unstage all files # Commit changes git commit -m "Commit message" # Basic commit git commit -am "Message" # Add and commit tracked files git commit --amend -m "New message" # Modify last commit git commit --amend --no-edit # Amend without changing message git commit -m "Title" -m "Description" # Multi-line commit # Empty commit (useful for triggering CI/CD) git commit --allow-empty -m "Empty commit"
Commit Message Best Practices:
  • Use imperative mood: “Add feature” not “Added feature”
  • Keep first line under 50 characters
  • Separate subject from body with blank line
  • Explain what and why, not how
  • Reference issue numbers when applicable

Viewing History

# View commit history git log # Full log git log --oneline # Condensed view git log --graph --oneline --all # Visual branch graph git log -n 5 # Last 5 commits git log --since="2 weeks ago" # Time-based git log --author="John Doe" # By author git log --grep="bug fix" # Search commit messages git log -- filename.txt # History of specific file git log -p # Show patches (changes) git log --stat # Show statistics # Beautiful log format git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit # Show commits unique to branch git log main..feature-branch # Show who changed what git blame filename.txt git blame -L 10,20 filename.txt # Specific lines

Undoing Changes

# Discard changes in working directory git checkout -- filename.txt # Restore single file git checkout -- . # Restore all files git restore filename.txt # Newer syntax (Git 2.23+) git restore . # Restore all # Unstage files git reset HEAD filename.txt # Remove from staging git restore --staged filename.txt # Newer syntax # Undo commits git reset --soft HEAD~1 # Undo last commit, keep changes staged git reset --mixed HEAD~1 # Undo last commit, unstage changes git reset --hard HEAD~1 # Undo last commit, discard changes git reset --hard commit-hash # Reset to specific commit # Revert a commit (creates new commit) git revert commit-hash # Safe for public branches git revert HEAD # Revert last commit git revert HEAD~3..HEAD # Revert range of commits
Warning: git reset –hard permanently deletes uncommitted changes. Use git reflog if you need to recover lost commits.

File Management

# Remove files git rm filename.txt # Delete and stage removal git rm --cached filename.txt # Remove from Git, keep locally git rm -r directory/ # Remove directory recursively # Move/Rename files git mv old-name.txt new-name.txt # Rename file git mv file.txt directory/ # Move file # Ignore files (.gitignore) # Create .gitignore file with patterns: *.log # Ignore all .log files node_modules/ # Ignore directory !important.log # Exception (don't ignore) build/**/*.js # Nested patterns # Ignore already tracked files git rm --cached filename.txt # Then add to .gitignore
4. Branching & Merging

Understanding Branches

Branches are one of Git’s most powerful features. They allow you to diverge from the main line of development and work independently without affecting the main codebase. Branches are lightweight pointers to commits, making them fast to create and switch between.

Branch Operations

# List branches git branch # Local branches git branch -r # Remote branches git branch -a # All branches git branch -v # Show last commit on each branch git branch --merged # Branches merged into current git branch --no-merged # Branches not merged # Create branches git branch feature-name # Create branch git checkout -b feature-name # Create and switch git switch -c feature-name # Newer syntax (Git 2.23+) # Create branch from specific commit git branch branch-name commit-hash # Switch branches git checkout branch-name # Classic syntax git switch branch-name # Newer syntax git checkout - # Switch to previous branch # Rename branches git branch -m old-name new-name # Rename any branch git branch -m new-name # Rename current branch # Delete branches git branch -d branch-name # Delete (safe - checks if merged) git branch -D branch-name # Force delete git push origin --delete branch-name # Delete remote branch

Merging Strategies

# Basic merge git checkout main git merge feature-branch # Merge feature into main # Merge with no fast-forward (creates merge commit) git merge --no-ff feature-branch # Fast-forward merge only git merge --ff-only feature-branch # Squash merge (combine all commits into one) git merge --squash feature-branch git commit -m "Squashed feature commits" # Abort merge during conflict git merge --abort # Continue merge after resolving conflicts git merge --continue

Handling Merge Conflicts

Merge conflicts occur when Git can’t automatically resolve differences between branches. Here’s how to handle them:

# When conflict occurs, check status git status # View conflicted files git diff --name-only --diff-filter=U # Conflict markers in file: # <<<<<<< HEAD # Current branch content # ======= # Incoming branch content # >>>>>>> feature-branch # After manually resolving conflicts: git add resolved-file.txt git commit -m "Resolve merge conflicts" # Use merge tools git mergetool # Launch configured merge tool # Choose a version git checkout --ours filename.txt # Keep current branch version git checkout --theirs filename.txt # Take incoming branch version # View conflict resolution log git log --merge --left-right
Pro Tip: Configure a visual merge tool like VS Code, Meld, or KDiff3 for easier conflict resolution:
git config --global merge.tool vscode git config --global mergetool.vscode.cmd 'code --wait $MERGED'

Cherry-Pick

Apply specific commits from one branch to another:

# Cherry-pick single commit git cherry-pick commit-hash # Cherry-pick multiple commits git cherry-pick commit1 commit2 commit3 # Cherry-pick range of commits git cherry-pick commit1^..commit2 # Cherry-pick without committing git cherry-pick -n commit-hash # Continue after resolving conflicts git cherry-pick --continue # Abort cherry-pick git cherry-pick --abort
5. Branching Strategies & Workflows
Git Flow

Git Flow is a branching model that uses multiple long-lived branches and specific naming conventions:

  • main/master: Production-ready code
  • develop: Integration branch for features
  • feature/*: New features (branch from develop)
  • release/*: Release preparation (branch from develop)
  • hotfix/*: Emergency fixes (branch from main)
# Feature workflow git checkout develop git checkout -b feature/user-authentication # ... work on feature ... git checkout develop git merge --no-ff feature/user-authentication git branch -d feature/user-authentication # Release workflow git checkout -b release/1.0.0 develop # ... bug fixes, version bump ... git checkout main git merge --no-ff release/1.0.0 git tag -a v1.0.0 git checkout develop git merge --no-ff release/1.0.0 git branch -d release/1.0.0 # Hotfix workflow git checkout -b hotfix/critical-bug main # ... fix bug ... git checkout main git merge --no-ff hotfix/critical-bug git tag -a v1.0.1 git checkout develop git merge --no-ff hotfix/critical-bug git branch -d hotfix/critical-bug
GitHub Flow

A simpler alternative to Git Flow, ideal for continuous deployment:

  • Single main branch (usually ‘main’)
  • Feature branches created from main
  • Pull requests for code review
  • Merge to main and deploy immediately
# GitHub Flow workflow git checkout main git pull origin main git checkout -b feature/add-payment-method # ... work on feature ... git push -u origin feature/add-payment-method # Create Pull Request on GitHub # After approval and CI passes: # Merge via GitHub interface git checkout main git pull origin main git branch -d feature/add-payment-method
GitLab Flow

Combines Git Flow and GitHub Flow with environment branches:

  • main: Latest deployed to production
  • pre-production: Staging environment
  • production: Production environment (optional)

Features are merged into main, then promoted through environments.

Trunk-Based Development

Developers work in short-lived branches or directly on trunk/main:

  • Very short-lived feature branches (hours or days)
  • Frequent integration to main
  • Feature flags for incomplete features
  • Strong CI/CD pipeline required
# Trunk-based workflow git checkout main git pull git checkout -b quick-feature # ... make small changes ... git push -u origin quick-feature # Quick review and merge git checkout main git pull git branch -d quick-feature
Choosing a Strategy:
  • Git Flow: Large projects with scheduled releases
  • GitHub Flow: Continuous deployment, web applications
  • GitLab Flow: Multiple deployment environments
  • Trunk-Based: Mature teams, strong CI/CD, rapid deployment
6. Advanced Git Operations

Rebase

Rebasing is an alternative to merging that rewrites commit history by moving commits to a new base. It creates a linear history but should be used carefully on shared branches.

# Basic rebase git checkout feature-branch git rebase main # Rebase feature onto main # Interactive rebase (rewrite history) git rebase -i HEAD~5 # Last 5 commits git rebase -i commit-hash # From specific commit # Interactive rebase commands: # pick = use commit # reword = use commit, but edit message # edit = use commit, but stop for amending # squash = combine with previous commit # fixup = like squash, but discard commit message # drop = remove commit # Continue rebase after resolving conflicts git rebase --continue # Skip problematic commit git rebase --skip # Abort rebase git rebase --abort # Rebase onto different branch git rebase --onto new-base old-base feature-branch
Golden Rule of Rebasing: Never rebase commits that have been pushed to a public/shared repository. Only rebase local, unpushed commits.

Rebase vs Merge

Aspect Merge Rebase
History Preserves complete history Creates linear history
Commits Creates merge commit Rewrites commit history
Safety Non-destructive Can lose commits if misused
Use Case Public branches, collaboration Local cleanup, feature branches
Traceability Shows when branches merged Loses merge context

Squashing Commits

# Squash last 3 commits into one git rebase -i HEAD~3 # In editor, change 'pick' to 'squash' for commits to combine # Alternative: reset and recommit git reset --soft HEAD~3 git commit -m "Combined commit message" # Squash during merge git merge --squash feature-branch git commit -m "Feature: Add user authentication" # Squash all commits from branch git checkout main git merge --squash feature-branch git commit

Bisect (Binary Search for Bugs)

Use bisect to find which commit introduced a bug:

# Start bisect git bisect start git bisect bad # Current commit is bad git bisect good v1.0 # Known good commit # Git checks out middle commit, you test: git bisect good # If current commit is good git bisect bad # If current commit is bad # Repeat until bug is found # Git will tell you the first bad commit # Reset after bisect git bisect reset # Automated bisect with script git bisect start HEAD v1.0 git bisect run npm test # Run tests automatically

Submodules

Include external Git repositories as subdirectories:

# Add submodule git submodule add https://github.com/user/repo.git path/to/submodule # Clone repository with submodules git clone --recursive https://github.com/user/repo.git # Initialize submodules in existing clone git submodule init git submodule update # Update submodules git submodule update --remote # Update all submodules git submodule foreach git pull origin main # Remove submodule git submodule deinit path/to/submodule git rm path/to/submodule rm -rf .git/modules/path/to/submodule

Git Tags

# Lightweight tags git tag v1.0.0 git tag v1.0.0 commit-hash # Annotated tags (recommended) git tag -a v1.0.0 -m "Release version 1.0.0" git tag -a v1.0.0 commit-hash -m "Tag message" # List tags git tag git tag -l "v1.*" # Pattern matching # Show tag information git show v1.0.0 # Push tags to remote git push origin v1.0.0 # Single tag git push origin --tags # All tags # Delete tags git tag -d v1.0.0 # Local git push origin --delete v1.0.0 # Remote # Checkout tag git checkout v1.0.0 # Detached HEAD state git checkout -b branch-name v1.0.0 # Create branch from tag
7. Git Stash & Reflog

Git Stash

Stash allows you to temporarily save uncommitted changes and revert to a clean working directory. Perfect for switching contexts quickly.

# Stash changes git stash # Stash modified tracked files git stash save "Work in progress" # Stash with message git stash -u # Include untracked files git stash -a # Include ignored files too # List stashes git stash list # Output: # stash@{0}: On main: Work in progress # stash@{1}: WIP on feature: 1234567 Fix bug # View stash contents git stash show # Summary of latest stash git stash show -p # Full diff git stash show stash@{1} # Specific stash # Apply stashes git stash apply # Apply latest, keep in stash git stash apply stash@{1} # Apply specific stash git stash pop # Apply and remove from stash git stash pop stash@{1} # Pop specific stash # Create branch from stash git stash branch new-branch-name # Remove stashes git stash drop stash@{1} # Remove specific git stash clear # Remove all stashes # Stash specific files git stash push -m "Message" file1.txt file2.txt # Stash interactively git stash -p # Choose hunks to stash
Pro Tip: Use stash when you need to quickly switch branches but aren’t ready to commit:
git stash git checkout other-branch # ... do work ... git checkout original-branch git stash pop

Git Reflog

Reflog records all changes to HEAD, allowing you to recover lost commits, reset branches, and undo mistakes. It’s your safety net!

# View reflog git reflog git reflog show # Same as above git reflog show branch-name # Reflog for specific branch # Output format: # a1b2c3d HEAD@{0}: commit: Add feature # e4f5g6h HEAD@{1}: checkout: moving from main to feature # i7j8k9l HEAD@{2}: commit: Fix bug # Recover lost commits git reflog git checkout HEAD@{2} # Go to specific state git cherry-pick a1b2c3d # Recover specific commit # Undo reset git reset --hard HEAD@{1} # Go back one step # Restore deleted branch git reflog git checkout -b recovered-branch HEAD@{5} # Find when file was deleted git log --all --full-history -- path/to/file git reflog -- path/to/file # Reflog for all references git reflog show --all # Expire reflog entries git reflog expire --expire=30.days.ago --all # Clean up old reflog entries git reflog delete HEAD@{5}
Reflog Retention: Reflog entries are kept for 90 days by default. Unreachable commits are kept for 30 days. After that, they may be garbage collected.

Recovery Scenarios

Recover from Hard Reset
# You accidentally did: git reset --hard HEAD~3 # To recover: git reflog # Find the commit before reset (e.g., HEAD@{1}) git reset --hard HEAD@{1} # Or use the commit hash git reset --hard a1b2c3d
Recover Deleted Branch
# You accidentally deleted a branch: git branch -D feature-branch # To recover: git reflog # Find the last commit on that branch # Look for: "checkout: moving from feature-branch to main" git checkout -b feature-branch HEAD@{X} # Or git branch feature-branch commit-hash
Recover Lost Commits
# Find lost commits git fsck --lost-found git reflog --all # View dangling commits git show commit-hash # Recover specific commit git cherry-pick commit-hash # Or create branch from it git branch recovered commit-hash
8. Remote Repositories

Working with Remotes

Remote repositories are versions of your project hosted on the internet or network. They enable collaboration and backup.

# View remotes git remote # List remote names git remote -v # Show URLs git remote show origin # Detailed info # Add remote git remote add origin https://github.com/user/repo.git git remote add upstream https://github.com/original/repo.git # Change remote URL git remote set-url origin https://github.com/user/new-repo.git # Rename remote git remote rename origin destination # Remove remote git remote remove origin # Prune deleted remote branches git remote prune origin git fetch --prune

Fetching & Pulling

# Fetch (download without merging) git fetch # Fetch all remotes git fetch origin # Fetch specific remote git fetch origin branch-name # Fetch specific branch git fetch --all # Fetch all remotes git fetch --prune # Remove deleted remote branches # Pull (fetch + merge) git pull # Pull current branch git pull origin main # Pull specific branch git pull --rebase # Pull and rebase instead of merge git pull --no-commit # Fetch and merge without committing git pull --all # Pull all branches # Pull with specific strategy git pull --ff-only # Fast-forward only git pull --no-ff # Always create merge commit # Set upstream branch git branch --set-upstream-to=origin/main main # Or shorter: git branch -u origin/main

Pushing

# Basic push git push # Push current branch git push origin main # Push to specific branch git push -u origin feature-branch # Set upstream and push # Push all branches git push --all origin # Push tags git push origin v1.0.0 # Specific tag git push --tags # All tags git push --follow-tags # Push tags with commits # Force push (dangerous!) git push --force # Overwrite remote git push --force-with-lease # Safer force push # Delete remote branch git push origin --delete branch-name git push origin :branch-name # Alternative syntax # Push to multiple remotes git remote set-url --add --push origin https://github.com/user/repo1.git git remote set-url --add --push origin https://github.com/user/repo2.git git push origin main # Pushes to both
Force Push Warning: Use git push –force-with-lease instead of –force. It checks that no one else has pushed changes before overwriting.

Tracking Branches

# Create tracking branch git checkout -b feature origin/feature git checkout --track origin/feature # Automatically names branch # Set upstream for existing branch git branch -u origin/main # View tracking branches git branch -vv # Push and set upstream git push -u origin feature-branch # Unset upstream git branch --unset-upstream

Working with Forks

# Clone your fork git clone https://github.com/your-username/repo.git cd repo # Add upstream remote (original repository) git remote add upstream https://github.com/original-owner/repo.git # Verify remotes git 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-owner/repo.git (fetch) # upstream https://github.com/original-owner/repo.git (push) # Sync with upstream git fetch upstream git checkout main git merge upstream/main # Or rebase: git rebase upstream/main # Push updates to your fork git push origin main # Create feature branch for contribution git checkout -b feature/new-feature # ... make changes ... git push -u origin feature/new-feature # Create Pull Request on GitHub/GitLab

SSH vs HTTPS

Aspect HTTPS SSH
URL Format https://github.com/user/repo.git git@github.com:user/repo.git
Authentication Username + Personal Access Token SSH Key
Setup Easier (no key generation) Requires SSH key setup
Firewall Works through most firewalls May be blocked (port 22)
Security Secure with token More secure, no passwords
# Switch from HTTPS to SSH git remote set-url origin git@github.com:username/repo.git # Switch from SSH to HTTPS git remote set-url origin https://github.com/username/repo.git # Generate SSH key ssh-keygen -t ed25519 -C "your_email@example.com" # Add to ssh-agent eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519 # Copy public key and add to GitHub/GitLab cat ~/.ssh/id_ed25519.pub
9. Collaboration Workflows

Pull Request Workflow

Pull Requests (GitHub) or Merge Requests (GitLab) are the primary way to propose and review changes:

# 1. Create feature branch git checkout -b feature/add-user-profile # 2. Make changes and commit git add . git commit -m "Add user profile page with avatar upload" # 3. Push to remote git push -u origin feature/add-user-profile # 4. Create Pull Request on GitHub/GitLab # Via web interface or CLI: gh pr create --title "Add user profile page" --body "Description" # 5. Address review feedback # Make changes based on reviews git add . git commit -m "Address review feedback: improve validation" git push # 6. After approval, merge (via web interface) # Or from command line: git checkout main git merge --no-ff feature/add-user-profile git push origin main # 7. Clean up git branch -d feature/add-user-profile git push origin --delete feature/add-user-profile

Code Review Best Practices

For Authors

  • Keep PRs small and focused
  • Write clear descriptions
  • Add tests for new features
  • Self-review before requesting
  • Respond to feedback promptly

For Reviewers

  • Be constructive and kind
  • Focus on important issues
  • Explain your reasoning
  • Approve if good enough
  • Test the changes locally

Reviewing Pull Requests

# Fetch PR locally for testing git fetch origin pull/123/head:pr-123 git checkout pr-123 # Or add PR refs to config git config --add remote.origin.fetch "+refs/pull/*/head:refs/remotes/origin/pr/*" git fetch origin git checkout origin/pr/123 # Test the changes npm test # or your test command # View changes git diff main...pr-123 # Check out PR with GitHub CLI gh pr checkout 123 # Leave review comments gh pr review 123 --comment -b "Looks good!" gh pr review 123 --approve gh pr review 123 --request-changes -b "Please fix X"

Resolving Conflicts in PRs

# Method 1: Merge main into feature branch git checkout feature-branch git fetch origin git merge origin/main # Resolve conflicts git add . git commit git push # Method 2: Rebase on main (cleaner history) git checkout feature-branch git fetch origin git rebase origin/main # Resolve conflicts git add . git rebase --continue git push --force-with-lease # Update branch from web interface (GitHub/GitLab) # Click "Update branch" button on PR page

Pair Programming with Git

# Co-authored commits git commit -m "Implement feature X Co-authored-by: Jane Doe Co-authored-by: John Smith " # Share work in progress git add . git commit -m "WIP: Feature in progress" git push origin feature-branch # Continue work on different machine git pull origin feature-branch # Make changes git commit --amend # Amend WIP commit git push --force-with-lease
10. Git Hooks & Automation

What are Git Hooks?

Git hooks are scripts that run automatically at certain points in the Git workflow. They’re stored in the .git/hooks directory and can enforce policies, run tests, or automate tasks.

Client-Side Hooks

Hook When It Runs Common Uses
pre-commit Before commit is created Linting, formatting, tests
prepare-commit-msg Before commit message editor Auto-generate commit messages
commit-msg After commit message entered Validate commit message format
post-commit After commit is created Notifications, logging
pre-push Before pushing to remote Run full test suite
pre-rebase Before rebasing Prevent rebasing published commits

Creating a Pre-Commit Hook

# Create pre-commit hook # File: .git/hooks/pre-commit #!/bin/bash # Run linter echo "Running ESLint..." npm run lint if [ $? -ne 0 ]; then echo "❌ Linting failed. Please fix errors before committing." exit 1 fi # Run tests echo "Running tests..." npm test if [ $? -ne 0 ]; then echo "❌ Tests failed. Please fix before committing." exit 1 fi echo "✅ All checks passed!" exit 0
# Make hook executable chmod +x .git/hooks/pre-commit # Skip hooks temporarily git commit --no-verify -m "Emergency fix" git commit -n -m "Skip hooks"

Commit Message Hook

# File: .git/hooks/commit-msg #!/bin/bash commit_msg_file=$1 commit_msg=$(cat "$commit_msg_file") # Check message format: TYPE: message pattern="^(feat|fix|docs|style|refactor|test|chore): .+" if ! echo "$commit_msg" | grep -qE "$pattern"; then echo "❌ Invalid commit message format!" echo "Format: TYPE: message" echo "Types: feat, fix, docs, style, refactor, test, chore" echo "Example: feat: Add user authentication" exit 1 fi # Check message length if [ ${#commit_msg} -lt 10 ]; then echo "❌ Commit message too short (minimum 10 characters)" exit 1 fi echo "✅ Commit message validated" exit 0

Husky makes Git hooks easy to share across teams:

# Install Husky npm install --save-dev husky npx husky install # Add to package.json npm set-script prepare "husky install" # Create pre-commit hook npx husky add .husky/pre-commit "npm test" npx husky add .husky/pre-commit "npm run lint" # Create commit-msg hook npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"' # Install commitlint npm install --save-dev @commitlint/cli @commitlint/config-conventional # Create commitlint.config.js echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js

Server-Side Hooks

Hook When It Runs Common Uses
pre-receive Before accepting push Enforce policies, run CI/CD
update Once per branch being pushed Branch-specific policies
post-receive After push is accepted Deploy, notifications, backups
Pro Tip: Use tools like Husky, lint-staged, and commitlint for a complete pre-commit workflow that’s easy to share across your team.
11. Security & Commit Signing

GPG Commit Signing

Signing commits with GPG proves that commits actually came from you. GitHub and GitLab show a “Verified” badge for signed commits.

# Generate GPG key gpg --full-generate-key # Choose: RSA and RSA, 4096 bits, no expiration # List GPG keys gpg --list-secret-keys --keyid-format=long # Output: # sec rsa4096/3AA5C34371567BD2 2024-01-15 [SC] # The key ID is: 3AA5C34371567BD2 # Export public key gpg --armor --export 3AA5C34371567BD2 # Copy output and add to GitHub/GitLab # Configure Git to use GPG git config --global user.signingkey 3AA5C34371567BD2 git config --global commit.gpgsign true git config --global tag.gpgsign true # Sign individual commit git commit -S -m "Signed commit" # Sign tags git tag -s v1.0.0 -m "Signed tag" # Verify signatures git log --show-signature git verify-commit HEAD git verify-tag v1.0.0

SSH Commit Signing (Newer Method)

# Use existing SSH key or generate new one ssh-keygen -t ed25519 -C "your_email@example.com" # Configure Git to use SSH signing git config --global gpg.format ssh git config --global user.signingkey ~/.ssh/id_ed25519.pub git config --global commit.gpgsign true # Add allowed signers file git config --global gpg.ssh.allowedSignersFile ~/.config/git/allowed_signers # Create allowed signers file echo "your_email@example.com $(cat ~/.ssh/id_ed25519.pub)" > ~/.config/git/allowed_signers # Sign commit git commit -S -m "SSH signed commit"

Security Best Practices

Protect Sensitive Data

  • Never commit passwords or API keys
  • Use .gitignore for secrets
  • Use environment variables
  • Scan for secrets with tools
  • Use git-crypt for encryption

Account Security

  • Enable 2FA on GitHub/GitLab
  • Use SSH keys instead of passwords
  • Use Personal Access Tokens
  • Sign commits with GPG/SSH
  • Regularly audit access

Removing Sensitive Data from History

# Using BFG Repo-Cleaner (Recommended - Faster) # Download from: https://rtyley.github.io/bfg-repo-cleaner/ # Remove passwords/secrets from all history bfg --replace-text passwords.txt repo.git # Remove large files bfg --strip-blobs-bigger-than 50M repo.git # Delete specific files bfg --delete-files id_rsa repo.git # Clean up cd repo.git git reflog expire --expire=now --all git gc --prune=now --aggressive # Force push (careful!) git push --force # Using git filter-branch (Manual method) git filter-branch --force --index-filter \ "git rm --cached --ignore-unmatch path/to/secret-file" \ --prune-empty --tag-name-filter cat -- --all # Alternative: git filter-repo (Modern tool) pip install git-filter-repo # Remove file from history git filter-repo --path path/to/secret-file --invert-paths # Remove all files matching pattern git filter-repo --path-glob '*.key' --invert-paths
Critical Warning: After removing sensitive data, consider it compromised. Rotate all secrets, API keys, and passwords immediately. History rewriting requires force push and coordination with team.

Git Security Tools

# git-secrets (Prevent committing secrets) git clone https://github.com/awslabs/git-secrets cd git-secrets make install # Install hooks in repository git secrets --install git secrets --register-aws # Scan repository git secrets --scan git secrets --scan-history # gitleaks (Find secrets in repo) # Install: https://github.com/gitleaks/gitleaks gitleaks detect --source . --verbose gitleaks protect --staged # TruffleHog (Find secrets in history) pip install truffleHog trufflehog --regex --entropy=True https://github.com/user/repo.git # Pre-commit hook with multiple tools # .pre-commit-config.yaml repos: - repo: https://github.com/gitleaks/gitleaks rev: v8.18.0 hooks: - id: gitleaks

Credential Management

# Configure credential helper (Linux) git config --global credential.helper cache git config --global credential.helper 'cache --timeout=3600' # macOS (Keychain) git config --global credential.helper osxkeychain # Windows (Windows Credential Manager) git config --global credential.helper wincred # Or with Git Credential Manager git config --global credential.helper manager # Store credentials (NOT RECOMMENDED for production) git config --global credential.helper store # Use Personal Access Token (GitHub) # Generate: GitHub Settings → Developer Settings → Personal Access Tokens # Use token as password when prompted # SSH Key for authentication (Recommended) ssh-keygen -t ed25519 -C "your_email@example.com" eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519 # Add public key to GitHub/GitLab # Test SSH connection ssh -T git@github.com
12. Git Best Practices

Commit Best Practices

Make atomic commits: Each commit should represent a single logical change. If you can’t describe it in one sentence, it’s too big.
Write meaningful messages: Use imperative mood (“Add feature” not “Added feature”). Explain what and why, not how.
Commit often: Commit complete work frequently rather than waiting for large changes. Makes debugging and reverting easier.
Don’t commit half-done work: Use stash for work-in-progress. Commits should leave the codebase in a working state.
Test before committing: Run tests and linting before committing. Use pre-commit hooks to automate this.
Use .gitignore properly: Ignore build artifacts, dependencies, IDE files, and OS-specific files.

Commit Message Convention

# Conventional Commits Format type(scope): subject body (optional) footer (optional) # Types: feat: New feature fix: Bug fix docs: Documentation changes style: Code style (formatting, semicolons, etc.) refactor: Code refactoring (no feature/fix) perf: Performance improvements test: Adding or updating tests chore: Maintenance tasks, dependencies ci: CI/CD changes build: Build system changes # Examples: feat(auth): add OAuth2 authentication fix(api): resolve race condition in user creation Closes #123 docs: update installation guide for Windows refactor(database): optimize query performance test(auth): add unit tests for login flow chore(deps): update dependencies to latest versions BREAKING CHANGE: authentication now requires OAuth2

Branching Best Practices

Use descriptive branch names: feature/user-authentication, bugfix/login-error, hotfix/security-patch
Keep branches short-lived: Merge branches within days, not weeks. Long-lived branches accumulate conflicts.
Update from main regularly: Frequently merge or rebase from main to stay current and minimize conflicts.
Delete merged branches: Clean up branches after merging to keep repository organized.
Protect main branch: Require pull requests and reviews before merging to main.

Repository Best Practices

Repository Structure

  • Include comprehensive README.md
  • Add LICENSE file
  • Create CONTRIBUTING.md
  • Use .gitignore templates
  • Document in CODE_OF_CONDUCT.md

Configuration

  • Set up CI/CD pipelines
  • Configure branch protection
  • Enable required reviews
  • Use issue templates
  • Set up automated testing

Performance Best Practices

# Keep repository size manageable # Avoid committing large binary files # Use Git LFS for large files git lfs install git lfs track "*.psd" git lfs track "*.mp4" git add .gitattributes # Shallow clone for faster downloads git clone --depth 1 https://github.com/user/repo.git # Partial clone (Git 2.22+) git clone --filter=blob:none https://github.com/user/repo.git # Clean up repository git gc --aggressive --prune=now git repack -a -d --depth=250 --window=250 # Remove unused objects git prune git prune-packed # Check repository size git count-objects -vH

Common Anti-Patterns to Avoid

What NOT to Do:
  • Committing generated files (node_modules, build/, *.pyc)
  • Using vague commit messages (“fix”, “update”, “changes”)
  • Making massive commits with unrelated changes
  • Force pushing to shared branches
  • Committing directly to main/production
  • Leaving TODO or debug code in commits
  • Rebasing public/shared branches
  • Ignoring merge conflicts (accepting without review)
  • Not pulling before pushing
  • Committing sensitive data (passwords, keys)

Git Aliases for Productivity

# Add useful Git aliases git config --global alias.co checkout git config --global alias.br branch git config --global alias.ci commit git config --global alias.st status git config --global alias.unstage 'reset HEAD --' git config --global alias.last 'log -1 HEAD' git config --global alias.visual 'log --graph --oneline --all' git config --global alias.aliases 'config --get-regexp alias' # Beautiful log git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit" # Show branches sorted by last commit git config --global alias.recent 'branch --sort=-committerdate' # Amend without editing message git config --global alias.amend 'commit --amend --no-edit' # Undo last commit but keep changes git config --global alias.undo 'reset HEAD~1 --soft' # Show file changes git config --global alias.changed 'diff --name-only'
13. Troubleshooting Common Issues

Common Problems & Solutions

“Detached HEAD” State

Problem: You checked out a commit directly and now you’re in “detached HEAD” state.

# If you want to keep your changes git checkout -b new-branch-name # If you want to discard changes git checkout main # If you made commits in detached state git branch temp-branch git checkout main git merge temp-branch
Rejected Push (Non-Fast-Forward)

Problem: Push rejected because remote has changes you don’t have locally.

# Pull and merge git pull origin main git push origin main # Or pull with rebase (cleaner history) git pull --rebase origin main git push origin main # If you're sure your changes should override (careful!) git push --force-with-lease origin main
Accidentally Committed to Wrong Branch
# Move commit to new branch git branch feature-branch git reset --hard HEAD~1 git checkout feature-branch # Or move to existing branch git checkout existing-branch git cherry-pick main git checkout main git reset --hard HEAD~1
Undo Last Commit
# Keep changes, undo commit git reset --soft HEAD~1 # Undo commit and staging git reset HEAD~1 # Undo commit and discard changes (dangerous!) git reset --hard HEAD~1 # If already pushed (creates new commit) git revert HEAD
Fix Commit Message
# Fix last commit message git commit --amend -m "New commit message" # Fix older commit message git rebase -i HEAD~3 # Change 'pick' to 'reword' for commits to edit # Save and edit messages in following screens # If already pushed (not recommended for shared branches) git push --force-with-lease
Remove File from Last Commit
# Remove file from last commit git reset HEAD~1 filename.txt git commit --amend --no-edit # Or alternative method git rm --cached filename.txt git commit --amend --no-edit
Resolve “Fatal: Not a git repository”

Problem: Git commands fail because you’re not in a Git repository.

# Check if you're in a Git repo git status # Navigate to repository root cd /path/to/your/repository # If no .git folder exists, initialize git init # If .git was accidentally deleted # You'll need to re-clone or restore from backup
Fix “Permission Denied (publickey)”
# Test SSH connection ssh -T git@github.com # Generate new SSH key ssh-keygen -t ed25519 -C "your_email@example.com" # Start ssh-agent eval "$(ssh-agent -s)" # Add SSH key ssh-add ~/.ssh/id_ed25519 # Copy public key to clipboard (macOS) pbcopy < ~/.ssh/id_ed25519.pub # Copy public key to clipboard (Linux) xclip -selection clipboard < ~/.ssh/id_ed25519.pub # Add key to GitHub/GitLab settings # Then test again ssh -T git@github.com

Merge Conflict Resolution Tips

Conflict Resolution Strategies:
  • Understand both versions before choosing
  • Test the code after resolving conflicts
  • Communicate with teammate if unsure
  • Use visual merge tools for complex conflicts
  • Consider keeping both changes when applicable
  • Document resolution decisions in commit message

Performance Issues

# Check repository health git fsck # Optimize repository git gc --aggressive # Clean up unnecessary files git clean -fd # Remove untracked files (preview first) git clean -n git clean -f # Clear Git cache git rm -r --cached . git add . # Fix slow git status git config --global core.preloadindex true git config --global core.fscache true git config --global gc.auto 256
14. Advanced Tips & Tricks

Powerful Git Commands

# Find which commit introduced a bug git bisect start git bisect bad HEAD git bisect good v1.0 # Test each commit git provides git bisect good/bad # Automate with script git bisect run npm test # Search commit messages git log --grep="bug fix" git log --grep="feature" --author="John" # Find when a string was introduced git log -S "function_name" --source --all # Show commits that changed specific function git log -L :function_name:file.js # Find who deleted a file git log --full-history -- path/to/file # Show commits unique to current branch git log main..feature-branch # Compare branches git diff main...feature-branch # Show changes in stash git stash show -p stash@{0} # Create patch file git format-patch -1 HEAD git format-patch main..feature-branch # Apply patch git apply patch-file.patch git am patch-file.patch

Time-Saving Shortcuts

# Quick commit all changes git commit -am "Message" # Stage and commit specific files git commit file1.txt file2.txt -m "Message" # Push current branch git push origin HEAD # Create and switch to branch in one command git checkout -b feature-name # Switch to previous branch git checkout - # Discard all changes git checkout . git restore . # Update all submodules git submodule update --init --recursive # Clone specific branch git clone -b branch-name --single-branch url # Reuse recorded conflict resolutions git config --global rerere.enabled true # Auto-correct mistyped commands git config --global help.autocorrect 20

Git Configuration Tips

# Edit global config git config --global --edit # Use different config per project git config user.name "Work Name" git config user.email "work@email.com" # Set default pull behavior git config --global pull.rebase false # merge (default) git config --global pull.rebase true # rebase git config --global pull.ff only # fast-forward only # Set default push behavior git config --global push.default simple # Enable auto-stash during rebase git config --global rebase.autoStash true # Show original branch name after rebase git config --global rebase.abbreviateCommands false # Auto-prune on fetch git config --global fetch.prune true # Use meld as diff tool git config --global diff.tool meld git config --global difftool.prompt false # Better diff algorithm git config --global diff.algorithm histogram # Show moved code differently git config --global diff.colorMoved zebra

Productivity Workflows

Efficient Daily Workflow:
# Morning routine git checkout main git pull --prune git branch -vv # Check branches # Start new work git checkout -b feature/new-work # During work git add -p # Review changes interactively git commit -m "feat: add feature" git push -u origin HEAD # Before lunch/end of day git add . git stash save "WIP: working on feature" # Resume work git stash pop # Keep feature branch updated git fetch origin git rebase origin/main # Cleanup merged branches git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

Advanced Search & Inspection

# Search for string in all branches git grep "search_term" $(git rev-list --all) # Find large files in repository git rev-list --objects --all | \ git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \ sed -n 's/^blob //p' | \ sort --numeric-sort --key=2 | \ tail -n 10 # List files in specific commit git ls-tree -r commit-hash --name-only # Show file content at specific commit git show commit-hash:path/to/file # Find commits that touch a file git log --follow -- path/to/file # Show commits between dates git log --since="2024-01-01" --until="2024-12-31" # Show commits by author git shortlog -sn --all --no-merges # Statistics about repository git log --shortstat --author="Your Name" | \ grep -E "fil(e|es) changed" | \ awk '{files+=$1; inserted+=$4; deleted+=$6} END \ {print "files changed:", files, "lines inserted:", inserted, "lines deleted:", deleted}' # Find commits that modified a specific line git log -L 15,20:path/to/file.js # Show all files changed between commits git diff --name-only commit1 commit2

Interactive Staging

# Interactive add (patch mode) git add -p # Commands in patch mode: # y - stage this hunk # n - do not stage this hunk # q - quit; do not stage this or remaining hunks # a - stage this and all remaining hunks in the file # d - do not stage this or remaining hunks in the file # s - split hunk into smaller hunks # e - manually edit the hunk # Interactive mode for all operations git add -i # Stage parts of files git add --patch file.txt # Unstage parts of files git reset --patch file.txt # Discard parts of changes git checkout --patch file.txt

Git Worktrees

Work on multiple branches simultaneously without switching:

# Create worktree for another branch git worktree add ../project-feature feature-branch # List worktrees git worktree list # Remove worktree git worktree remove ../project-feature # Prune deleted worktrees git worktree prune # Use case: Fix bug while working on feature git worktree add ../project-hotfix hotfix cd ../project-hotfix # Fix bug, commit, push cd ../project-main git worktree remove ../project-hotfix

Git Sparse Checkout

Clone only specific directories from a large repository:

# Initialize repository git clone --filter=blob:none --sparse https://github.com/user/repo.git cd repo # Add specific directories git sparse-checkout init --cone git sparse-checkout set docs src/components # Add more directories git sparse-checkout add tests # List sparse directories git sparse-checkout list # Disable sparse checkout git sparse-checkout disable
15. Resources, Tools & Further Learning

Essential Git Tools

GitHub CLI

Official GitHub command-line tool

# Install brew install gh # Authenticate gh auth login # Create PR gh pr create # View issues gh issue list

GitKraken

Visual Git client with intuitive interface

  • • Visual commit history
  • • Built-in merge conflict editor
  • • GitHub/GitLab integration
  • • Cross-platform support

SourceTree

Free Git GUI for Windows & Mac

  • • Visualize branches easily
  • • Interactive rebase
  • • Submodule support
  • • Git flow integration

Tig

Text-mode interface for Git

# Install brew install tig # Launch tig # View specific file tig path/to/file

Delta

Better diff viewer with syntax highlighting

# Install brew install git-delta # Configure git config --global core.pager delta git config --global delta.side-by-side true

Lazygit

Terminal UI for Git commands

# Install brew install lazygit # Launch lazygit

IDE Git Integration

VS Code Git Extensions

  • GitLens: Supercharge Git in VS Code
  • Git Graph: View repository graph
  • Git History: View and search history
  • GitHub Pull Requests: Manage PRs

IntelliJ IDEA Git Features

  • • Built-in visual diff and merge
  • • Local history tracking
  • • Shelf changes (like stash)
  • • Interactive rebase dialog

Learning Resources

Pro Git Book: Free comprehensive guide at git-scm.com/book - The definitive Git resource
Learn Git Branching: Interactive visual tutorial at learngitbranching.js.org
Oh My Git!: Open-source game to learn Git at ohmygit.org
Git Documentation: Official reference at git-scm.com/docs
Atlassian Git Tutorials: Excellent tutorials at atlassian.com/git/tutorials
Git & GitHub Crash Course: YouTube tutorials by Traversy Media, The Net Ninja, and Academind

Git Hosting Platforms

Platform Best For Key Features
GitHub Open source, collaboration Actions, Discussions, Copilot, Pages
GitLab DevOps, CI/CD Built-in CI/CD, Container Registry
Bitbucket Atlassian ecosystem Jira integration, Pipelines
Azure DevOps Enterprise, Microsoft stack Boards, Pipelines, Artifacts
Gitea Self-hosted, lightweight Open source, minimal resources

Useful Git Commands Reference

# Quick command reference git help # Get help git --help # Detailed help man git- # Man pages # Configuration locations ~/.gitconfig # Global config .git/config # Local repo config /etc/gitconfig # System config # Environment variables export GIT_AUTHOR_NAME="Your Name" export GIT_AUTHOR_EMAIL="your@email.com" export GIT_COMMITTER_NAME="Your Name" export GIT_COMMITTER_EMAIL="your@email.com" # Git directory structure .git/ ├── HEAD # Current branch pointer ├── config # Repository config ├── description # Repository description ├── hooks/ # Hook scripts ├── objects/ # Git objects (commits, trees, blobs) ├── refs/ # Branch and tag references └── logs/ # Reflog data

Community & Support

Stack Overflow

Search and ask Git questions

Discord Communities

Real-time help and discussions

Reddit r/git

Community discussions and tips

Frequently Asked Questions
What's the difference between Git and GitHub?

Git is the version control system - software you install locally. GitHub is a cloud-based hosting service for Git repositories with additional collaboration features like pull requests, issues, and project management.

When should I use merge vs rebase?

Use merge for: public/shared branches, preserving complete history, team collaboration. Use rebase for: cleaning up local commits before pushing, maintaining linear history, feature branches before merging to main.

How do I undo a pushed commit?

Use git revert HEAD to create a new commit that undoes changes (safe for shared branches). Avoid git reset on pushed commits as it rewrites history and causes problems for others.

What's the best branching strategy?

It depends on your team and project. GitHub Flow works well for continuous deployment. Git Flow suits projects with scheduled releases. Trunk-Based Development is ideal for mature teams with strong CI/CD.

How often should I commit?

Commit whenever you complete a logical unit of work. Each commit should be atomic (one purpose), functional (code works), and meaningful (has clear message). Typically several times per day.

Can I recover deleted commits?

Yes! Use git reflog to find the commit hash, then git checkout commit-hash or git cherry-pick commit-hash. Reflog keeps commits for 90 days by default.

What's .gitignore and what should I ignore?

.gitignore specifies files Git should ignore. Always ignore: dependencies (node_modules/), build outputs (dist/, build/), logs, OS files (.DS_Store), IDE configs (.vscode/), environment files (.env), and sensitive data.

How do I sync my fork with upstream?
git remote add upstream https://github.com/original/repo.git git fetch upstream git checkout main git merge upstream/main git push origin main
What does HEAD mean in Git?

HEAD is a pointer to your current location in the repository - usually the tip of your current branch. HEAD~1 means one commit before HEAD, HEAD~2 means two commits before, etc.

Should I use HTTPS or SSH for Git?

SSH is recommended for regular use (no password prompts, more secure). HTTPS works well for occasional access or restrictive networks. Both are secure when properly configured.

Share:
FEEDBACK