Git/GitHub Interview Questions
Git Interview Questions: 30 Important Questions + 20 Scenario-Based Questions
Section titled “Git Interview Questions: 30 Important Questions + 20 Scenario-Based Questions”Part 1: 30 Important Git Questions with Detailed Answers
Section titled “Part 1: 30 Important Git Questions with Detailed Answers”1. What is Git and how does it differ from other version control systems?
Section titled “1. What is Git and how does it differ from other version control systems?”Answer:
Git is a distributed version control system (DVCS) designed for speed, data integrity, and distributed workflows.
Key Differences from Centralized VCS (SVN, CVS):
| Aspect | Git (DVCS) | Centralized VCS (SVN) |
|---|---|---|
| Repository | Complete copy on every developer’s machine | Single central repository |
| Working offline | Full commit history available offline | Cannot commit without network |
| Branching | Cheap, fast, easy | Expensive, complex |
| Performance | Local operations are instant | Most operations require network |
| Backup | Every clone is a full backup | Single point of failure |
Git’s Core Features:
- Distributed: Every clone contains full history
- Snapshot-based: Stores snapshots, not file differences
- Integrity: SHA-1 hashing ensures data integrity
- Non-linear development: First-class branching support
2. Explain Git’s three-tree architecture.
Section titled “2. Explain Git’s three-tree architecture.”Answer:
Git manages files through three primary “trees”:
1. Working Directory (Working Tree):
- Where you edit files
- Contains actual files in your filesystem
- Can be in modified, staged, or committed state
2. Index (Staging Area):
- Intermediate area between working directory and repository
- Contains files ready to be committed
- Located in
.git/index
3. HEAD (Repository):
- Points to the last commit in the current branch
- Contains committed snapshots
- Located in
.git/HEAD
Visual Flow:
Working Directory → git add → Staging Area (Index) → git commit → Repository (HEAD) ↓ ↓ ↓ Modified Staged CommittedPractical Example:
# Working Directory: Edit fileecho "change" > file.txt
# Staging Area (Index)git add file.txt
# Repository (HEAD)git commit -m "Commit file"3. What is a Git commit object and what does it contain?
Section titled “3. What is a Git commit object and what does it contain?”Answer:
A commit object is a SHA-1 hashed object containing:
Commit Structure:
tree 4a2b3c... # Tree object representing directory structureparent d6e8f9... # Parent commit(s) SHA (multiple for merges)author John Doe <john@example.com> 1645632000 -0500committer John Doe <john@example.com> 1645632000 -0500gpgsig -----BEGIN PGP SIGNATURE----- ... -----END PGP SIGNATURE-----
Commit message describing changesComponents:
- Tree SHA: Points to the root tree object (directory snapshot)
- Parent SHA: Link to previous commit(s)
- Author: Who wrote the changes (name, email, timestamp)
- Committer: Who applied the changes
- Signature: GPG signature (if signed)
- Message: Commit description
View Commit Details:
# See commit objectgit cat-file -p <commit-sha>
# See commit treegit ls-tree <commit-sha>
# Detailed loggit log --pretty=raw -14. Explain the difference between git merge and git rebase.
Section titled “4. Explain the difference between git merge and git rebase.”Answer:
Git Merge (Preserves History):
- Creates a merge commit combining both branches
- Preserves complete historical context
- Results in non-linear history with explicit merge points
git checkout maingit merge feature# Creates merge commit: "Merge branch 'feature' into main"Git Rebase (Rewrites History):
- Moves entire feature branch to begin at tip of main
- Creates linear history with no merge commits
- Rewrites commit SHAs (new commits)
git checkout featuregit rebase main# Feature branch now starts from main's latest commitVisual Comparison:
Merge: Rebase:A---B---C A---B---C \ \ D---E D'---E' \ \ F F' \ \ M (merge) (linear)When to Use:
- Merge: Public branches, preserving actual history, collaboration
- Rebase: Private feature branches, cleaning up before merging, linear history
5. What’s the difference between git reset and git revert?
Section titled “5. What’s the difference between git reset and git revert?”Answer:
| Aspect | Git Reset | Git Revert |
|---|---|---|
| Operation | Moves branch pointer | Creates new commit that undoes changes |
| History | Rewrites/removes history | Preserves history with undo record |
| Safety | Dangerous (can lose commits) | Safe for shared branches |
| Use case | Local undo, removing commits | Undo public/shared commits |
Git Reset (Three Modes):
# Soft: Moves HEAD only (changes staged)git reset --soft HEAD~1# HEAD moved, changes remain in staging
# Mixed (default): Moves HEAD, unstages changesgit reset HEAD~1# HEAD moved, changes in working directory
# Hard: Moves HEAD, discards all changesgit reset --hard HEAD~1# HEAD moved, changes lost completelyGit Revert (Safe for Public):
# Creates new commit that undoes the specified commitgit revert HEAD~2# Creates commit: "Revert 'Previous commit message'"6. Explain Git’s object model.
Section titled “6. Explain Git’s object model.”Answer:
Git stores four types of objects, all identified by SHA-1 hashes:
1. Blob (Binary Large Object):
- File content (not filename)
- Stored in
.git/objects/
# Create a blobecho "content" | git hash-object -w --stdin
# View blobgit cat-file -p <blob-sha>2. Tree:
- Directory structure
- Contains blob SHAs and other tree SHAs
- Equivalent to a folder
# View treegit cat-file -p <tree-sha># 100644 blob a1b2c3... file.txt# 040000 tree d4e5f6... subdir3. Commit:
- Snapshot of tree at a point in time
- Contains tree SHA, parent SHA, author, committer, message
4. Tag:
- Reference to a specific commit
- Can be lightweight or annotated
Object Storage:
# Objects are compressed and stored in.git/objects/ab/cdef123456789... # First 2 chars = directoryObject Relationships:
Commit ← Tree ← Blob (file content) ↓Parent Commit ← Another Tree7. What is HEAD and detached HEAD state?
Section titled “7. What is HEAD and detached HEAD state?”Answer:
HEAD: Pointer to the current branch reference (which points to the latest commit)
# Normal HEAD: Points to branchcat .git/HEAD# HEAD points to commit a1b2c3git log -1 --format=%HDetached HEAD: HEAD points directly to a commit, not a branch
# Causes detached HEADgit checkout <commit-sha>git checkout origin/maingit checkout HEAD~3
# Check if detachedgit status# HEAD detached at a1b2c3Detached HEAD Scenario:
Normal: HEAD → main → commit123Detached: HEAD → commit123 (no branch reference)What to do in Detached HEAD:
# Create a branch to save workgit branch temp-branchgit checkout temp-branch# ORgit switch -c new-branch8. Explain the reflog and its uses.
Section titled “8. Explain the reflog and its uses.”Answer:
Reflog (Reference Log) records when branch tips and other references are updated locally.
What Reflog Tracks:
- All branch movements
- Checkouts, commits, resets, merges
- Local-only (not pushed/shared)
Common Reflog Operations:
# View refloggit reflog# a1b2c3 HEAD@{0}: commit: Added feature# d4e5f6 HEAD@{1}: checkout: moving from main to feature# g7h8i9 HEAD@{2}: commit: Fixed bug
# View specific branchgit reflog show main
# Recover lost commit (after hard reset)git reflog # Find the commit SHAgit checkout <lost-commit-sha>git branch recovered-branch
# Recover after accidental resetgit reset --hard HEAD@{2} # Go back to state 2 operations agoRecovery Scenarios:
# Recover deleted branchgit refloggit checkout -b recovered-branch <last-commit-sha>
# Undo a rebasegit refloggit reset --hard HEAD@{1} # Before rebase9. What are Git hooks and how are they used?
Section titled “9. What are Git hooks and how are they used?”Answer:
Git hooks are scripts that run automatically at key points in Git workflow.
Hook Locations: .git/hooks/
Types of Hooks:
Client-side:
# Pre-commit: Before commit creation# Example: Run tests, lint code.git/hooks/pre-commit
# Prepare-commit-msg: Before commit message editor# Example: Add branch name to commit message
# Commit-msg: After message entered# Example: Enforce commit message format
# Post-commit: After commit created# Example: Notify team
# Pre-push: Before pushing# Example: Run tests before pushServer-side:
# Pre-receive: Before push accepted# Example: Enforce code review policy
# Update: Per-branch push validation# Example: Prevent force push to main
# Post-receive: After push# Example: Deploy to stagingExample Pre-commit Hook:
#!/bin/sh# Run testsnpm testif [ $? -ne 0 ]; then echo "Tests failed. Commit aborted." exit 1fi
# Check for debugging statementsif grep -r "console.log" src/; then echo "Found console.log statements. Commit aborted." exit 1fi10. Explain the difference between git fetch and git pull.
Section titled “10. Explain the difference between git fetch and git pull.”Answer:
| Aspect | Git Fetch | Git Pull |
|---|---|---|
| Operation | Downloads remote changes | Downloads AND merges |
| Safety | Safe, doesn’t change working directory | Can cause merge conflicts |
| Merge | No automatic merge | Automatic merge (or rebase) |
| Use case | Check what changed before merging | Quick update when no conflicts expected |
Git Fetch:
# Downloads objects and refs from remotegit fetch origin# Updates origin/main, origin/feature, etc.# Does NOT update local branches or working directory
# See what changedgit log main..origin/main
# Then merge manuallygit merge origin/mainGit Pull = Fetch + Merge:
# Fetches and merges in one commandgit pull origin main
# With rebase (cleaner history)git pull --rebase origin main
# Equivalent togit fetch origingit merge origin/mainBest Practice:
# Safer approachgit fetch origingit diff main origin/main # Review changesgit merge origin/main # Merge if satisfied11. What is a merge conflict and how do you resolve it?
Section titled “11. What is a merge conflict and how do you resolve it?”Answer:
A merge conflict occurs when Git cannot automatically reconcile differences between two commits.
When Conflicts Happen:
- Same file modified in different ways
- One branch deleted, other modified
- Binary files modified in both branches
Conflict Markers:
<<<<<<< HEADCurrent branch changes=======Incoming branch changes>>>>>>> feature-branchResolution Steps:
- Identify Conflicts:
git status# both modified: file.txtgit diff # Shows conflicts- Manual Resolution:
# Edit file to resolve conflicts# Remove conflict markers# Keep desired changesvim file.txt- Complete Merge:
git add file.txtgit commit -m "Resolved merge conflict"Conflict Resolution Tools:
# Use mergetoolgit mergetool # Opens configured diff tool (vimdiff, meld, etc.)
# Accept specific versiongit checkout --ours file.txt # Keep current branch versiongit checkout --theirs file.txt # Keep incoming version
# Abort mergegit merge --abort12. Explain Git branching strategies.
Section titled “12. Explain Git branching strategies.”Answer:
1. GitFlow (Classic):
main (production) ← release branches ← develop ← feature branches- main: Production-ready code
- develop: Integration branch
- feature/: New features
- release/: Release preparation
- hotfix/: Emergency fixes
2. GitHub Flow (Simplified):
main ← feature branches (deploy to production after merge)- Single main branch
- Feature branches deploy to production immediately after review
- Simpler, continuous delivery focused
3. GitLab Flow:
main ← staging ← production ← feature branches- Environment branches (staging, production)
- Pre-production verification
- Environment-specific commits allowed
4. Trunk-Based Development:
- Single main branch
- Short-lived feature branches (< 1 day)
- Feature flags for incomplete work
- Continuous integration
Comparison:
| Strategy | Complexity | Release Frequency | Best For |
|---|---|---|---|
| GitFlow | High | Scheduled | Traditional releases |
| GitHub Flow | Low | Continuous | Web applications, SaaS |
| GitLab Flow | Medium | Environment-based | Multi-environment deployments |
| Trunk-Based | Low | Continuous | High-velocity teams |
13. What is cherry-pick and when would you use it?
Section titled “13. What is cherry-pick and when would you use it?”Answer:
Cherry-pick applies specific commits from one branch to another.
Syntax:
git cherry-pick <commit-hash>
# Multiple commitsgit cherry-pick commit1 commit2 commit3
# Range of commitsgit cherry-pick commit1..commit5Use Cases:
1. Apply Hotfix to Multiple Branches:
# On main branchgit commit -m "Critical security fix" # SHA: a1b2c3
# Apply to release branchgit checkout release/v2git cherry-pick a1b2c32. Selectively Bring Features:
# Only bring specific commits from feature branchgit checkout maingit cherry-pick feature-commit1 feature-commit33. Fix Mistaken Commit Branch:
# Commit made on wrong branchgit checkout correct-branchgit cherry-pick <wrong-branch-commit>git checkout wrong-branchgit reset --hard HEAD~1 # Remove from wrong branchCherry-pick Options:
# Edit commit messagegit cherry-pick -e <commit>
# Don't auto-commitgit cherry-pick -n <commit> # Stage changes only
# Continue after conflict resolutiongit cherry-pick --continuegit cherry-pick --abort14. What is git stash and how does it work?
Section titled “14. What is git stash and how does it work?”Answer:
Git stash temporarily saves changes without committing, allowing you to switch contexts.
Basic Stash Operations:
# Save current changesgit stashgit stash push -m "WIP: feature X"
# List stashesgit stash list# stash@{0}: On feature: WIP: feature X# stash@{1}: On main: Testing changes
# Apply latest stash (keeps in stash)git stash apply
# Apply and remove from stashgit stash pop
# Apply specific stashgit stash apply stash@{2}
# Remove stashgit stash drop stash@{1}git stash clear # Remove all stashesStash Variations:
# Stash untracked filesgit stash -ugit stash --include-untracked
# Stash with staging areagit stash --staged
# Create branch from stashgit stash branch new-branch stash@{0}Use Cases:
- Switch to urgent bug fix without committing half-done work
- Test alternative approach without losing current work
- Pull latest changes while having local modifications
15. Explain Git tags and their types.
Section titled “15. Explain Git tags and their types.”Answer:
Tags mark specific points in history (releases, milestones).
Types of Tags:
1. Lightweight Tags:
# Just a pointer to a commitgit tag v1.0.0git tag -l # List tags2. Annotated Tags (Recommended):
# Stored as full objects with metadatagit tag -a v1.0.0 -m "Release version 1.0.0"git tag -a v1.0.0 -m "Release notes" <commit-sha>
# View tag detailsgit show v1.0.0Tag Operations:
# Push tagsgit push origin v1.0.0git push --tags # Push all tags
# Delete tagsgit tag -d v1.0.0 # Localgit push origin --delete v1.0.0 # Remote
# Checkout tag (detached HEAD)git checkout v1.0.0git checkout -b release/v1.0.0 # Create branch from tag
# Sign tags with GPGgit tag -s v1.0.0 -m "Signed release"Semantic Versioning:
- MAJOR.MINOR.PATCH (v1.2.3)
- MAJOR: Breaking changes
- MINOR: New features (backwards compatible)
- PATCH: Bug fixes
16. What’s the difference between git merge –ff-only, –no-ff, and –squash?
Section titled “16. What’s the difference between git merge –ff-only, –no-ff, and –squash?”Answer:
| Option | Behavior | History Result |
|---|---|---|
--ff-only | Only merge if fast-forward possible | Linear, no merge commit |
--no-ff | Always create merge commit | Non-linear with merge commit |
--squash | Combine all commits into one | Single commit, no merge history |
Examples:
Fast-forward (Default):
git merge --ff-only feature# Only merges if feature branch is ahead of main# Results: main → A → B → C (linear)No Fast-forward:
git merge --no-ff feature# Always creates merge commit# Results: main → A → B → C → M (merge commit)# Preserves that work came from branchSquash:
git merge --squash feature# Takes all commits from feature, stages as one change# Results: main → A → B (single commit with combined changes)Use Cases:
--ff-only: Public branches, avoid merge commits--no-ff: Feature branches, preserve branch history--squash: Clean up messy commit history before merging
17. How do you undo the last commit while keeping changes?
Section titled “17. How do you undo the last commit while keeping changes?”Answer:
Methods to Undo Commits:
1. git reset –soft (Keeps changes staged):
# Undo last commit, changes stay in staginggit reset --soft HEAD~1
# Undo last 3 commitsgit reset --soft HEAD~32. git reset –mixed (Unstage but keep in working directory):
# Undo last commit, changes in working directorygit reset HEAD~1# orgit reset --mixed HEAD~13. git reset –hard (Remove commit AND changes - DANGEROUS):
# Undo commit and discard changesgit reset --hard HEAD~14. git revert (Create inverse commit - safe for shared branches):
# Creates new commit that undoes the last commitgit revert HEAD# Keeps history intactComparison:
| Method | Commits Removed | Changes Preserved | Safe for Shared |
|——–|—————–|——————-|—————–|
| reset --soft | Yes | Staged | No |
| reset --mixed | Yes | Working directory | No |
| reset --hard | Yes | Lost | No |
| revert | No (new commit) | N/A | Yes |
18. Explain the purpose of .gitignore.
Section titled “18. Explain the purpose of .gitignore.”Answer:
.gitignore specifies intentionally untracked files that Git should ignore.
Common Patterns:
# Dependenciesnode_modules/vendor/__pycache__/
# Build outputsdist/build/*.exe*.dll
# Environment files.env.env.local.env.production
# IDE files.vscode/.idea/*.swp.DS_Store
# Logs*.lognpm-debug.log*
# OS filesThumbs.dbDesktop.ini
# Pattern syntax*.log # All .log files!important.log # Except important.logbuild/ # Directory build/doc/*.txt # txt files in doc/doc/**/*.txt # txt files in doc and subdirsGlobal .gitignore:
# Set global ignore for personal preferencesgit config --global core.excludesfile ~/.gitignore_globalCheck Ignored Files:
# Show ignored filesgit status --ignored
# Debug why file is ignoredgit check-ignore -v file.txt19. What is git bisect and how does it help debugging?
Section titled “19. What is git bisect and how does it help debugging?”Answer:
Git bisect performs binary search through commit history to find which commit introduced a bug.
Basic Workflow:
# Start bisectgit bisect start
# Mark current commit as bad (has bug)git bisect bad
# Mark known good commit (no bug)git bisect good <commit-sha>
# Git checks out the midpoint, test, mark# If current commit is bad:git bisect bad
# If current commit is good:git bisect good
# Repeat until bug foundAutomated Bisect:
# Run script to test each commitgit bisect run ./test-script.sh
# Script returns:# 0 for good# 1-127 for bad# 125 for skip
# Example test script#!/bin/bash# test.shmake test 2>&1 | grep "FAILED" && exit 1exit 0Bisect with Logs:
# Start with rangegit bisect startgit bisect bad HEADgit bisect good v1.0.0
# Show remaining stepsgit bisect visualizeEnd Bisect:
# Stop bisect sessiongit bisect reset
# Found commit SHA is saved# Commit is now known bug introduction point20. Explain Git submodules and their use cases.
Section titled “20. Explain Git submodules and their use cases.”Answer:
Git submodules allow you to keep a Git repository as a subdirectory of another repository.
Adding Submodules:
# Add submodulegit submodule add https://github.com/user/library.git libs/library
# Commit the .gitmodules filegit commit -m "Added library submodule"
# .gitmodules file[submodule "libs/library"] path = libs/library url = https://github.com/user/library.gitCloning with Submodules:
# Clone including submodulesgit clone --recurse-submodules https://github.com/user/main.git
# Or clone then initgit clone https://github.com/user/main.gitcd maingit submodule update --init --recursiveWorking with Submodules:
# Update all submodules to latestgit submodule update --remote
# Update specific submodulecd libs/librarygit pull origin maincd ../..git add libs/librarygit commit -m "Updated library"
# See submodule statusgit submodule statusCommon Issues:
- Submodule HEAD detached by default
- Forgetting to
--recurse-submodules - Nested submodules complexity
Alternatives:
- Git Subtree (simpler, but more code duplication)
- Package managers (npm, pip, maven)
- Monorepo (all code in one repo)
21. How do you handle large files in Git?
Section titled “21. How do you handle large files in Git?”Answer:
Git LFS (Large File Storage):
# Install Git LFSgit lfs install
# Track large file typesgit lfs track "*.psd"git lfs track "*.zip"git lfs track "assets/*"
# Add .gitattributesgit add .gitattributesgit commit -m "Add LFS tracking"
# Use normallygit add large-file.psdgit commit -m "Add design asset"git pushGit LFS Configuration:
# View tracked filesgit lfs ls-files
# See LFS statusgit lfs status
# Pull LFS filesgit lfs pull
# Migrate existing files to LFSgit lfs migrate import --include="*.psd,*.zip" --everythingAlternatives:
- Git Annex: Manage files without storing in repo
- External Storage: S3, Dropbox with symlinks
- Git Bundle: Archive large repos
Best Practices:
- Never commit large binaries (>10MB) to regular Git
- Use .gitignore for generated files
- Consider if file needs to be versioned at all
22. What are Git aliases and how do you create them?
Section titled “22. What are Git aliases and how do you create them?”Answer:
Git aliases create shortcuts for frequently used commands.
Creating Aliases:
# Simple aliasgit config --global alias.co checkoutgit config --global alias.br branchgit config --global alias.st status
# Complex alias with argumentsgit config --global alias.last 'log -1 HEAD'git config --global alias.unstage 'reset HEAD --'
# With shell commands (using !)git config --global alias.aliases '!git config --get-regexp alias'git config --global alias.tree 'log --graph --oneline --all'Useful Aliases:
# Better loggit 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 changed filesgit config --global alias.changed "diff --name-only"
# Amend commit without changing messagegit config --global alias.amend "commit --amend --no-edit"
# Force push with leasegit config --global alias.fpush "push --force-with-lease"
# List all aliasesgit config --global alias.alias "!git config --get-regexp alias | cut -d. -f2-"
# Remove all local branches merged into maingit config --global alias.cleanup '!git branch --merged main | grep -v "main" | xargs git branch -d'View Aliases:
# List all aliasesgit config --list | grep aliasgit alias # If alias configured23. Explain the difference between git diff and git whatchanged.
Section titled “23. Explain the difference between git diff and git whatchanged.”Answer:
Both show changes, but with different focus and output.
git diff:
- Shows actual changes between states
- Focuses on content differences
- No commit metadata
# Unstaged changesgit diff
# Staged vs last commitgit diff --stagedgit diff --cached
# Between commitsgit diff main..feature
# Specific filegit diff HEAD~2 file.txt
# Word-level diffgit diff --word-diffgit whatchanged (Legacy):
- Shows commit log with diff of each commit
- Equivalent to
git log --raw - Shows file names that changed
# Show commits with changed filesgit whatchanged
# Show only files (no diff)git whatchanged --pretty=oneline --name-onlyModern Alternatives:
# Better than whatchangedgit log --statgit log --name-statusgit log --oneline --graph --decorate
# Show file changesgit log -p # Shows diff in loggit show <commit> # Show one commit with diff24. How do you squash commits before merging?
Section titled “24. How do you squash commits before merging?”Answer:
Squashing combines multiple commits into one, creating cleaner history.
Method 1: Interactive Rebase
# Squash last 3 commitsgit rebase -i HEAD~3
# Editor opens with:pick a1b2c3 First commitpick d4e5f6 Second commitpick g7h8i9 Third commit
# Change to:pick a1b2c3 First commitsquash d4e5f6 Second commitsquash g7h8i9 Third commit# Save and close
# Edit the squashed commit messageMethod 2: Merge with Squash
# Squash all feature branch commits into onegit checkout maingit merge --squash feature-branchgit commit -m "Add feature X"Method 3: Soft Reset
# Reset but keep changesgit reset --soft HEAD~3git commit -m "Combined changes"Squash Options:
- squash (s): Combine with previous, include in commit message
- fixup (f): Combine with previous, discard commit message
- reword (r): Keep commit, edit message
- edit (e): Stop to amend commit
25. What’s the difference between git remote and git origin?
Section titled “25. What’s the difference between git remote and git origin?”Answer:
git remote: Command to manage remote repositories
origin: Default name for the main remote repository
Remote Operations:
# List remotesgit remote -v# origin https://github.com/user/repo.git (fetch)# origin https://github.com/user/repo.git (push)
# Add new remotegit remote add upstream https://github.com/org/repo.git
# Multiple remotesgit remote add production https://git.example.com/app.git
# Remove remotegit remote remove upstream
# Rename remotegit remote rename origin upstream
# Show remote detailsgit remote show originCommon Remote Setup:
# Fork workfloworigin → your fork (user/repo)upstream → original repo (org/repo)
# Multiple environmentsorigin → main repositorystaging → staging serverproduction → production serverRemote URLs:
# HTTPShttps://github.com/user/repo.git
# SSH (recommended)git@github.com:user/repo.git
# Git protocolgit://github.com/user/repo.git26. Explain Git worktrees.
Section titled “26. Explain Git worktrees.”Answer:
Git worktrees allow having multiple working trees attached to the same repository.
Why Worktrees:
- Work on multiple branches simultaneously without switching
- No need for multiple clones
- Share the same Git history
Basic Usage:
# Create new worktreegit worktree add ../project-feature feature-branch
# Create worktree from new branchgit worktree add ../project-hotfix -b hotfix/bug
# List worktreesgit worktree list# /home/user/project abc123 [main]# /home/user/project-feature def456 [feature]
# Remove worktreegit worktree remove ../project-feature
# Prune stale worktree referencesgit worktree pruneUse Cases:
# Simultaneous workcd project/main # Working on feature Acd ../project-feature # Working on feature B
# Hotfix while developinggit worktree add ../hotfix maincd ../hotfix# Make emergency fixgit push origin main
# Code reviewgit worktree add ../review pr-123cd ../reviewgit fetch origin pull/123/head:pr-123git checkout pr-123Benefits vs Multiple Clones:
- Single .git directory (less disk space)
- Shared object database (faster)
- Same references across worktrees
- Easy to switch context
27. What is git rerere (reuse recorded resolution)?
Section titled “27. What is git rerere (reuse recorded resolution)?”Answer:
Rerere (Reuse Recorded Resolution) automatically resolves conflicts the same way you resolved them before.
Enable Rerere:
# Enable globallygit config --global rerere.enabled true
# Enable in current repogit config rerere.enabled trueHow It Works:
- When you resolve a merge conflict, rerere records the resolution
- If the same conflict appears again, rerere applies the saved resolution
- Works for rebases, merges, cherry-picks
Benefits:
- Automates repeated conflict resolution
- Perfect for long-lived branches that regularly rebase
- Saves time in complex workflows
Managing Rerere:
# View recorded resolutionsgit rerere status
# See what rerere will dogit rerere diff
# Forget a resolutiongit rerere forget file.txt
# Clear all recorded resolutionsgit rerere clear
# Rerere cache location.git/rr-cache/Use Case Example:
# Feature branch constantly rebasing on maingit checkout featuregit rebase main# Conflict in config.js - resolve manuallygit add config.jsgit rebase --continue
# Next rebase - same conflict auto-resolved!git rebase main# Conflict auto-resolved using previous resolution28. Explain Git’s garbage collection.
Section titled “28. Explain Git’s garbage collection.”Answer:
Git’s garbage collection (gc) cleans up unreachable objects and optimizes repository.
When Git Collects Garbage:
- After
git gccommand - Automatically during
git push,git pull - When too many loose objects exist
Manual Garbage Collection:
# Run garbage collectiongit gc
# Aggressive optimization (slower, better compression)git gc --aggressive
# Prune older unreachable objectsgit gc --prune=now
# Just prune (no recompression)git pruneWhat Git Cleans:
- Unreachable commits (after rebase, reset)
- Dangling blobs and trees
- Pack loose objects into packfiles
- Optimize packfile indexing
Check Repository Size:
# Repository sizedu -sh .git
# Count objectsgit count-objects -v
# List large filesgit rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | awk '/^blob/ {print substr($0,6)}' | sort --numeric-sort --key=2Prevent Unnecessary Growth:
# Auto-gc configurationgit config --global gc.auto 500 # Run when >500 loose objectsgit config --global gc.autopacklimit 5029. How do you sign commits with GPG?
Section titled “29. How do you sign commits with GPG?”Answer:
GPG signing ensures commit authenticity and integrity.
Setup GPG:
# Generate GPG keygpg --full-generate-key# RSA and RSA, 4096 bits, no expiration
# List keysgpg --list-secret-keys --keyid-format LONG# sec rsa4096/3AA5C34371567BD2 2024-01-01 [SC]# uid John Doe <john@example.com>
# Configure Gitgit config --global user.signingkey 3AA5C34371567BD2git config --global commit.gpgsign trueSigning Commits:
# Sign commitgit commit -S -m "Signed commit"
# Sign with specific keygit commit -S --gpg-sign=3AA5C34371567BD2 -m "Message"
# Sign tagsgit tag -s v1.0.0 -m "Release"git tag -v v1.0.0 # Verify tagConfigure GPG for Different Environments:
# Git config for specific repogit config commit.gpgsign true
# Export public keygpg --export --armor 3AA5C34371567BD2# Share on GitHub: Settings → SSH and GPG keys
# Verify commitgit log --show-signature -1git verify-commit <commit-sha>Troubleshooting:
# GPG not foundexport GPG_TTY=$(tty)
# Agent issuesgpgconf --kill gpg-agentgpg-agent --daemon
# Use different programgit config --global gpg.program gpg230. Explain Git’s internal directory structure.
Section titled “30. Explain Git’s internal directory structure.”Answer:
The .git directory contains everything Git needs to manage a repository.
Core Directory Structure:
.git/├── HEAD # Current branch reference├── config # Repository-specific settings├── description # Repository description├── hooks/ # Client-side hook scripts├── index # Staging area (binary)├── info/ # Additional info, exclude file├── logs/ # Reflog data│ ├── HEAD│ └── refs/├── objects/ # All Git objects│ ├── info/│ ├── pack/ # Packed objects│ └── ab/ # Object storage (first 2 chars)│ └── cdef123...├── refs/ # References (branches, tags)│ ├── heads/ # Local branches│ │ ├── main│ │ └── feature│ ├── remotes/ # Remote tracking branches│ │ └── origin/│ │ ├── HEAD│ │ └── main│ └── tags/ # Tags└── packed-refs # Compressed referencesImportant Files Explained:
# HEAD - Current branchcat .git/HEAD# Config - Repository settingscat .git/config[core] repositoryformatversion = 0 filemode = true[remote "origin"] url = https://github.com/user/repo.git fetch = +refs/heads/*:refs/remotes/origin/*
# Index - Staging area (binary)git ls-files --stage# 100644 a1b2c3... 0 file.txt
# Reflogcat .git/logs/HEAD# a1b2c3... d4e5f6... John Doe <john@example.com> 1645632000 +0000 commit: Add featureObject Storage:
# Objects stored asobjects/ab/cdef123... # SHA-1: abcdef123...# Each object is compressed with zlibPart 2: 20 Scenario-Based Questions with Answers
Section titled “Part 2: 20 Scenario-Based Questions with Answers”1. Scenario: You accidentally committed to main instead of feature branch
Section titled “1. Scenario: You accidentally committed to main instead of feature branch”Situation: You made several commits directly to main instead of creating a feature branch.
Solution:
# 1. Create feature branch from current stategit checkout -b feature/actual-work# All commits now on feature branch
# 2. Reset main back to before the commitsgit checkout maingit reset --hard HEAD~3 # Reset to 3 commits before
# 3. Push changes (if already pushed)git push origin main --force-with-leasegit push origin feature/actual-work
# Alternative: If commits are already pushedgit revert HEAD~3..HEAD # Creates inverse commitsgit checkout -b feature/actual-work2. Scenario: You lost work after a hard reset
Section titled “2. Scenario: You lost work after a hard reset”Situation: You performed git reset --hard HEAD~5 and lost recent work.
Recovery with Reflog:
# 1. Find lost commitsgit reflog# a1b2c3 HEAD@{0}: reset: moving to HEAD~5# d4e5f6 HEAD@{1}: commit: Important feature# g7h8i9 HEAD@{2}: commit: More work
# 2. Recover the lost commitsgit checkout -b recovered-work d4e5f6# ORgit branch recovered-work d4e5f6
# 3. Merge back to current branchgit checkout maingit merge recovered-work3. Scenario: Merge conflict during long-running feature rebase
Section titled “3. Scenario: Merge conflict during long-running feature rebase”Situation: You’re rebasing a feature branch with 50 commits and hit a merge conflict.
Handling Conflicts:
# During rebase, conflict occursgit status# You are currently rebasing branch 'feature'# Unmerged paths: both modified: config.js
# 1. Resolve conflict manuallyvim config.js # Remove conflict markers
# 2. Stage resolved filegit add config.js
# 3. Continue rebasegit rebase --continue
# If you want to abort rebasegit rebase --abort
# Skip current commitgit rebase --skip4. Scenario: Need to revert a merge commit
Section titled “4. Scenario: Need to revert a merge commit”Situation: A merge commit was pushed to main and needs to be undone.
Solution:
# 1. Identify merge commitgit log --oneline --graph# * a1b2c3 Merge branch 'feature'# |\# | * d4e5f6 Feature commit
# 2. Revert the merge (need -m flag)git revert -m 1 a1b2c3# -m 1 keeps main branch's changes# Creates revert commit
# 3. If you want to revert later againgit revert -m 1 a1b2c3 --no-commitgit commit -m "Revert merge temporarily"
# Later to re-introduce:git revert <revert-commit-sha>5. Scenario: Large repository is slow to clone
Section titled “5. Scenario: Large repository is slow to clone”Situation: Your repository has grown to 2GB, making clones slow.
Solutions:
1. Shallow Clone:
# Clone only recent historygit clone --depth 1 https://github.com/user/repo.git# Only latest commit (much faster)
# Clone with specific depthgit clone --depth 50 https://github.com/user/repo.git2. Partial Clone:
# Clone without blobs (file contents)git clone --filter=blob:none https://github.com/user/repo.git
# Fetch blobs on demandgit checkout file.txt # Downloads blob automatically3. Sparse Checkout:
git clone --filter=blob:none --sparse https://github.com/user/repo.gitcd repogit sparse-checkout set src/ docs/6. Scenario: Commit message needs editing after push
Section titled “6. Scenario: Commit message needs editing after push”Situation: You pushed a commit with a typo in the message.
Solution:
# If it's the latest commitgit commit --amend -m "Corrected commit message"git push --force-with-lease origin main
# If it's older commitgit rebase -i HEAD~5 # Include the commit# Change 'pick' to 'reword' for that commit# Save and edit messagegit push --force-with-lease origin main
# If other developers pulled, coordinate first!7. Scenario: Need to find which commit introduced a bug
Section titled “7. Scenario: Need to find which commit introduced a bug”Situation: A bug appeared in production, and you need to find when it was introduced.
Bisect Solution:
# 1. Start bisectgit bisect start
# 2. Mark current (broken) version as badgit bisect bad HEAD
# 3. Mark known good versiongit bisect good v1.0.0
# 4. Test each checkpoint# Git checks out a commit, you test# If bug exists:git bisect bad# If bug doesn't exist:git bisect good
# 5. When found, Git shows the culprit# commit a1b2c3 is the first bad commitgit bisect reset8. Scenario: Working on multiple features simultaneously
Section titled “8. Scenario: Working on multiple features simultaneously”Situation: You need to switch between feature A and feature B frequently.
Solution with Worktrees:
# Create separate worktrees for each featuregit worktree add ../project-feature-a feature-agit worktree add ../project-feature-b feature-b
# Work on each in separate terminalscd ../project-feature-a # Feature A workcd ../project-feature-b # Feature B work
# Or use stashgit stash push -m "WIP feature A"git checkout feature-b# Work on feature Bgit stash pop9. Scenario: Accidentally committed sensitive data
Section titled “9. Scenario: Accidentally committed sensitive data”Situation: You committed API keys, passwords, or other secrets.
Immediate Actions:
# 1. If not pushed yetgit reset --soft HEAD~1 # Undo commit but keep changesgit reset HEAD file-with-secrets.txt # Unstage sensitive fileecho "file-with-secrets.txt" >> .gitignoregit add .gitignoregit commit -m "Add .gitignore"
# 2. If pushedgit filter-branch --force --index-filter \ "git rm --cached --ignore-unmatch file-with-secrets.txt" \ --prune-empty --tag-name-filter cat -- --all
# Or use BFG Repo-Cleanerjava -jar bfg.jar --delete-files file-with-secrets.txt repo.git
# Force pushgit push origin --force --all
# 3. CRITICAL: Rotate compromised secrets immediately!10. Scenario: Merge is too complex, need to start over
Section titled “10. Scenario: Merge is too complex, need to start over”Situation: A merge has too many conflicts, and you want to start fresh.
Solutions:
# 1. Abort mergegit merge --abort
# 2. Try alternative strategygit merge --strategy-option theirs feature # Accept their changesgit merge --strategy-option ours feature # Accept our changes
# 3. Manual merge with strategygit merge -s recursive -X theirs feature
# 4. Or do a squash mergegit merge --squash feature# Manually resolve, then commit as one11. Scenario: Need to apply hotfix to multiple branches
Section titled “11. Scenario: Need to apply hotfix to multiple branches”Situation: A critical bug fix needs to be applied to main, release/v1, and release/v2.
Cherry-pick Solution:
# 1. Fix on maingit checkout maingit commit -m "Critical security fix" # SHA: a1b2c3
# 2. Apply to other branchesgit checkout release/v1git cherry-pick a1b2c3git push origin release/v1
git checkout release/v2git cherry-pick a1b2c3git push origin release/v2
# 3. Tag the fixgit tag -a v1.0.1 -m "Security patch"git tag -a v2.0.1 -m "Security patch"12. Scenario: Team wants to enforce commit message format
Section titled “12. Scenario: Team wants to enforce commit message format”Situation: You need to enforce conventional commits (feat:, fix:, docs:, etc.)
Hook Solution:
#!/bin/bash# Enforce conventional commits
commit_regex='^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .{1,100}'if !grep -qE "$commit_regex" "$1"; then echo "ERROR: Commit message must follow format:" echo "type(scope): description" echo "Example: feat(auth): add login functionality" exit 1fi
# Make executablechmod +x .git/hooks/commit-msg13. Scenario: Need to split a large commit into smaller ones
Section titled “13. Scenario: Need to split a large commit into smaller ones”Situation: You made a commit with multiple unrelated changes that should be separate.
Solution:
# 1. Reset to before the commit (changes stay)git reset HEAD~1
# 2. Stage and commit in logical groupsgit add file1.txt file2.txtgit commit -m "feat: add feature A"
git add file3.txtgit commit -m "fix: bug in module B"
git add docs/*.mdgit commit -m "docs: update documentation"
# 3. If already pushedgit push --force-with-lease origin branch14. Scenario: Collaborate on a feature with a team
Section titled “14. Scenario: Collaborate on a feature with a team”Situation: Multiple developers working on same feature branch.
Workflow:
# Daily workflow# 1. Start day with latest changesgit checkout featuregit pull --rebase origin main # Rebase on latest maingit pull --rebase origin feature # Get team changes
# 2. Make changes, commit locallygit commit -m "feat: part of feature"
# 3. Push changesgit push origin feature
# 4. If push rejected (someone pushed)git fetch origingit rebase origin/featuregit push origin feature
# Use --force-with-lease (never --force)git push --force-with-lease origin feature15. Scenario: Remove large file from history
Section titled “15. Scenario: Remove large file from history”Situation: A large binary file was committed and now bloats the repo.
BFG Repo-Cleaner:
# 1. Clone with --mirrorgit clone --mirror git://example.com/repo.git
# 2. Remove filejava -jar bfg.jar --delete-files large-file.zip repo.git
# 3. Clean upcd repo.gitgit reflog expire --expire=now --all && git gc --prune=now --aggressive
# 4. Push backgit push16. Scenario: Deploy specific commit without merging
Section titled “16. Scenario: Deploy specific commit without merging”Situation: Need to deploy a specific commit to production without merging the branch.
Solution:
# 1. Create temporary branchgit checkout -b deploy-temp <commit-sha>
# 2. Deploy from this branchgit push origin deploy-temp
# 3. After deployment, delete branchgit checkout maingit branch -d deploy-tempgit push origin --delete deploy-temp
# Or use tagsgit tag deploy-$(date +%s) <commit-sha>git push origin deploy-*# Deploy from tag17. Scenario: Fix merge conflict in binary files
Section titled “17. Scenario: Fix merge conflict in binary files”Situation: Binary files (images, PDFs) have merge conflicts.
Solutions:
# 1. Choose one versiongit checkout --ours image.pnggit checkout --theirs document.pdf
# 2. For conflict in image:git checkout --ours image.pnggit add image.pnggit commit -m "Resolved conflict using our version"
# 3. For merge conflict, specify strategygit merge -X ours feature # Always use our versiongit merge -X theirs feature # Always use their version
# 4. Git LFS helps track binary filesgit lfs track "*.png"git lfs track "*.psd"18. Scenario: Need to see who changed a line
Section titled “18. Scenario: Need to see who changed a line”Situation: You need to find who introduced a specific line of code.
Blame Solution:
# 1. Basic blamegit blame file.txt# a1b2c3 (John Doe 2024-01-01) line content
# 2. Show more contextgit blame -L 50,60 file.txt # Lines 50-60
# 3. Show previous commitsgit blame -w file.txt # Ignore whitespacegit blame -M file.txt # Detect moved linesgit blame -C file.txt # Detect copied lines
# 4. Show commits affecting filegit log -p file.txt19. Scenario: Sync fork with upstream
Section titled “19. Scenario: Sync fork with upstream”Situation: Your fork is behind the original repository.
Solution:
# 1. Add upstream remote (once)git remote add upstream https://github.com/original/repo.git
# 2. Fetch upstream changesgit fetch upstream
# 3. Update local maingit checkout maingit rebase upstream/main# ORgit merge upstream/main
# 4. Push to forkgit push origin main
# 5. For feature branchgit checkout featuregit rebase main # Now includes upstream changes20. Scenario: Debug why merge conflict occurred
Section titled “20. Scenario: Debug why merge conflict occurred”Situation: Need to understand how a merge conflict happened.
Investigation:
# 1. See merge basegit merge-base main feature
# 2. See what changed on each branchgit log --oneline --graph main...feature
# 3. Compare versionsgit diff main...feature file.txt
# 4. See who made conflicting changesgit log -p main..feature -- file.txtgit log -p feature..main -- file.txt
# 5. Visualize with toolsgit mergetool # Opens diff toolgit difftool main feature -- file.txt
# 6. Use git log to find when changes introducedgit log -S"conflicting text" --source --allBonus: Git Command Quick Reference
Section titled “Bonus: Git Command Quick Reference”Configuration Commands
Section titled “Configuration Commands”git config --global user.name "John Doe"git config --global user.email "john@example.com"git config --global core.editor "vim"git config --global color.ui autogit config --listBasic Workflow Commands
Section titled “Basic Workflow Commands”git initgit clone <url>git add <file>git commit -m "message"git pushgit pullgit fetchgit statusgit loggit diffBranching Commands
Section titled “Branching Commands”git branchgit branch <name>git branch -d <name>git checkout <branch>git checkout -b <branch>git merge <branch>git rebase <branch>Undoing Changes
Section titled “Undoing Changes”git reset HEAD~1git reset --hard HEAD~1git revert HEADgit checkout -- <file>git restore <file>git restore --staged <file>Remote Operations
Section titled “Remote Operations”git remote -vgit remote add <name> <url>git remote remove <name>git push -u origin <branch>git push --force-with-leasegit pull --rebaseStashing
Section titled “Stashing”git stashgit stash listgit stash popgit stash applygit stash dropgit stash branch <branch>Logging and Debugging
Section titled “Logging and Debugging”git log --oneline --graph --allgit log -pgit log --statgit diff --stagedgit blame <file>git bisect startgit reflogAdvanced Operations
Section titled “Advanced Operations”git cherry-pick <commit>git rebase -i HEAD~5git tag -a v1.0 -m "Release"git worktree add <path> <branch>git submodule add <url>git filter-branch --tree-filterThis comprehensive guide covers Git fundamentals, internal architecture, core workflows, and practical scenarios that will help you succeed in Git interviews and real-world version control challenges.