Skip to content

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):

AspectGit (DVCS)Centralized VCS (SVN)
RepositoryComplete copy on every developer’s machineSingle central repository
Working offlineFull commit history available offlineCannot commit without network
BranchingCheap, fast, easyExpensive, complex
PerformanceLocal operations are instantMost operations require network
BackupEvery clone is a full backupSingle 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 Committed

Practical Example:

Terminal window
# Working Directory: Edit file
echo "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:

Terminal window
tree 4a2b3c... # Tree object representing directory structure
parent d6e8f9... # Parent commit(s) SHA (multiple for merges)
author John Doe <john@example.com> 1645632000 -0500
committer John Doe <john@example.com> 1645632000 -0500
gpgsig -----BEGIN PGP SIGNATURE-----
...
-----END PGP SIGNATURE-----
Commit message describing changes

Components:

  • 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:

Terminal window
# See commit object
git cat-file -p <commit-sha>
# See commit tree
git ls-tree <commit-sha>
# Detailed log
git log --pretty=raw -1

4. 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
Terminal window
git checkout main
git 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)
Terminal window
git checkout feature
git rebase main
# Feature branch now starts from main's latest commit

Visual 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:

AspectGit ResetGit Revert
OperationMoves branch pointerCreates new commit that undoes changes
HistoryRewrites/removes historyPreserves history with undo record
SafetyDangerous (can lose commits)Safe for shared branches
Use caseLocal undo, removing commitsUndo public/shared commits

Git Reset (Three Modes):

Terminal window
# Soft: Moves HEAD only (changes staged)
git reset --soft HEAD~1
# HEAD moved, changes remain in staging
# Mixed (default): Moves HEAD, unstages changes
git reset HEAD~1
# HEAD moved, changes in working directory
# Hard: Moves HEAD, discards all changes
git reset --hard HEAD~1
# HEAD moved, changes lost completely

Git Revert (Safe for Public):

Terminal window
# Creates new commit that undoes the specified commit
git revert HEAD~2
# Creates commit: "Revert 'Previous commit message'"

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/
Terminal window
# Create a blob
echo "content" | git hash-object -w --stdin
# View blob
git cat-file -p <blob-sha>

2. Tree:

  • Directory structure
  • Contains blob SHAs and other tree SHAs
  • Equivalent to a folder
Terminal window
# View tree
git cat-file -p <tree-sha>
# 100644 blob a1b2c3... file.txt
# 040000 tree d4e5f6... subdir

3. 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:

Terminal window
# Objects are compressed and stored in
.git/objects/ab/cdef123456789... # First 2 chars = directory

Object Relationships:

Commit ← Tree ← Blob (file content)
Parent Commit ← Another Tree

Answer:

HEAD: Pointer to the current branch reference (which points to the latest commit)

refs/heads/main
# Normal HEAD: Points to branch
cat .git/HEAD
# HEAD points to commit a1b2c3
git log -1 --format=%H

Detached HEAD: HEAD points directly to a commit, not a branch

Terminal window
# Causes detached HEAD
git checkout <commit-sha>
git checkout origin/main
git checkout HEAD~3
# Check if detached
git status
# HEAD detached at a1b2c3

Detached HEAD Scenario:

Normal: HEAD → main → commit123
Detached: HEAD → commit123 (no branch reference)

What to do in Detached HEAD:

Terminal window
# Create a branch to save work
git branch temp-branch
git checkout temp-branch
# OR
git switch -c new-branch

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:

Terminal window
# View reflog
git reflog
# a1b2c3 HEAD@{0}: commit: Added feature
# d4e5f6 HEAD@{1}: checkout: moving from main to feature
# g7h8i9 HEAD@{2}: commit: Fixed bug
# View specific branch
git reflog show main
# Recover lost commit (after hard reset)
git reflog # Find the commit SHA
git checkout <lost-commit-sha>
git branch recovered-branch
# Recover after accidental reset
git reset --hard HEAD@{2} # Go back to state 2 operations ago

Recovery Scenarios:

Terminal window
# Recover deleted branch
git reflog
git checkout -b recovered-branch <last-commit-sha>
# Undo a rebase
git reflog
git reset --hard HEAD@{1} # Before rebase

9. 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:

Terminal window
# 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 push

Server-side:

Terminal window
# 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 staging

Example Pre-commit Hook:

.git/hooks/pre-commit
#!/bin/sh
# Run tests
npm test
if [ $? -ne 0 ]; then
echo "Tests failed. Commit aborted."
exit 1
fi
# Check for debugging statements
if grep -r "console.log" src/; then
echo "Found console.log statements. Commit aborted."
exit 1
fi

10. Explain the difference between git fetch and git pull.

Section titled “10. Explain the difference between git fetch and git pull.”

Answer:

AspectGit FetchGit Pull
OperationDownloads remote changesDownloads AND merges
SafetySafe, doesn’t change working directoryCan cause merge conflicts
MergeNo automatic mergeAutomatic merge (or rebase)
Use caseCheck what changed before mergingQuick update when no conflicts expected

Git Fetch:

Terminal window
# Downloads objects and refs from remote
git fetch origin
# Updates origin/main, origin/feature, etc.
# Does NOT update local branches or working directory
# See what changed
git log main..origin/main
# Then merge manually
git merge origin/main

Git Pull = Fetch + Merge:

Terminal window
# Fetches and merges in one command
git pull origin main
# With rebase (cleaner history)
git pull --rebase origin main
# Equivalent to
git fetch origin
git merge origin/main

Best Practice:

Terminal window
# Safer approach
git fetch origin
git diff main origin/main # Review changes
git merge origin/main # Merge if satisfied

11. 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:

Terminal window
<<<<<<< HEAD
Current branch changes
=======
Incoming branch changes
>>>>>>> feature-branch

Resolution Steps:

  1. Identify Conflicts:
Terminal window
git status
# both modified: file.txt
git diff # Shows conflicts
  1. Manual Resolution:
Terminal window
# Edit file to resolve conflicts
# Remove conflict markers
# Keep desired changes
vim file.txt
  1. Complete Merge:
Terminal window
git add file.txt
git commit -m "Resolved merge conflict"

Conflict Resolution Tools:

Terminal window
# Use mergetool
git mergetool # Opens configured diff tool (vimdiff, meld, etc.)
# Accept specific version
git checkout --ours file.txt # Keep current branch version
git checkout --theirs file.txt # Keep incoming version
# Abort merge
git merge --abort

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:

StrategyComplexityRelease FrequencyBest For
GitFlowHighScheduledTraditional releases
GitHub FlowLowContinuousWeb applications, SaaS
GitLab FlowMediumEnvironment-basedMulti-environment deployments
Trunk-BasedLowContinuousHigh-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:

Terminal window
git cherry-pick <commit-hash>
# Multiple commits
git cherry-pick commit1 commit2 commit3
# Range of commits
git cherry-pick commit1..commit5

Use Cases:

1. Apply Hotfix to Multiple Branches:

Terminal window
# On main branch
git commit -m "Critical security fix" # SHA: a1b2c3
# Apply to release branch
git checkout release/v2
git cherry-pick a1b2c3

2. Selectively Bring Features:

Terminal window
# Only bring specific commits from feature branch
git checkout main
git cherry-pick feature-commit1 feature-commit3

3. Fix Mistaken Commit Branch:

Terminal window
# Commit made on wrong branch
git checkout correct-branch
git cherry-pick <wrong-branch-commit>
git checkout wrong-branch
git reset --hard HEAD~1 # Remove from wrong branch

Cherry-pick Options:

Terminal window
# Edit commit message
git cherry-pick -e <commit>
# Don't auto-commit
git cherry-pick -n <commit> # Stage changes only
# Continue after conflict resolution
git cherry-pick --continue
git cherry-pick --abort

14. 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:

Terminal window
# Save current changes
git stash
git stash push -m "WIP: feature X"
# List stashes
git 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 stash
git stash pop
# Apply specific stash
git stash apply stash@{2}
# Remove stash
git stash drop stash@{1}
git stash clear # Remove all stashes

Stash Variations:

Terminal window
# Stash untracked files
git stash -u
git stash --include-untracked
# Stash with staging area
git stash --staged
# Create branch from stash
git 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

Answer:

Tags mark specific points in history (releases, milestones).

Types of Tags:

1. Lightweight Tags:

Terminal window
# Just a pointer to a commit
git tag v1.0.0
git tag -l # List tags

2. Annotated Tags (Recommended):

Terminal window
# Stored as full objects with metadata
git tag -a v1.0.0 -m "Release version 1.0.0"
git tag -a v1.0.0 -m "Release notes" <commit-sha>
# View tag details
git show v1.0.0

Tag Operations:

Terminal window
# Push tags
git push origin v1.0.0
git push --tags # Push all tags
# Delete tags
git tag -d v1.0.0 # Local
git push origin --delete v1.0.0 # Remote
# Checkout tag (detached HEAD)
git checkout v1.0.0
git checkout -b release/v1.0.0 # Create branch from tag
# Sign tags with GPG
git 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:

OptionBehaviorHistory Result
--ff-onlyOnly merge if fast-forward possibleLinear, no merge commit
--no-ffAlways create merge commitNon-linear with merge commit
--squashCombine all commits into oneSingle commit, no merge history

Examples:

Fast-forward (Default):

Terminal window
git merge --ff-only feature
# Only merges if feature branch is ahead of main
# Results: main → A → B → C (linear)

No Fast-forward:

Terminal window
git merge --no-ff feature
# Always creates merge commit
# Results: main → A → B → C → M (merge commit)
# Preserves that work came from branch

Squash:

Terminal window
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):

Terminal window
# Undo last commit, changes stay in staging
git reset --soft HEAD~1
# Undo last 3 commits
git reset --soft HEAD~3

2. git reset –mixed (Unstage but keep in working directory):

Terminal window
# Undo last commit, changes in working directory
git reset HEAD~1
# or
git reset --mixed HEAD~1

3. git reset –hard (Remove commit AND changes - DANGEROUS):

Terminal window
# Undo commit and discard changes
git reset --hard HEAD~1

4. git revert (Create inverse commit - safe for shared branches):

Terminal window
# Creates new commit that undoes the last commit
git revert HEAD
# Keeps history intact

Comparison: | 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 |


Answer:

.gitignore specifies intentionally untracked files that Git should ignore.

Common Patterns:

.gitignore
# Dependencies
node_modules/
vendor/
__pycache__/
# Build outputs
dist/
build/
*.exe
*.dll
# Environment files
.env
.env.local
.env.production
# IDE files
.vscode/
.idea/
*.swp
.DS_Store
# Logs
*.log
npm-debug.log*
# OS files
Thumbs.db
Desktop.ini
# Pattern syntax
*.log # All .log files
!important.log # Except important.log
build/ # Directory build/
doc/*.txt # txt files in doc/
doc/**/*.txt # txt files in doc and subdirs

Global .gitignore:

Terminal window
# Set global ignore for personal preferences
git config --global core.excludesfile ~/.gitignore_global

Check Ignored Files:

Terminal window
# Show ignored files
git status --ignored
# Debug why file is ignored
git check-ignore -v file.txt

19. 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:

Terminal window
# Start bisect
git 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 found

Automated Bisect:

Terminal window
# Run script to test each commit
git bisect run ./test-script.sh
# Script returns:
# 0 for good
# 1-127 for bad
# 125 for skip
# Example test script
#!/bin/bash
# test.sh
make test 2>&1 | grep "FAILED" && exit 1
exit 0

Bisect with Logs:

Terminal window
# Start with range
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
# Show remaining steps
git bisect visualize

End Bisect:

Terminal window
# Stop bisect session
git bisect reset
# Found commit SHA is saved
# Commit is now known bug introduction point

20. 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:

Terminal window
# Add submodule
git submodule add https://github.com/user/library.git libs/library
# Commit the .gitmodules file
git commit -m "Added library submodule"
# .gitmodules file
[submodule "libs/library"]
path = libs/library
url = https://github.com/user/library.git

Cloning with Submodules:

Terminal window
# Clone including submodules
git clone --recurse-submodules https://github.com/user/main.git
# Or clone then init
git clone https://github.com/user/main.git
cd main
git submodule update --init --recursive

Working with Submodules:

Terminal window
# Update all submodules to latest
git submodule update --remote
# Update specific submodule
cd libs/library
git pull origin main
cd ../..
git add libs/library
git commit -m "Updated library"
# See submodule status
git submodule status

Common 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)

Answer:

Git LFS (Large File Storage):

Terminal window
# Install Git LFS
git lfs install
# Track large file types
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "assets/*"
# Add .gitattributes
git add .gitattributes
git commit -m "Add LFS tracking"
# Use normally
git add large-file.psd
git commit -m "Add design asset"
git push

Git LFS Configuration:

Terminal window
# View tracked files
git lfs ls-files
# See LFS status
git lfs status
# Pull LFS files
git lfs pull
# Migrate existing files to LFS
git lfs migrate import --include="*.psd,*.zip" --everything

Alternatives:

  • 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:

Terminal window
# Simple alias
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.st status
# Complex alias with arguments
git 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:

Terminal window
# Better log
git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
# Show changed files
git config --global alias.changed "diff --name-only"
# Amend commit without changing message
git config --global alias.amend "commit --amend --no-edit"
# Force push with lease
git config --global alias.fpush "push --force-with-lease"
# List all aliases
git config --global alias.alias "!git config --get-regexp alias | cut -d. -f2-"
# Remove all local branches merged into main
git config --global alias.cleanup '!git branch --merged main | grep -v "main" | xargs git branch -d'

View Aliases:

Terminal window
# List all aliases
git config --list | grep alias
git alias # If alias configured

23. 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
Terminal window
# Unstaged changes
git diff
# Staged vs last commit
git diff --staged
git diff --cached
# Between commits
git diff main..feature
# Specific file
git diff HEAD~2 file.txt
# Word-level diff
git diff --word-diff

git whatchanged (Legacy):

  • Shows commit log with diff of each commit
  • Equivalent to git log --raw
  • Shows file names that changed
Terminal window
# Show commits with changed files
git whatchanged
# Show only files (no diff)
git whatchanged --pretty=oneline --name-only

Modern Alternatives:

Terminal window
# Better than whatchanged
git log --stat
git log --name-status
git log --oneline --graph --decorate
# Show file changes
git log -p # Shows diff in log
git show <commit> # Show one commit with diff

24. 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

Terminal window
# Squash last 3 commits
git rebase -i HEAD~3
# Editor opens with:
pick a1b2c3 First commit
pick d4e5f6 Second commit
pick g7h8i9 Third commit
# Change to:
pick a1b2c3 First commit
squash d4e5f6 Second commit
squash g7h8i9 Third commit
# Save and close
# Edit the squashed commit message

Method 2: Merge with Squash

Terminal window
# Squash all feature branch commits into one
git checkout main
git merge --squash feature-branch
git commit -m "Add feature X"

Method 3: Soft Reset

Terminal window
# Reset but keep changes
git reset --soft HEAD~3
git 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:

Terminal window
# List remotes
git remote -v
# origin https://github.com/user/repo.git (fetch)
# origin https://github.com/user/repo.git (push)
# Add new remote
git remote add upstream https://github.com/org/repo.git
# Multiple remotes
git remote add production https://git.example.com/app.git
# Remove remote
git remote remove upstream
# Rename remote
git remote rename origin upstream
# Show remote details
git remote show origin

Common Remote Setup:

Terminal window
# Fork workflow
origin your fork (user/repo)
upstream original repo (org/repo)
# Multiple environments
origin main repository
staging staging server
production production server

Remote URLs:

Terminal window
# HTTPS
https://github.com/user/repo.git
# SSH (recommended)
git@github.com:user/repo.git
# Git protocol
git://github.com/user/repo.git

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:

Terminal window
# Create new worktree
git worktree add ../project-feature feature-branch
# Create worktree from new branch
git worktree add ../project-hotfix -b hotfix/bug
# List worktrees
git worktree list
# /home/user/project abc123 [main]
# /home/user/project-feature def456 [feature]
# Remove worktree
git worktree remove ../project-feature
# Prune stale worktree references
git worktree prune

Use Cases:

Terminal window
# Simultaneous work
cd project/main # Working on feature A
cd ../project-feature # Working on feature B
# Hotfix while developing
git worktree add ../hotfix main
cd ../hotfix
# Make emergency fix
git push origin main
# Code review
git worktree add ../review pr-123
cd ../review
git fetch origin pull/123/head:pr-123
git checkout pr-123

Benefits 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:

Terminal window
# Enable globally
git config --global rerere.enabled true
# Enable in current repo
git config rerere.enabled true

How It Works:

  1. When you resolve a merge conflict, rerere records the resolution
  2. If the same conflict appears again, rerere applies the saved resolution
  3. 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:

Terminal window
# View recorded resolutions
git rerere status
# See what rerere will do
git rerere diff
# Forget a resolution
git rerere forget file.txt
# Clear all recorded resolutions
git rerere clear
# Rerere cache location
.git/rr-cache/

Use Case Example:

Terminal window
# Feature branch constantly rebasing on main
git checkout feature
git rebase main
# Conflict in config.js - resolve manually
git add config.js
git rebase --continue
# Next rebase - same conflict auto-resolved!
git rebase main
# Conflict auto-resolved using previous resolution

Answer:

Git’s garbage collection (gc) cleans up unreachable objects and optimizes repository.

When Git Collects Garbage:

  • After git gc command
  • Automatically during git push, git pull
  • When too many loose objects exist

Manual Garbage Collection:

Terminal window
# Run garbage collection
git gc
# Aggressive optimization (slower, better compression)
git gc --aggressive
# Prune older unreachable objects
git gc --prune=now
# Just prune (no recompression)
git prune

What Git Cleans:

  • Unreachable commits (after rebase, reset)
  • Dangling blobs and trees
  • Pack loose objects into packfiles
  • Optimize packfile indexing

Check Repository Size:

Terminal window
# Repository size
du -sh .git
# Count objects
git count-objects -v
# List large files
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | awk '/^blob/ {print substr($0,6)}' | sort --numeric-sort --key=2

Prevent Unnecessary Growth:

Terminal window
# Auto-gc configuration
git config --global gc.auto 500 # Run when >500 loose objects
git config --global gc.autopacklimit 50

Answer:

GPG signing ensures commit authenticity and integrity.

Setup GPG:

Terminal window
# Generate GPG key
gpg --full-generate-key
# RSA and RSA, 4096 bits, no expiration
# List keys
gpg --list-secret-keys --keyid-format LONG
# sec rsa4096/3AA5C34371567BD2 2024-01-01 [SC]
# uid John Doe <john@example.com>
# Configure Git
git config --global user.signingkey 3AA5C34371567BD2
git config --global commit.gpgsign true

Signing Commits:

Terminal window
# Sign commit
git commit -S -m "Signed commit"
# Sign with specific key
git commit -S --gpg-sign=3AA5C34371567BD2 -m "Message"
# Sign tags
git tag -s v1.0.0 -m "Release"
git tag -v v1.0.0 # Verify tag

Configure GPG for Different Environments:

Terminal window
# Git config for specific repo
git config commit.gpgsign true
# Export public key
gpg --export --armor 3AA5C34371567BD2
# Share on GitHub: Settings → SSH and GPG keys
# Verify commit
git log --show-signature -1
git verify-commit <commit-sha>

Troubleshooting:

Terminal window
# GPG not found
export GPG_TTY=$(tty)
# Agent issues
gpgconf --kill gpg-agent
gpg-agent --daemon
# Use different program
git config --global gpg.program gpg2

30. 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 references

Important Files Explained:

refs/heads/main
# HEAD - Current branch
cat .git/HEAD
# Config - Repository settings
cat .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
# Reflog
cat .git/logs/HEAD
# a1b2c3... d4e5f6... John Doe <john@example.com> 1645632000 +0000 commit: Add feature

Object Storage:

Terminal window
# Objects stored as
objects/ab/cdef123... # SHA-1: abcdef123...
# Each object is compressed with zlib

Part 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:

Terminal window
# 1. Create feature branch from current state
git checkout -b feature/actual-work
# All commits now on feature branch
# 2. Reset main back to before the commits
git checkout main
git reset --hard HEAD~3 # Reset to 3 commits before
# 3. Push changes (if already pushed)
git push origin main --force-with-lease
git push origin feature/actual-work
# Alternative: If commits are already pushed
git revert HEAD~3..HEAD # Creates inverse commits
git checkout -b feature/actual-work

2. 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:

Terminal window
# 1. Find lost commits
git 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 commits
git checkout -b recovered-work d4e5f6
# OR
git branch recovered-work d4e5f6
# 3. Merge back to current branch
git checkout main
git merge recovered-work

3. 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:

Terminal window
# During rebase, conflict occurs
git status
# You are currently rebasing branch 'feature'
# Unmerged paths: both modified: config.js
# 1. Resolve conflict manually
vim config.js # Remove conflict markers
# 2. Stage resolved file
git add config.js
# 3. Continue rebase
git rebase --continue
# If you want to abort rebase
git rebase --abort
# Skip current commit
git rebase --skip

4. 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:

Terminal window
# 1. Identify merge commit
git 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 again
git revert -m 1 a1b2c3 --no-commit
git 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:

Terminal window
# Clone only recent history
git clone --depth 1 https://github.com/user/repo.git
# Only latest commit (much faster)
# Clone with specific depth
git clone --depth 50 https://github.com/user/repo.git

2. Partial Clone:

Terminal window
# Clone without blobs (file contents)
git clone --filter=blob:none https://github.com/user/repo.git
# Fetch blobs on demand
git checkout file.txt # Downloads blob automatically

3. Sparse Checkout:

Terminal window
git clone --filter=blob:none --sparse https://github.com/user/repo.git
cd repo
git 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:

Terminal window
# If it's the latest commit
git commit --amend -m "Corrected commit message"
git push --force-with-lease origin main
# If it's older commit
git rebase -i HEAD~5 # Include the commit
# Change 'pick' to 'reword' for that commit
# Save and edit message
git 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:

Terminal window
# 1. Start bisect
git bisect start
# 2. Mark current (broken) version as bad
git bisect bad HEAD
# 3. Mark known good version
git 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 commit
git bisect reset

8. 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:

Terminal window
# Create separate worktrees for each feature
git worktree add ../project-feature-a feature-a
git worktree add ../project-feature-b feature-b
# Work on each in separate terminals
cd ../project-feature-a # Feature A work
cd ../project-feature-b # Feature B work
# Or use stash
git stash push -m "WIP feature A"
git checkout feature-b
# Work on feature B
git stash pop

9. Scenario: Accidentally committed sensitive data

Section titled “9. Scenario: Accidentally committed sensitive data”

Situation: You committed API keys, passwords, or other secrets.

Immediate Actions:

Terminal window
# 1. If not pushed yet
git reset --soft HEAD~1 # Undo commit but keep changes
git reset HEAD file-with-secrets.txt # Unstage sensitive file
echo "file-with-secrets.txt" >> .gitignore
git add .gitignore
git commit -m "Add .gitignore"
# 2. If pushed
git 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-Cleaner
java -jar bfg.jar --delete-files file-with-secrets.txt repo.git
# Force push
git 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:

Terminal window
# 1. Abort merge
git merge --abort
# 2. Try alternative strategy
git merge --strategy-option theirs feature # Accept their changes
git merge --strategy-option ours feature # Accept our changes
# 3. Manual merge with strategy
git merge -s recursive -X theirs feature
# 4. Or do a squash merge
git merge --squash feature
# Manually resolve, then commit as one

11. 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:

Terminal window
# 1. Fix on main
git checkout main
git commit -m "Critical security fix" # SHA: a1b2c3
# 2. Apply to other branches
git checkout release/v1
git cherry-pick a1b2c3
git push origin release/v1
git checkout release/v2
git cherry-pick a1b2c3
git push origin release/v2
# 3. Tag the fix
git 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:

.git/hooks/commit-msg
#!/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 1
fi
# Make executable
chmod +x .git/hooks/commit-msg

13. 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:

Terminal window
# 1. Reset to before the commit (changes stay)
git reset HEAD~1
# 2. Stage and commit in logical groups
git add file1.txt file2.txt
git commit -m "feat: add feature A"
git add file3.txt
git commit -m "fix: bug in module B"
git add docs/*.md
git commit -m "docs: update documentation"
# 3. If already pushed
git push --force-with-lease origin branch

14. 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:

Terminal window
# Daily workflow
# 1. Start day with latest changes
git checkout feature
git pull --rebase origin main # Rebase on latest main
git pull --rebase origin feature # Get team changes
# 2. Make changes, commit locally
git commit -m "feat: part of feature"
# 3. Push changes
git push origin feature
# 4. If push rejected (someone pushed)
git fetch origin
git rebase origin/feature
git push origin feature
# Use --force-with-lease (never --force)
git push --force-with-lease origin feature

15. 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:

Terminal window
# 1. Clone with --mirror
git clone --mirror git://example.com/repo.git
# 2. Remove file
java -jar bfg.jar --delete-files large-file.zip repo.git
# 3. Clean up
cd repo.git
git reflog expire --expire=now --all && git gc --prune=now --aggressive
# 4. Push back
git push

16. 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:

Terminal window
# 1. Create temporary branch
git checkout -b deploy-temp <commit-sha>
# 2. Deploy from this branch
git push origin deploy-temp
# 3. After deployment, delete branch
git checkout main
git branch -d deploy-temp
git push origin --delete deploy-temp
# Or use tags
git tag deploy-$(date +%s) <commit-sha>
git push origin deploy-*
# Deploy from tag

17. 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:

Terminal window
# 1. Choose one version
git checkout --ours image.png
git checkout --theirs document.pdf
# 2. For conflict in image:
git checkout --ours image.png
git add image.png
git commit -m "Resolved conflict using our version"
# 3. For merge conflict, specify strategy
git merge -X ours feature # Always use our version
git merge -X theirs feature # Always use their version
# 4. Git LFS helps track binary files
git 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:

Terminal window
# 1. Basic blame
git blame file.txt
# a1b2c3 (John Doe 2024-01-01) line content
# 2. Show more context
git blame -L 50,60 file.txt # Lines 50-60
# 3. Show previous commits
git blame -w file.txt # Ignore whitespace
git blame -M file.txt # Detect moved lines
git blame -C file.txt # Detect copied lines
# 4. Show commits affecting file
git log -p file.txt

Situation: Your fork is behind the original repository.

Solution:

Terminal window
# 1. Add upstream remote (once)
git remote add upstream https://github.com/original/repo.git
# 2. Fetch upstream changes
git fetch upstream
# 3. Update local main
git checkout main
git rebase upstream/main
# OR
git merge upstream/main
# 4. Push to fork
git push origin main
# 5. For feature branch
git checkout feature
git rebase main # Now includes upstream changes

20. 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:

Terminal window
# 1. See merge base
git merge-base main feature
# 2. See what changed on each branch
git log --oneline --graph main...feature
# 3. Compare versions
git diff main...feature file.txt
# 4. See who made conflicting changes
git log -p main..feature -- file.txt
git log -p feature..main -- file.txt
# 5. Visualize with tools
git mergetool # Opens diff tool
git difftool main feature -- file.txt
# 6. Use git log to find when changes introduced
git log -S"conflicting text" --source --all

Terminal window
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 auto
git config --list
Terminal window
git init
git clone <url>
git add <file>
git commit -m "message"
git push
git pull
git fetch
git status
git log
git diff
Terminal window
git branch
git branch <name>
git branch -d <name>
git checkout <branch>
git checkout -b <branch>
git merge <branch>
git rebase <branch>
Terminal window
git reset HEAD~1
git reset --hard HEAD~1
git revert HEAD
git checkout -- <file>
git restore <file>
git restore --staged <file>
Terminal window
git remote -v
git remote add <name> <url>
git remote remove <name>
git push -u origin <branch>
git push --force-with-lease
git pull --rebase
Terminal window
git stash
git stash list
git stash pop
git stash apply
git stash drop
git stash branch <branch>
Terminal window
git log --oneline --graph --all
git log -p
git log --stat
git diff --staged
git blame <file>
git bisect start
git reflog
Terminal window
git cherry-pick <commit>
git rebase -i HEAD~5
git tag -a v1.0 -m "Release"
git worktree add <path> <branch>
git submodule add <url>
git filter-branch --tree-filter

This 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.