Git is the foundation of modern software development. Whether you are working solo or in a team, mastering Git commands dramatically improves your productivity. This guide covers everything from daily basics to advanced recovery techniques.
Key Takeaways
- 1git add -p for interactive staging; git commit --amend to fix last commit
- 2git switch -c branch-name is the modern way to create and switch branches
- 3git push --force-with-lease is safer than --force for shared branches
- 4git reset for local commits, git revert for pushed commits
- 5git reflog is your safety net—it tracks all HEAD movements for about 90 days
1Initial Setup
Configure Git with your identity and preferences before your first commit. These settings apply globally or per-repository.
# Set your identity (required for commits)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
# Set default branch name (main instead of master)
git config --global init.defaultBranch main
# Set default editor (for commit messages)
git config --global core.editor "code --wait" # VS Code
git config --global core.editor "vim" # Vim
# Enable helpful colors
git config --global color.ui auto
# 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.lg "log --oneline --graph --all"
# View all settings
git config --listUse --global for user-wide settings, no flag for repo-specific settings. Your global config lives in ~/.gitconfig; repo config is in .git/config.
Basic Commands
These commands form your daily Git workflow: tracking changes, staging, and committing.
# Initialize a new repository
git init
# Clone an existing repository
git clone https://github.com/user/repo.git
git clone git@github.com:user/repo.git # SSH
# Check status of working directory
git status
git status -s # Short format
# Stage files for commit
git add filename.txt # Single file
git add . # All changes
git add -p # Interactive (pick hunks)
# Commit staged changes
git commit -m "Add feature X"
git commit -am "Fix bug" # Add + commit tracked files
git commit --amend # Edit last commit
# View commit history
git log
git log --oneline # Compact view
git log --oneline --graph --all # Visual branches
git log -p # With diffs
git log --since="2 weeks ago" # Time filter| Command | Purpose |
|---|---|
| git init | Create new repository |
| git clone <url> | Copy remote repository |
| git status | Show working tree status |
| git add <file> | Stage changes |
| git commit -m "msg" | Save staged changes |
| git log | View commit history |
3Branching and Merging
Branches let you work on features in isolation. Master these commands for effective collaboration.
# List branches
git branch # Local branches
git branch -r # Remote branches
git branch -a # All branches
# Create and switch branches
git branch feature-x # Create branch
git checkout feature-x # Switch to branch
git checkout -b feature-x # Create + switch (shortcut)
git switch feature-x # Modern switch command
git switch -c feature-x # Create + switch (modern)
# Merge branches
git checkout main
git merge feature-x # Merge feature into main
git merge --no-ff feature-x # Force merge commit
# Delete branches
git branch -d feature-x # Delete (safe)
git branch -D feature-x # Force delete
git push origin --delete feature-x # Delete remote branch
# Rename branch
git branch -m old-name new-name
git branch -m new-name # Rename current branchUse git switch (Git 2.23+) instead of checkout for branch operations. It is clearer: switch is for branches, restore is for files.
4Working with Remotes
Remote repositories enable collaboration. Learn to sync your local work with GitHub, GitLab, or other hosts.
# View remotes
git remote -v
# Add remote
git remote add origin https://github.com/user/repo.git
git remote add upstream https://github.com/original/repo.git
# Fetch and pull
git fetch origin # Download without merge
git fetch --all # All remotes
git pull origin main # Fetch + merge
git pull --rebase origin main # Fetch + rebase
# Push changes
git push origin main # Push to main
git push -u origin feature-x # Push + set upstream
git push --force-with-lease # Safe force push
git push --tags # Push all tags
# Track remote branch
git checkout -b feature origin/feature # Create tracking branch
git branch --set-upstream-to=origin/main # Set upstream
# Remove remote
git remote remove originNever use git push --force on shared branches. It rewrites history and can destroy teammates work. Use --force-with-lease which fails if remote has new commits.
5Stashing Changes
Stash temporarily saves uncommitted changes so you can switch branches or pull updates cleanly.
# Stash current changes
git stash # Stash tracked files
git stash -u # Include untracked files
git stash -m "WIP: feature X" # With message
# List stashes
git stash list
# Apply stash
git stash pop # Apply + delete stash
git stash apply # Apply, keep stash
git stash apply stash@{2} # Apply specific stash
# View stash contents
git stash show # Summary
git stash show -p # Full diff
# Delete stashes
git stash drop # Delete latest
git stash drop stash@{2} # Delete specific
git stash clear # Delete all
# Create branch from stash
git stash branch new-feature # Creates branch with stashUse git stash -m "description" to name your stashes. Without names, stash@{0}, stash@{1} becomes confusing quickly.
6Undoing Changes
Git provides multiple ways to undo changes. Choose based on whether changes are staged, committed, or pushed.
# Unstage files (keep changes)
git restore --staged filename.txt
git reset HEAD filename.txt # Old syntax
# Discard local changes
git restore filename.txt # Discard file changes
git checkout -- filename.txt # Old syntax
git restore . # Discard all changes
# Undo last commit (keep changes staged)
git reset --soft HEAD~1
# Undo last commit (keep changes unstaged)
git reset HEAD~1
git reset --mixed HEAD~1 # Same as above
# Undo last commit (discard changes)
git reset --hard HEAD~1
# Revert a commit (creates new commit)
git revert abc1234 # Revert specific commit
git revert HEAD # Revert last commit
git revert HEAD~3..HEAD # Revert range
# Recover deleted commits
git reflog # View all HEAD movements
git checkout abc1234 # Checkout lost commit
git branch recovered abc1234 # Create branch at commit| Scenario | Command |
|---|---|
| Unstage file | git restore --staged file |
| Discard local changes | git restore file |
| Undo commit, keep changes | git reset --soft HEAD~1 |
| Undo commit, discard changes | git reset --hard HEAD~1 |
| Undo pushed commit | git revert <commit> |
| Find lost commits | git reflog |
git reset --hard permanently discards changes. Use with caution. For pushed commits, always use git revert to create a new commit that undoes changes without rewriting history.
7Rebasing
Rebasing replays commits on a new base, creating a linear history. It is powerful but requires care with shared branches.
# Rebase current branch onto main
git checkout feature
git rebase main
# Interactive rebase (edit, squash, reorder commits)
git rebase -i HEAD~5 # Last 5 commits
git rebase -i main # All commits since main
# Interactive rebase options:
# pick - keep commit as is
# reword - change commit message
# edit - pause to amend commit
# squash - meld into previous commit
# fixup - like squash but discard message
# drop - remove commit
# Continue after resolving conflicts
git rebase --continue
# Abort rebase
git rebase --abort
# Pull with rebase (cleaner than merge)
git pull --rebase origin main
# Autosquash fixup commits
git commit --fixup abc1234
git rebase -i --autosquash mainGolden rule: Never rebase commits that have been pushed and shared with others. Rebasing rewrites history, which causes problems for anyone who has based work on those commits.
8Troubleshooting
When things go wrong, these commands help diagnose and fix issues.
# Find which commit introduced a bug
git bisect start
git bisect bad # Current commit is bad
git bisect good abc1234 # Known good commit
# Git checks out middle commit; test and mark good/bad
git bisect good # or git bisect bad
git bisect reset # When done
# Find who changed a line
git blame filename.txt
git blame -L 10,20 filename.txt # Lines 10-20
# Search commits
git log --grep="bug fix" # Search messages
git log -S "functionName" # Search for code changes
git log -- filename.txt # Commits touching file
# View file at specific commit
git show abc1234:path/to/file.txt
# Compare branches/commits
git diff main..feature # Diff between branches
git diff abc1234..def5678 # Diff between commits
git diff --stat # Summary only
# Clean untracked files
git clean -n # Dry run
git clean -f # Remove files
git clean -fd # Remove files + directories
# Fix corrupted repository
git fsck # Check integrity
git gc # Garbage collectiongit bisect is incredibly powerful for finding bugs. It uses binary search to test commits, finding the problematic one in O(log n) steps even across hundreds of commits.
Boost Your Developer Workflow
Free online tools for encoding, formatting, hashing, and more.
Explore Dev ToolsFrequently Asked Questions
What is the difference between git pull and git fetch?
git fetch downloads commits and refs from remote but does not integrate them—your working directory stays unchanged. git pull is git fetch + git merge (or rebase with --rebase). Use fetch to see what is new without affecting your work; use pull when ready to integrate.
When should I use merge vs rebase?
Use merge for shared branches and when you want to preserve history exactly as it happened. Use rebase for feature branches before merging to create a clean, linear history. Never rebase commits that have been pushed and shared with others.
How do I undo a pushed commit?
Use git revert <commit-hash> to create a new commit that undoes the changes. This is safe for shared branches because it does not rewrite history. Avoid git reset on pushed commits—it causes problems for collaborators.
What is HEAD in Git?
HEAD is a pointer to the current commit you are working on. Usually it points to a branch (like main), which points to a commit. HEAD~1 means ’one commit before HEAD’, HEAD~2 means ’two commits before’, etc. Detached HEAD means HEAD points directly to a commit, not a branch.
How do I recover a deleted branch?
Use git reflog to find the commit hash of the branch tip before deletion. Then create a new branch at that commit: git branch recovered-branch abc1234. Reflog keeps references for about 90 days, so act reasonably quickly.