Essential Git Commands Cheatsheet for Developers

· 12 min read

Table of Contents

Git is the backbone of modern software development. Whether you're working solo or collaborating with a team of hundreds, mastering Git commands is essential for efficient version control and code management.

This comprehensive cheatsheet covers everything from basic operations to advanced techniques. Bookmark this page and refer back whenever you need a quick reference for Git commands.

Setup & Configuration

Before you start using Git, you need to configure your identity and preferences. These settings determine how Git behaves and how your commits are attributed.

Initial Configuration

Run these commands once per machine to set up your Git environment:

# Set your name and email (required)
git config --global user.name "Your Name"
git config --global user.email "[email protected]"

# Set default branch name to 'main'
git config --global init.defaultBranch main

# Enable color output for better readability
git config --global color.ui auto

# Set your preferred text editor
git config --global core.editor "code --wait"  # VS Code
git config --global core.editor "vim"          # Vim
git config --global core.editor "nano"         # Nano

# View all configuration settings
git config --list

# View specific configuration
git config user.name
git config user.email

The --global flag applies settings to all repositories on your machine. To configure settings for a single repository, navigate to that repo and omit the --global flag.

Configuration Levels

Git has three configuration levels, each overriding the previous:

Level Flag Location Scope
System --system /etc/gitconfig All users on the machine
Global --global ~/.gitconfig All repos for current user
Local --local .git/config Current repository only

Pro tip: Use different email addresses for work and personal projects by setting local configs in each repository. This prevents accidentally committing with the wrong identity.

Useful Configuration Options

# Set up credential caching (avoid repeated password prompts)
git config --global credential.helper cache
git config --global credential.helper 'cache --timeout=3600'

# Enable automatic line ending conversion
git config --global core.autocrlf true   # Windows
git config --global core.autocrlf input  # Mac/Linux

# Set up aliases for common commands
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'

# Configure merge and diff tools
git config --global merge.tool vimdiff
git config --global diff.tool vimdiff

Basic Git Commands

These are the fundamental commands you'll use daily. Master these first before moving to advanced operations.

Repository Initialization

# Initialize a new Git repository
git init

# Initialize with a specific branch name
git init -b main

# Clone an existing repository
git clone https://github.com/user/repo.git
git clone [email protected]:user/repo.git  # SSH
git clone https://github.com/user/repo.git my-folder  # Custom folder name

# Clone only recent history (faster for large repos)
git clone --depth 1 https://github.com/user/repo.git

Working with Changes

# Check status of working directory
git status
git status -s  # Short format
git status -sb # Short format with branch info

# Stage files for commit
git add filename.js        # Single file
git add src/               # Entire directory
git add .                  # All changes in current directory
git add -A                 # All changes in entire repo
git add -p                 # Interactive staging (patch mode)
git add *.js               # All JavaScript files

# Unstage files
git reset filename.js      # Unstage specific file
git reset                  # Unstage all files

# Commit staged changes
git commit -m "feat: add user authentication"
git commit -am "fix: resolve login bug"  # Stage + commit tracked files
git commit --amend         # Modify the last commit
git commit --amend --no-edit  # Amend without changing message

# View differences
git diff                   # Unstaged changes
git diff --staged          # Staged changes
git diff HEAD              # All changes since last commit
git diff main..feature     # Between branches
git diff --stat            # Summary of changes

Quick tip: Use git add -p to review and stage changes interactively. This is perfect for committing only specific parts of a file while leaving other changes unstaged.

Removing and Moving Files

# Remove files
git rm filename.js         # Remove from working directory and stage deletion
git rm --cached filename.js # Remove from Git but keep in working directory
git rm -r directory/       # Remove directory recursively

# Move or rename files
git mv old-name.js new-name.js
git mv src/file.js lib/file.js  # Move to different directory

When you use git mv or git rm, the changes are automatically staged. This is more convenient than using regular shell commands and then staging the changes separately.

Branching & Merging

Branches are Git's killer feature. They allow you to work on multiple features simultaneously without interfering with the main codebase.

Branch Management

# List branches
git branch                 # Local branches
git branch -r              # Remote branches
git branch -a              # All branches (local + remote)
git branch -v              # With last commit info
git branch --merged        # Branches merged into current branch
git branch --no-merged     # Branches not yet merged

# Create branches
git branch feature-login   # Create new branch
git checkout -b feature-login  # Create and switch to new branch
git switch -c feature-login    # Modern alternative to checkout

# Switch branches
git checkout main          # Switch to main branch
git switch main            # Modern alternative
git checkout -            # Switch to previous branch

# Rename branches
git branch -m old-name new-name  # Rename branch
git branch -M new-name     # Force rename current branch

# Delete branches
git branch -d feature-login     # Delete merged branch
git branch -D feature-login     # Force delete (even if unmerged)
git push origin --delete feature-login  # Delete remote branch

Merging Strategies

# Merge branches
git merge feature-login    # Merge feature-login into current branch
git merge --no-ff feature-login  # Create merge commit even for fast-forward
git merge --squash feature-login # Squash all commits into one

# Abort a merge
git merge --abort

# Continue after resolving conflicts
git merge --continue
Merge Type Command When to Use
Fast-forward git merge Linear history, no divergence
No fast-forward git merge --no-ff Preserve feature branch history
Squash git merge --squash Clean history, combine all commits
Rebase git rebase Linear history, rewrite commits

Rebasing

Rebasing rewrites commit history by moving your branch to a new base commit. This creates a cleaner, linear history but should be used carefully.

# Rebase current branch onto main
git rebase main

# Interactive rebase (edit, squash, reorder commits)
git rebase -i HEAD~3       # Last 3 commits
git rebase -i main         # All commits since branching from main

# Continue after resolving conflicts
git rebase --continue

# Skip current commit
git rebase --skip

# Abort rebase
git rebase --abort

Pro tip: Never rebase commits that have been pushed to a shared branch. Rebasing rewrites history, which can cause serious problems for collaborators. Use it only for local cleanup before pushing.

Resolving Merge Conflicts

When Git can't automatically merge changes, you'll need to resolve conflicts manually:

  1. Run git status to see which files have conflicts
  2. Open conflicted files and look for conflict markers (<<<<<<<, =======, >>>>>>>)
  3. Edit the file to resolve conflicts, removing the markers
  4. Stage the resolved files with git add
  5. Complete the merge with git commit or git merge --continue
# Use merge tools to resolve conflicts
git mergetool

# Accept all changes from one side
git checkout --ours filename.js    # Keep your version
git checkout --theirs filename.js  # Keep their version

Remote Operations

Remote repositories enable collaboration. These commands help you sync your local work with remote servers like GitHub, GitLab, or Bitbucket.

Managing Remotes

# List remote repositories
git remote
git remote -v              # With URLs

# Add remote repository
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 [email protected]:user/repo.git

# Remove remote
git remote remove origin

# Rename remote
git remote rename origin upstream

# Show remote details
git remote show origin

Fetching and Pulling

# Fetch changes from remote (doesn't merge)
git fetch origin
git fetch --all            # Fetch from all remotes
git fetch --prune          # Remove deleted remote branches

# Pull changes (fetch + merge)
git pull origin main
git pull --rebase origin main  # Fetch + rebase instead of merge
git pull --ff-only         # Only fast-forward, fail if merge needed

# Pull with automatic stash
git pull --autostash

The difference between fetch and pull is important. Fetch downloads changes but doesn't modify your working directory, while pull automatically merges the changes.

Pushing Changes

# Push to remote
git push origin main
git push -u origin feature-login  # Set upstream and push
git push --all             # Push all branches
git push --tags            # Push all tags

# Force push (use with caution!)
git push --force           # Overwrite remote history
git push --force-with-lease # Safer force push, fails if remote updated

# Delete remote branch
git push origin --delete feature-login
git push origin :feature-login  # Alternative syntax

Pro tip: Use --force-with-lease instead of --force when you need to force push. It prevents you from accidentally overwriting someone else's work if the remote has been updated since your last fetch.

Tracking Branches

# Set upstream branch
git branch --set-upstream-to=origin/main main
git branch -u origin/main  # Shorthand

# Create tracking branch
git checkout -b feature origin/feature
git checkout --track origin/feature  # Automatic naming

# View tracking relationships
git branch -vv

Stashing Changes

Stashing temporarily shelves changes so you can work on something else without committing incomplete work.

# Stash current changes
git stash
git stash save "work in progress on login feature"
git stash -u               # Include untracked files
git stash -a               # Include untracked and ignored files

# List stashes
git stash list

# Apply stashed changes
git stash apply            # Apply most recent stash
git stash apply stash@{2}  # Apply specific stash
git stash pop              # Apply and remove from stash list

# View stash contents
git stash show
git stash show -p          # Show full diff
git stash show stash@{1}   # Show specific stash

# Create branch from stash
git stash branch feature-name

# Remove stashes
git stash drop stash@{1}   # Remove specific stash
git stash clear            # Remove all stashes

Stashing is perfect when you need to quickly switch contexts. For example, if you're working on a feature and need to fix an urgent bug, stash your changes, fix the bug, then pop the stash to continue where you left off.

Quick tip: Use descriptive messages with git stash save when you have multiple stashes. This makes it much easier to identify the right stash later.

History & Inspection

Understanding your project's history is crucial for debugging, code review, and understanding how your codebase evolved.

Viewing Commit History

# View commit history
git log
git log --oneline          # Compact view
git log --graph            # Visual branch structure
git log --all              # All branches
git log -n 5               # Last 5 commits
git log --since="2 weeks ago"
git log --until="2024-01-01"
git log --author="John"

# Formatted output
git log --pretty=format:"%h - %an, %ar : %s"
git log --pretty=oneline
git log --graph --oneline --all --decorate

# Filter by file or directory
git log -- filename.js
git log -- src/

# Search commits
git log --grep="bug fix"   # Search commit messages
git log -S "function name" # Search code changes (pickaxe)
git log -G "regex pattern" # Search with regex

# Show commits that changed specific lines
git log -L 10,20:filename.js

Inspecting Changes

# Show commit details
git show HEAD              # Latest commit
git show abc123            # Specific commit
git show HEAD~3            # 3 commits ago
git show main:filename.js  # File at specific branch

# Show file at specific commit
git show abc123:src/app.js

# Blame (see who changed each line)
git blame filename.js
git blame -L 10,20 filename.js  # Specific lines
git blame -C filename.js   # Detect moved/copied lines

# Show changes between commits
git diff abc123 def456
git diff HEAD~2 HEAD
git diff main...feature    # Changes since branching

# Show files changed in commit
git diff-tree --no-commit-id --name-only -r abc123

Searching the Repository

# Search working directory
git grep "search term"
git grep -n "search term"  # Show line numbers
git grep -c "search term"  # Count matches per file
git grep -i "search term"  # Case insensitive

# Search specific commit
git grep "search term" abc123

# Search with context
git grep -A 3 -B 3 "search term"  # 3 lines before/after

Use our Diff Checker tool to compare code changes visually when working with complex diffs.

Undoing Changes

Mistakes happen. Git provides multiple ways to undo changes depending on what you need to fix.

Undoing Working Directory Changes

# Discard changes in working directory
git restore filename.js    # Modern command
git checkout -- filename.js # Legacy command
git restore .              # Discard all changes

# Restore file from specific commit
git restore --source=HEAD~2 filename.js
git restore --source=abc123 filename.js

Unstaging Changes

# Unstage files
git restore --staged filename.js  # Modern command
git reset HEAD filename.js        # Legacy command
git reset                         # Unstage all files

Modifying Commits

# Amend last commit
git commit --amend -m "new message"
git commit --amend --no-edit  # Keep same message

# Reset to previous commit
git reset --soft HEAD~1   # Keep changes staged
git reset --mixed HEAD~1  # Keep changes unstaged (default)
git reset --hard HEAD~1   # Discard all changes

# Reset to specific commit
git reset --hard abc123

# Reset single file to previous commit
git checkout HEAD~1 -- filename.js
Reset Type Working Directory Staging Area Commit History
--soft Unchanged Unchanged Reset
--mixed Unchanged Reset Reset
--hard Reset Reset Reset

Reverting Commits

Unlike reset, revert creates a new commit that undoes changes. This is safer for shared branches because it doesn't rewrite history.

# Revert specific commit
git revert abc123
git revert HEAD            # Revert last commit
git revert HEAD~3          # Revert 4th last commit

# Revert without committing
git revert -n abc123       # Stage changes only

# Revert merge commit
git revert -m 1 abc123     # Specify parent number

# Revert multiple commits
git revert abc123..def456

Pro tip: Use git revert for shared branches and git reset for local branches. Revert is safer because it preserves history, while reset rewrites it.

Recovering Lost Commits

# View reflog (history of HEAD movements)
git reflog
git reflog show main

# Recover lost commit
git checkout abc123        # From reflog
git cherry-pick abc123     # Apply to current branch

# Recover deleted branch
git checkout -b recovered-branch abc123

Advanced Commands

These advanced techniques help you work more efficiently and handle complex scenarios.

Cherry-picking

Cherry-pick applies specific commits from one branch to another without merging the entire branch.

# Apply specific commit to current branch
git cherry-pick abc123
git cherry-pick abc123 def456  # Multiple commits

# Cherry-pick without committing
git cherry-pick -n abc123

# Cherry-pick with edit
git cherry-pick -e abc123

# Continue after resolving conflicts
git cherry-pick --continue

# Abort cherry-pick
git cherry-pick --abort

Tagging

Tags mark specific points in history, typically for releases.

# Create lightweight tag
git tag v1.0.0

# Create annotated tag (recommended)
git tag -a v1.0.0 -m "Release version 1.0.0"

# Tag specific commit
git tag -a v1.0.0 abc123 -m "Release version 1.0.0"

# List tags
git tag
git tag -l "v1.*"          # Filter tags

# Show tag details
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

Submodules

Submodules allow you to include other Git repositories within your repository.

# Add submodule
git submodule add https://github.com/user/repo.git path/to/submodule

# Initialize submodules after cloning
git submodule init
git submodule update

# Clone repository with submodules
git clone --recursive https://github.com/user/repo.git

# Update submodules
git submodule update --remote

# Remove submodule
git submodule deinit path/to/submodule
git rm path/to/submodule
rm -rf .git/modules/path/to/submodule

Bisect (Binary Search for Bugs)

Bisect helps you find which commit introduced a bug using binary search.

# Start bisect
git bisect start

# Mark current commit as bad
git bisect bad

# Mark known good commit
git bisect good abc123

# Git will checkout middle commit - test it
# Then mark as good or bad
git bisect good   # or git bisect bad

# Continue until bug is found
# Reset when done
git bisect reset

Worktrees

Worktrees let you check out multiple branches simultaneously in different directories.

# Create new worktree
git worktree add ../feature-branch feature-branch

# List worktrees
git worktree list

# Remove worktree
git worktree remove ../feature-branch

# Prune deleted worktrees
git worktree prune

Git Workflows & Best Practices

Choosing the right workflow and following best practices makes collaboration smoother and keeps your repository clean.

Common Git Workflows

Feature Branch Workflow: Create a new branch for each feature, merge back to main when complete. Simple and effective for small teams.

Gitflow Workflow: Uses multiple long-lived branches (main, develop) and specific branch types (feature, release, hotfix). Good for scheduled releases.

Forking Workflow: Each developer has their own server-side repository. Common in open source projects.

Trunk-Based Development: Developers work on short-lived branches or directly on main with feature flags. Enables continuous integration.

Commit Message Best Practices

Good commit messages make your history readable and useful:

# Good commit message examples
feat(auth): add OAuth2 authentication
fix(api): resolve race condition in user endpoint
docs(readme): update installation instructions
refactor(utils): simplify date formatting logic
test(auth): add integration tests for login flow

# With detailed description
feat(auth): add OAuth2 authentication

Implement OAuth2 authentication flow with support for
Google and GitHub providers. Includes token refresh
logic and secure session management.

Closes #123

Branch Naming Conventions

# Feature branches
feature/user-authentication
feature/payment-integration

# Bug fix branches
fix/login-error
bugfix/memory-leak

# Hotfix branches
hotfix/security-patch
hotfix/critical-bug

# Release branches
release/v1.2.0
release/2024-q1

Keeping Your Repository Clean

# Remove merged branches
git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

# Clean up remote tracking branches
git fetch --prune

# Remove untracked files
git clean -n               # Dry run (preview)
git clean -f               # Remove files
git clean -fd              # Remove files and directories
git clean -fx              # Include ignored files

# Optimize repository
git gc                     # Garbage collection
git gc --aggressive        # More thorough optimization

Pro tip: Set up a pre-commit hook to automatically format code and run linters before each commit. This keeps your codebase consistent and catches issues early.

Troubleshooting Common Issues

Even experienced developers encounter Git problems. Here's how to solve the most common issues.

Merge Conflicts

When Git can't automatically merge changes:

# See which files have conflicts
git status

# Use a merge tool
git mergetool

# After resolving, complete the merge
git add resolved-file.js
git commit

# Or abort the merge
git merge --abort

Accidentally Committed to Wrong Branch

# Move commits to new branch
git branch feature-branch
git reset --hard HEAD~2    # Remove last 2 commits from current branch
git checkout feature-branch

# Or use cherry-pick
git checkout correct-branch
git cherry-pick abc123

Pushed Sensitive Data

If you accidentally committed passwords or API keys:

# Remove file from all history (use with caution!)
git filter-branch --force --index-filter \
  "git rm --cached --ignore-unmatch path/to/file" \
  --prune-empty --tag-name-filter cat -- --all

# Or use BFG Repo-Cleaner (faster)
bfg --delete-files sensitive-file.txt

# Force push to update remote
git push --force --all

Important: Change any exposed credentials immediately. Removing them from Git history doesn't revoke access.

Detached HEAD State

# Create branch from detached HEAD
git checkout -b new-branch-name

# Or discard changes and return to branch
git checkout main

Large Files Causing Issues

# Find large files in history
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

# Use Git LFS for large files
git lfs install
git lfs track "*.psd"
git add .gitattributes

Recovering from Force Push