Git Interview Questions: Complete Guide with Answers
How to Prepare for Git Interviews
Git interviews test more than just memorized commands. Interviewers want to understand your mental model of how Git works, how you approach problems, and how you handle real-world scenarios. This guide organizes questions by difficulty and topic, with detailed explanations that go beyond simple answers. Each question includes why it's asked, what interviewers look for, and follow-up discussions that might arise.
Interview Strategy: When answering Git questions, don't just recite commands. Explain your thought process, mention alternative approaches, and discuss trade-offs. This demonstrates depth of understanding and real-world experience.
📋 Beginner Level Questions
These questions assess fundamental Git knowledge. Expect these in phone screens or early-round interviews for junior positions.
Answer: Git is a distributed version control system (DVCS) created by Linus Torvalds in 2005. Key differences from centralized systems (like SVN):
- Distributed architecture: Every developer has a complete copy of the repository, including full history. Work continues even without network access.
- Snapshot-based, not file-based: Git stores snapshots of the entire repository at each commit, not file differences. This makes branching and merging faster.
- Strong branching model: Branches are lightweight pointers, encouraging frequent branching workflows.
- Data integrity: Everything is checksummed with SHA-1 hashes before storage, making history tamper-evident.
- Staging area: Git has an index/staging area where you can prepare commits before finalizing them.
Why interviewers ask this: This tests whether you understand Git's fundamental architecture, not just memorized commands. It reveals if you know why Git behaves differently from other VCS tools.
Answer: git fetch downloads new data from the remote repository but does not integrate it into your working files. It updates remote-tracking branches (like origin/main) but leaves your local branches unchanged. git pull is essentially git fetch followed by either git merge or git rebase (depending on configuration). It downloads changes and immediately tries to integrate them into your current branch.
$ git fetch origin
$ git log origin/main # See what changed
# Pull - fetch + integrate
$ git pull origin main # Fetch and merge
$ git pull --rebase # Fetch and rebase
Why this matters: Using fetch before pull lets you review changes before integration, avoiding surprise merges. Senior developers often use fetch first to inspect remote changes.
Answer: A merge conflict occurs when Git cannot automatically reconcile changes from two branches that modified the same part of a file. Git pauses the merge and marks conflicted files with special markers:
This is your current branch's version
=======
This is the incoming branch's version
>>>>>>> feature-branch
Resolution steps:
- Identify conflicted files with
git status - Edit each file to resolve conflicts: choose one version, combine them, or write new code
- Remove the conflict markers (<<<<, ====, >>>>)
- Stage resolved files:
git add [file] - Complete the merge:
git commit(Git generates merge commit message)
You can also use git mergetool to launch a visual merge tool.
Interviewer insight: This tests whether you've actually dealt with conflicts in real work, not just read about them. Follow-up questions might ask about specific conflict scenarios or tools.
Answer: Both integrate changes from one branch into another, but they create different history:
- Merge: Creates a new "merge commit" that has two parents. Preserves the exact history of when branches diverged and were reunited. Shows that parallel development happened.
- Rebase: Takes the commits from your branch and reapplies them on top of another branch, creating new commits with new hashes. Results in a linear history as if the work was done sequentially.
$ git checkout feature
$ git merge main
# Creates: ... A---B---C feature
# \ /
# D---E---F main
# Rebase (linear history)
$ git checkout feature
$ git rebase main
# Creates: ... D---E---F---A'---B'---C' feature
Trade-offs: Merge preserves context but can clutter history. Rebase creates clean history but rewrites commits (dangerous on shared branches).
Answer: There are two main approaches, depending on whether you need to preserve history:
- git revert (safe for shared branches): Creates a new commit that undoes the changes of a previous commit. History remains intact, and everyone can pull safely.
$ git revert a1b2c3d # Creates new commit undoing a1b2c3d
$ git push - git reset + force push (only if you're sure): Rewrites history by removing commits. Dangerous on shared branches because others may have pulled the old commits.
$ git reset --hard HEAD~1 # Remove last commit
$ git push --force-with-lease # Safer than --force
Rule of thumb: On shared branches, use revert. On personal branches that no one else uses, reset is acceptable.
📋 Intermediate Level Questions
Expect these in technical interviews for developer or DevOps roles. They test deeper understanding and practical experience.
Answer: Git is fundamentally a content-addressable filesystem with four object types:
- Blob (Binary Large Object): Stores file content, but not the filename. Identical file content = identical blob hash. Stored as
blob <size>\0<content>. - Tree: Represents a directory. Maps filenames to blobs (or other trees) and includes file modes. Stores directory structure.
- Commit: Points to a tree (snapshot of entire repository at that point). Contains parent commit(s), author/committer info, timestamp, and commit message.
- Tag (annotated): Points to a specific commit, with tagger info and message. Used for marking releases.
$ git cat-file -t a1b2c3d # Shows object type
$ git cat-file -p a1b2c3d # Shows object content
$ git ls-tree HEAD # Shows tree at HEAD
All objects are stored in .git/objects/, identified by SHA-1 hash of their content. This design ensures data integrity and enables Git's efficiency.
Why this matters: Understanding internals helps debug complex issues, recover lost data, and explains why Git behaves the way it does. Senior roles often require this depth.
Answer: The reflog (reference log) records every movement of HEAD and branch tips in your local repository. It's your safety net for recovering "lost" commits.
a1b2c3d HEAD@{0}: reset: moving to HEAD~2
b4c5d6e HEAD@{1}: commit: Add payment feature
e7f8g9h HEAD@{2}: checkout: moving from main to feature
Common use cases:
- Recover after bad reset:
git reset --hard HEAD@{1}to undo a reset - Restore deleted branch: Find the last commit hash of the branch in reflog, then
git branch recovered-branch [hash] - Undo rebase mistakes: Find pre-rebase commit in reflog and reset
Reflog entries expire after 90 days by default (configurable with gc.reflogExpire).
Answer: When merging branch B into branch A:
- Fast-forward merge: Possible if A hasn't changed since B branched off. Git simply moves A's pointer forward to B's commit. No merge commit is created.
- Non-fast-forward merge (true merge): Occurs when both branches have diverged. Git creates a new merge commit with two parents.
A---B---C (main)
\
D---E (feature)
# git merge feature: main moves to E (fast-forward)
# Non-fast-forward (diverged)
A---B---C---F (main)
\
D---E (feature)
# git merge feature: creates merge commit
You can force a merge commit even when fast-forward is possible with git merge --no-ff, which some teams prefer to preserve branch history.
Answer: Git isn't designed for large binary files—they bloat the repository and slow operations. Solutions include:
- Git LFS (Large File Storage): Replaces large files with text pointers in the repository, storing the actual file content on a separate server. When you clone, you get pointers; the actual files are downloaded on demand.
- BFG Repo-Cleaner: Removes large files that were accidentally committed from history.
- Shallow clones:
git clone --depth 1for CI/CD to avoid downloading history. - Partial clones:
git clone --filter=blob:noneto fetch blobs only when needed.
$ git lfs track "*.psd" "*.zip"
$ git add .gitattributes
$ git commit -m "chore: track large files with LFS"
$ git lfs push --all origin main
Answer: Common branching strategies for environments:
- GitFlow:
main(production),develop(integration),release/*(release preparation),hotfix/*(emergency fixes). Good for scheduled releases. - GitHub Flow: Simple:
mainis always deployable. Feature branches, PRs, and immediate deployment. Good for continuous delivery. - GitLab Flow: Adds environment branches (
production,pre-production) with merge rules. - Trunk-based development: Short-lived feature branches, frequent merges to main, release from main with tags.
Configuration management: Never store environment-specific values in Git. Use environment variables, secrets managers, or templated config files with CI/CD substitution.
📋 Advanced Level Questions
These questions target senior engineers, DevOps specialists, and candidates for positions requiring deep Git expertise.
Answer: Git's garbage collection (git gc) performs several housekeeping tasks:
- Compresses loose objects into packfiles (saves space)
- Removes unreachable objects that are older than gc.pruneExpire (default 2 weeks)
- Consolidates multiple packfiles
- Removes stale reflog entries
Git automatically runs git gc --auto when certain thresholds are met (too many loose objects or packfiles). Manual triggers are useful when:
- After large history rewrites (filter-branch) to clean up
- Before archiving a repository
- When repository performance degrades
- After removing sensitive data from history
$ git gc --aggressive --prune=now
# Configure auto GC thresholds
$ git config gc.auto 5000 # Number of loose objects
$ git config gc.autoPackLimit 50 # Number of packfiles
Answer: git bisect performs a binary search through commit history to find which commit introduced a bug. It's invaluable for debugging when you know a bug existed in a known bad commit and didn't exist in a known good commit.
$ git bisect start
$ git bisect bad HEAD # Current commit is broken
$ git bisect good v2.0.0 # v2.0.0 was working
# Git checks out a middle commit. You test it.
$ git bisect good # If this commit works
$ git bisect bad # If this commit is broken
# Repeat until Git identifies the first bad commit
$ git bisect reset # End bisect session
Automation: You can automate with git bisect run and a test script:
$ git bisect run npm test # Run tests automatically
Answer: When you run git commit, several steps occur:
- Create blob objects: For each staged file, Git creates a blob object from the file content (if not already existing).
- Create tree objects: Git builds tree objects representing the directory structure, referencing the new blobs (and existing blobs for unchanged files).
- Create commit object: Git creates a commit object containing:
- The hash of the root tree (snapshot)
- Hash of parent commit(s)
- Author information (name, email, timestamp)
- Committer information (may differ from author)
- Commit message
- Update HEAD and branch refs: The current branch ref is updated to point to the new commit.
- Update reflog: An entry is added to the reflog recording this commit.
$ git cat-file -p HEAD # Shows commit object
$ git ls-tree HEAD # Shows tree object
$ find .git/objects -type f -mmin -1 # New objects in last minute
Answer: Repository corruption requires careful diagnosis and recovery:
- Diagnose with fsck:
git fsck --fullidentifies corrupted or missing objects. - Restore from remote: If corruption is local and remote is healthy, clone fresh and reapply uncommitted work.
- Recover from other clones: Add a healthy clone as remote:
git remote add backup ../healthy-repo; git fetch backup - Manual object recovery: For missing objects, try
git unpack-objectsfrom packfiles or copy objects from backups. - Reinitialize if hopeless:
git initin a backup of your working directory, then re-add remotes.
#!/bin/bash
cp -r .git .git-backup
git fsck --full > corruption.log
# If missing objects, try to get from remote
git fetch --all --force
git reset --hard origin/main
# Still corrupted? Try cloning fresh
cd ..
git clone [url] fresh-repo
cp -r old-repo/* fresh-repo/ (except .git)
Answer: Git security spans multiple layers:
- Authentication: SSH keys (recommended) with passphrases, or HTTPS with tokens (never passwords). Rotate keys regularly.
- Commit signing: GPG signatures verify that commits genuinely come from claimed authors. Enable with
commit.gpgSignand enforce with branch protection. - Branch protection: Require PR reviews, status checks, and signed commits on protected branches.
- Secrets management: Pre-commit hooks to detect secrets, secret scanning in CI, and tools like git-secrets.
- Access control: Repository permissions (read/write/admin), team-based access, and SAML/SSO integration.
- Audit logging: Enable audit logs on Git hosting platforms and ship to SIEM systems.
- Signed tags: Sign release tags to verify authenticity of releases.
Enterprise implementation: Use Git hosting with enterprise features (GitHub Enterprise, GitLab Self-Managed). Implement automated compliance checks in CI/CD.
📋 Scenario-Based Questions
These questions test practical problem-solving and real-world experience. Interviewers describe a situation and ask how you'd handle it.
Answer: This requires immediate, coordinated action:
- ROTATE SECRETS FIRST: Immediately revoke the exposed API keys. The secret was public for 30 minutes—assume compromise.
- Clean Git history: Use
git filter-repoor BFG to remove the file from all history. This rewrites history, changing commit SHAs. - Force push clean history:
git push --force --all(with coordination). - Notify all developers: They must reset their local repositories:
$ git fetch --all
$ git reset --hard origin/main - Check for forks/clones: If the repository was public or widely cloned, consider the secret permanently exposed.
- Prevent recurrence: Add pre-commit hooks with secret detection, enable secret scanning in GitHub/GitLab.
Answer: Implement path-based filtering in CI/CD:
- GitHub Actions: Use
pathsin workflow triggers:
push:
paths:
- 'api/**'
- 'shared-libs/**' # Dependencies
- GitLab CI: Use
changeskeyword:
only:
changes:
- api/**/*
- Custom script: In CI, compute changed files with
git diff --name-only $PREVIOUS_SHA $CURRENT_SHAand conditionally run steps. - Dependency awareness: Include shared libraries in deployment triggers for services that depend on them.
Answer: Follow the hotfix workflow:
- Create hotfix branch from the production tag (not main):
$ git checkout -b hotfix/critical-bug v2.1.0
- Apply the fix, commit with message:
hotfix: resolve critical bug - Test thoroughly
- Merge to main and tag:
$ git checkout main
$ git merge --no-ff hotfix/critical-bug
$ git tag -a v2.1.1 -m "Hotfix release" - Also merge to develop to ensure fix isn't lost:
$ git checkout develop
$ git merge --no-ff hotfix/critical-bug - Delete hotfix branch:
git branch -d hotfix/critical-bug
Key point: Merging to both main and develop ensures the fix persists in all future releases.
Answer: Follow this recovery process:
- Check if branch was ever pushed:
git branch -a | grep feature-name - If found on remote, recover with:
git checkout -b recovered-branch origin/feature-name - If not on remote, check local reflog:
git reflog | grep feature-name - Look for commits around the time the branch was last active:
$ git reflog --date=local | grep "checkout: moving from feature"
$ git log --oneline -g --grep="feature"
$ git fsck --lost-found | grep commit - Once you find likely commit hashes, inspect them:
git show [hash] - Create branch at found commit:
git branch recovered-feature [hash] - If multiple commits, cherry-pick or rebase to reconstruct
Prevention: Encourage regular pushing to remote and educate about reflog as safety net.
Answer: A structured migration plan:
- Assessment: Analyze SVN repository structure, identify large files, understand branching patterns.
- Tool selection: Use
git svn clonefor migration, or specialized tools likesvn2git. - Pilot migration: Migrate a non-critical project first to test workflow.
- Training:
- Workshop on Git concepts (distributed, staging, branching)
- Common workflows (feature branches, PRs)
- Daily commands vs. SVN equivalents
- GUI tools for those who prefer visual interfaces
- Documentation: Create team-specific Git workflow guide, cheat sheets, and troubleshooting FAQ.
- Migration weekend: Final conversion of all repositories, update CI/CD pipelines.
- Post-migration support: Pair programming, office hours for questions, collect feedback.
Common pitfalls: Ignoring .gitignore, committing large files, force-pushing to shared branches.
📋 Quick Reference: Git Command Comparison
| Question | Command | When to Use |
|---|---|---|
| Undo last commit (keep changes) | git reset --soft HEAD~1 |
Forgot to add a file, want to amend |
| Undo last commit (discard changes) | git reset --hard HEAD~1 |
Commit was completely wrong |
| Fix last commit message | git commit --amend -m "new message" |
Typo or unclear message |
| Add forgotten file to last commit | git add file && git commit --amend |
Missed including a change |
| Unstage a file | git reset HEAD file |
Accidentally added file |
| Discard changes in working directory | git checkout -- file |
Revert to last committed version |
Interview Preparation FAQ
Preparation strategy:
- Understand concepts, not just commands: Know why Git behaves the way it does, not just what commands to run.
- Practice on real repositories: Create test repositories and intentionally break things to practice recovery.
- Learn internals: Understand objects, refs, and the reflog. This separates senior candidates.
- Prepare for scenarios: Think through real-world situations like hotfixes, rebase conflicts, and secret leaks.
- Know your team's workflow: Be ready to explain your current branching strategy and why it works for your team.
- Review Git hosting features: GitHub/GitLab-specific features like protected branches, required status checks, and merge methods.
Interviewers typically evaluate:
- Depth of understanding: Can you explain the underlying mechanisms, not just recite commands?
- Practical experience: Have you actually dealt with merge conflicts, rebase issues, or recovery scenarios?
- Problem-solving approach: How do you diagnose and resolve Git problems?
- Team awareness: Do you consider how your actions affect other developers? (e.g., force push implications)
- Best practices: Do you follow security practices, commit conventions, and workflow patterns?
- Communication: Can you explain complex Git concepts clearly?
Memorization alone isn't enough. While knowing common commands is helpful, interviewers are more interested in:
- Knowing which command to use in a situation
- Understanding what the command actually does
- Knowing alternative approaches and their trade-offs
- Being able to look up syntax if needed (real developers use docs)
For example, it's better to know "I need to undo the last commit but keep my changes, so I'd use reset --soft" than to recite the exact command without understanding.
For DevOps positions, focus on:
- CI/CD integration: How Git triggers pipelines, path filtering, commit status checks
- Branching strategies: Trunk-based development, release management, hotfix workflows
- Security: Signed commits, secret detection, branch protection, access control
- Automation: Git hooks, scripting with Git commands, API integration
- Large repositories: Shallow clones, partial clones, Git LFS, performance optimization
- Recovery: Reflog, fsck, handling force pushes, disaster recovery
- Infrastructure as Code: GitOps principles, managing infrastructure with Git