- Git Basics
- Repository Setup
- Basic Workflow
- Branching & Merging
- Remote Repositories
- Commit Management
- Cherry Picking
- Authorship & Attribution
- Advanced Commands
- GitHub Integration
- Useful Tricks & Tips
- Troubleshooting
Git is a distributed version control system that tracks changes in files and coordinates work between multiple people. It's essential for software development and project management.
- Version Control: Track all changes to your code over time
- Collaboration: Multiple developers can work on the same project
- Backup: Distributed nature provides automatic backups
- Branching: Create separate lines of development
- History: Complete audit trail of all changes
# Create a new Git repository in current directory
git init
# Create a new directory and initialize Git
git init my-project
cd my-project
# Clone from GitHub/GitLab/etc.
git clone https://github.com/username/repository.git
# Clone to a specific directory
git clone https://github.com/username/repository.git my-folder
# Clone only specific branch
git clone -b branch-name https://github.com/username/repository.git
# Shallow clone (only recent history)
git clone --depth 1 https://github.com/username/repository.git
# Set global user information
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
# Set local user information (for current repo only)
git config user.name "Your Name"
git config user.email "your.email@example.com"
# View current configuration
git config --list
git config user.name
git config user.email
# Set default editor
git config --global core.editor "code --wait" # VS Code
git config --global core.editor "vim" # Vim
# Set default branch name
git config --global init.defaultBranch main
# Check repository status
git status
# Short status format
git status -s
# Check ignored files too
git status --ignored
# Add specific file
git add filename.txt
# Add multiple files
git add file1.txt file2.txt
# Add all files in current directory
git add .
# Add all modified files
git add -u
# Add all files (new, modified, deleted)
git add -A
# Interactive adding
git add -i
# Add parts of a file (patch mode)
git add -p filename.txt
# Basic commit
git commit -m "Your commit message"
# Commit with detailed message
git commit -m "Short description" -m "Longer explanation of changes"
# Add and commit in one step (tracked files only)
git commit -am "Commit message"
# Amend the last commit
git commit --amend -m "New commit message"
# Commit with different author
git commit --author="Name <email@example.com>" -m "Message"
# Empty commit (useful for triggering CI)
git commit --allow-empty -m "Trigger build"
# View commit history
git log
# Compact one-line format
git log --oneline
# Show last N commits
git log -n 5
# Show commits with file changes
git log --stat
# Show commits with full diff
git log -p
# Graphical representation
git log --graph --oneline --all
# Filter by author
git log --author="John Doe"
# Filter by date
git log --since="2023-01-01" --until="2023-12-31"
# Filter by message
git log --grep="bug fix"
# Show commits that modified specific file
git log -- filename.txt
# List all branches
git branch
# List all branches (including remote)
git branch -a
# Create new branch
git branch new-feature
# Create and switch to new branch
git checkout -b new-feature
# Modern way to create and switch
git switch -c new-feature
# Switch to existing branch
git checkout main
git switch main
# Rename current branch
git branch -m new-name
# Rename specific branch
git branch -m old-name new-name
# Delete branch
git branch -d feature-branch
# Force delete branch
git branch -D feature-branch
# Delete remote branch
git push origin --delete feature-branch
# Merge branch into current branch
git merge feature-branch
# Merge with no fast-forward (always create merge commit)
git merge --no-ff feature-branch
# Merge with squash (combine all commits into one)
git merge --squash feature-branch
# Abort merge if conflicts
git merge --abort
# Rebase current branch onto main
git rebase main
# Interactive rebase (last 3 commits)
git rebase -i HEAD~3
# Continue rebase after resolving conflicts
git rebase --continue
# Skip current commit during rebase
git rebase --skip
# Abort rebase
git rebase --abort
# Rebase onto specific commit
git rebase commit-hash
# List remotes
git remote -v
# Add remote
git remote add origin https://github.com/username/repository.git
# Change remote URL
git remote set-url origin https://github.com/username/new-repository.git
# Remove remote
git remote remove origin
# Rename remote
git remote rename origin upstream
# Fetch changes from remote
git fetch origin
# Fetch all remotes
git fetch --all
# Pull changes (fetch + merge)
git pull origin main
# Pull with rebase instead of merge
git pull --rebase origin main
# Set upstream branch
git push -u origin main
git branch --set-upstream-to=origin/main main
# Push to remote
git push origin main
# Push all branches
git push --all origin
# Push tags
git push --tags
# Force push (dangerous!)
git push --force origin main
# Force push with lease (safer)
git push --force-with-lease origin main
# Push and set upstream
git push -u origin feature-branch
# Show unstaged changes
git diff
# Show staged changes
git diff --cached
# Show changes between commits
git diff commit1 commit2
# Show changes in specific file
git diff filename.txt
# Show changes between branches
git diff main..feature-branch
# Word-level diff
git diff --word-diff
# Unstage file
git reset HEAD filename.txt
# Discard unstaged changes
git checkout -- filename.txt
git restore filename.txt
# Discard all unstaged changes
git checkout -- .
git restore .
# Reset to last commit (keep changes staged)
git reset --soft HEAD~1
# Reset to last commit (unstage changes)
git reset HEAD~1
# Reset to last commit (discard all changes)
git reset --hard HEAD~1
# Reset to specific commit
git reset --hard commit-hash
# Stash current changes
git stash
# Stash with message
git stash save "Work in progress"
# List stashes
git stash list
# Apply most recent stash
git stash apply
# Apply specific stash
git stash apply stash@{1}
# Apply and remove from stash list
git stash pop
# Drop specific stash
git stash drop stash@{1}
# Clear all stashes
git stash clear
# Stash including untracked files
git stash -u
Cherry picking allows you to apply specific commits from one branch to another without merging the entire branch.
# Cherry pick a specific commit
git cherry-pick commit-hash
# Cherry pick multiple commits
git cherry-pick commit1 commit2 commit3
# Cherry pick a range of commits
git cherry-pick commit1..commit3
# Cherry pick without committing
git cherry-pick --no-commit commit-hash
# Cherry pick and edit commit message
git cherry-pick -e commit-hash
# Cherry pick without changing author
git cherry-pick -x commit-hash
# Cherry pick and sign off
git cherry-pick -s commit-hash
# Continue cherry pick after resolving conflicts
git cherry-pick --continue
# Abort cherry pick
git cherry-pick --abort
# Skip current commit
git cherry-pick --skip
# Cherry pick from another branch
git cherry-pick feature-branch~2
# Cherry pick merge commit (specify parent)
git cherry-pick -m 1 merge-commit-hash
# Cherry pick and change author
git cherry-pick --author="New Author <email@example.com>" commit-hash
# Set author for next commit only
git -c user.name="John Doe" -c user.email="john@example.com" commit -m "Message"
# Commit with specific author
git commit --author="John Doe <john@example.com>" -m "Message"
# Commit on behalf of someone (co-authored)
git commit -m "Fix bug
Co-authored-by: Jane Smith <jane@example.com>"
# Change author of last commit
git commit --amend --author="New Author <email@example.com>"
# Change author of multiple commits (interactive rebase)
git rebase -i HEAD~3
# In the editor, change 'pick' to 'edit' for commits to modify
# For each commit:
git commit --amend --author="New Author <email@example.com>"
git rebase --continue
# Show commits with author info
git log --pretty=format:"%h %an %ae %ad %s"
# Show commits by specific author
git log --author="John Doe"
# Show commits with committer vs author
git log --pretty=format:"%h %an %cn %ad %cd %s"
# Shortlog grouped by author
git shortlog
# Multiple co-authors
git commit -m "Implement feature X
Co-authored-by: Alice <alice@example.com>
Co-authored-by: Bob <bob@example.com>"
# Create lightweight tag
git tag v1.0.0
# Create annotated tag
git tag -a v1.0.0 -m "Version 1.0.0"
# Tag specific commit
git tag -a v1.0.0 commit-hash
# List tags
git tag
# Show tag information
git show v1.0.0
# Push tags
git push origin v1.0.0
git push origin --tags
# Delete tag
git tag -d v1.0.0
git push origin --delete v1.0.0
# Show who last modified each line
git blame filename.txt
# Show blame for specific lines
git blame -L 10,20 filename.txt
# Show blame ignoring whitespace changes
git blame -w filename.txt
# Start bisect
git bisect start
# Mark current commit as bad
git bisect bad
# Mark known good commit
git bisect good commit-hash
# Mark current as good/bad and continue
git bisect good
git bisect bad
# End bisect session
git bisect reset
# Automate bisect with script
git bisect run test-script.sh
# 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
# Install: https://cli.github.com/
# Authenticate
gh auth login
# Create repository
gh repo create my-project
# Clone your repositories
gh repo clone username/repository
# Create pull request
gh pr create --title "Feature X" --body "Description"
# List pull requests
gh pr list
# View pull request
gh pr view 123
# Merge pull request
gh pr merge 123
# Fetch pull request locally
git fetch origin pull/123/head:pr-123
git checkout pr-123
# Push branch for pull request
git push origin feature-branch
# Then create PR on GitHub web interface
# Trigger workflow with empty commit
git commit --allow-empty -m "Trigger CI"
# Push specific branch to trigger workflow
git push origin feature-branch
# Create useful aliases
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.visual '!gitk'
git config --global alias.hist 'log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short'
# Use aliases
git st # Same as git status
git co main # Same as git checkout main
git hist # Pretty formatted log
# Show files changed in last commit
git diff-tree --no-commit-id --name-only -r HEAD
# Count commits by author
git shortlog -sn
# Find commits that added or removed specific text
git log -S "function_name" --oneline
# Show commits not yet pushed
git log origin/main..HEAD --oneline
# Show commits in main that aren't in current branch
git log HEAD..origin/main --oneline
# Undo last commit but keep changes
git reset --soft HEAD~1
# Create patch file
git diff > changes.patch
# Apply patch file
git apply changes.patch
# Show current branch name
git rev-parse --abbrev-ref HEAD
# Create .gitignore file
echo "node_modules/" >> .gitignore
echo "*.log" >> .gitignore
echo ".env" >> .gitignore
# Common .gitignore patterns
*.log # Ignore all .log files
/node_modules # Ignore node_modules directory in root
*.tmp # Ignore all .tmp files
!important.log # Don't ignore important.log
build/ # Ignore build directory
.env* # Ignore all .env files
# Check if file is ignored
git check-ignore filename.txt
# Track previously ignored file
git add -f filename.txt
# Remove untracked files
git clean -f
# Remove untracked files and directories
git clean -fd
# Dry run (show what would be deleted)
git clean -n
# Remove ignored files too
git clean -fx
# Prune remote branches
git remote prune origin
# Delete merged branches
git branch --merged | grep -v "\*\|main\|master" | xargs -n 1 git branch -d
# When merge conflicts occur:
# 1. Open conflicted files and resolve conflicts
# 2. Mark as resolved
git add conflicted-file.txt
# 3. Complete merge
git commit
# Or use merge tools
git mergetool
# Move commits to correct branch
git log --oneline -n 3 # Note commit hashes
git reset --hard HEAD~3 # Remove commits from current branch
git checkout correct-branch
git cherry-pick commit1 commit2 commit3
# Find lost commits
git reflog
# Recover lost commit
git checkout commit-hash
git branch recovered-branch # Create branch to save it
# Remove large file from history
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch largefile.zip' \
--prune-empty --tag-name-filter cat -- --all
# Or use BFG Repo-Cleaner (recommended)
# https://rtyley.github.io/bfg-repo-cleaner/
# When push is rejected due to non-fast-forward:
# Option 1: Pull and merge
git pull origin main
# Option 2: Pull with rebase
git pull --rebase origin main
# Option 3: Force push (dangerous!)
git push --force-with-lease origin main
# View reference log
git reflog
# Recover deleted branch
git checkout -b recovered-branch HEAD@{1}
# Undo last action
git reset HEAD@{1}
# Find dangling commits
git fsck --lost-found
- 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
- Use descriptive branch names (feature/user-auth, bugfix/login-error)
- Keep branches short-lived
- Regularly sync with main branch
- Delete merged branches
- Never commit sensitive information (passwords, API keys)
- Use .gitignore for sensitive files
- Review commits before pushing
- Use signed commits for important repositories
# Enable commit signing
git config --global commit.gpgsign true
git config --global user.signingkey YOUR_GPG_KEY_ID
This guide covers the essential Git commands and concepts you'll need for effective version control and collaboration. Keep practicing these commands to build muscle memory and become proficient with Git!