GitCommon Interview Questions

Git Interview Questions and Answers

Over 40 Git questions covering everything from introductory concepts to internal architecture — the range you can expect in technical interviews for software engineering roles. Read the explanations, not just the short answers; interviewers follow up with "why" and "when would you use this?"

Basic Questions

Question

Answer

What is Git?

Git is a distributed version control system (VCS) that tracks changes to files over time. Every developer has a complete copy of the repository including full history. Created by Linus Torvalds in 2005 for managing the Linux kernel source code.

What is version control and why do we need it?

Version control tracks every change made to a codebase over time. It lets you: revert to previous states, see what changed and when, collaborate without overwriting each other's work, create experimental branches, and understand why code was written a certain way.

What is the difference between Git and GitHub?

Git is the version control tool — the software you install locally. GitHub is a web hosting service for Git repositories that adds collaboration features: pull requests, issues, Actions (CI/CD), code review, and access control. Alternatives to GitHub include GitLab and Bitbucket.

What is a commit?

A commit is a snapshot of the entire repository at a specific point in time. It stores: the state of all tracked files, the author name and email, the commit date and time, a commit message, and a pointer to the parent commit(s). Each commit is identified by a unique SHA-1 hash.

What is a branch?

A branch is a lightweight, movable pointer to a commit. Creating a branch is just creating a pointer — no files are copied. When you commit on a branch, the pointer advances to the new commit. Branches let multiple lines of development proceed in parallel without interference.

What is the difference between git pull and git fetch?

git fetch downloads changes from the remote but does not modify your working tree or local branches. It updates remote-tracking branches (e.g., origin/main). git pull does a fetch AND then merges (or rebases) the remote changes into your current branch. git pull = git fetch + git merge.

What does git clone do?

Creates a complete local copy of a remote repository: all files, full commit history, all branches, and all tags. Sets up origin as a remote pointing to the source URL and checks out the default branch.

How do you revert a commit?

git revert <hash> creates a new commit that undoes the changes of a specific commit. Safe for shared branches because history is not rewritten. git reset --hard HEAD~1 undoes the last commit by moving HEAD back — dangerous if already pushed because it rewrites history.

What is the staging area?

The staging area (also called the index) is the intermediate step between your working tree and a commit. git add moves changes into the staging area. git commit packages everything in the staging area into a commit. This gives you fine-grained control over what goes into each commit.

What is .gitignore?

A file listing patterns for files and directories that Git should not track. Common entries: node_modules/, *.log, .env, dist/, .DS_Store. Once a file is already tracked, adding it to .gitignore does not untrack it — use git rm --cached <file> first.

What is git status?

git status shows the current state of the working tree and staging area: which files are modified, staged, or untracked. It also shows whether your branch is ahead or behind the remote tracking branch.

What is git init?

Creates a new empty Git repository by creating a .git directory in the current folder. The .git directory contains all the repository metadata, objects, refs, and config.

Intermediate Questions

Question

Answer

What is the difference between git merge and git rebase?

Both integrate changes from one branch into another. Merge creates a new "merge commit" with two parents, preserving the full history of when branches diverged and merged. Rebase moves the commits from your branch and replays them on top of another branch — the history looks linear as if the work was done sequentially. Merge is safer for shared branches; rebase creates cleaner history but rewrites commits (new SHAs).

What is detached HEAD state?

HEAD normally points to a branch name, which in turn points to the latest commit. In detached HEAD state, HEAD points directly to a commit SHA instead of a branch. This happens when you checkout a commit, tag, or remote-tracking branch directly. Any commits made here have no branch pointer — they become unreachable when you switch away. Fix with: git checkout -b new-branch to put those commits on a branch.

What is git stash?

git stash saves your current uncommitted changes (staged and unstaged) onto a stack and restores the working tree to the last commit. Use it when you need to switch branches without committing unfinished work. git stash pop applies the most recent stash and removes it; git stash apply applies without removing.

What is the difference between git reset --soft, --mixed, and --hard?

All three move HEAD to the specified commit. --soft: keeps staged changes and working tree as-is. --mixed (default): unstages changes but keeps working tree. --hard: discards all changes — both staged and working tree. Use --soft/--mixed to undo commits while keeping your work; use --hard to truly discard work.

What is git cherry-pick?

Apply the changes introduced by one or more specific commits onto the current branch. Creates a new commit with the same changes but a new SHA. Useful for applying a bug fix from main to a release branch, or pulling one feature from a branch without merging the whole thing. Use sparingly — it creates duplicated commits in history.

What is the difference between git revert and git reset?

git revert creates a new commit that inverts the changes of a specific commit. History is preserved and it is safe to push to shared branches. git reset moves HEAD (and the branch pointer) to an earlier commit, effectively removing commits from the history. Never reset commits that have been pushed and shared with others.

What is a fast-forward merge?

A fast-forward merge happens when the branch being merged into has not received any new commits since the feature branch was created. Instead of creating a merge commit, Git simply advances the branch pointer to the tip of the feature branch. The result is as if you had been committing directly to the target branch. Use --no-ff to force a merge commit even when fast-forward is possible.

What is git rebase -i (interactive rebase)?

Interactive rebase lets you edit, reorder, squash, fixup, drop, or reword commits before they are applied. You get an editor showing each commit in the range as pick <hash> <message>. Change pick to squash to combine a commit with the previous one, reword to edit the message, drop to delete a commit, or edit to stop at a commit to amend it. Used to clean up messy history before merging a PR.

What is git bisect?

A binary search tool for finding which commit introduced a bug. You tell Git which commit is "bad" (has the bug) and which is "good" (does not). Git checks out the midpoint commit; you test it and mark it good or bad. Git keeps halving the range until it identifies the exact commit that introduced the regression. A 1000-commit range takes at most 10 steps (log₂ 1000 ≈ 10).

What is a merge conflict and how do you resolve it?

A merge conflict occurs when two branches change the same lines of the same file differently. Git cannot automatically choose which version to keep. Conflict markers (<<<<<<<, =======, >>>>>>>) show both versions in the file. Resolution: edit the file to the desired final state, remove all markers, run git add <file>, then git commit (merge) or git rebase --continue (rebase).

What is the difference between git fetch and git pull?

git fetch updates remote-tracking branches (origin/main, etc.) but does not touch your local branch or working tree. It is always safe. git pull is git fetch followed by git merge (or git rebase with --rebase flag) — it updates your current branch with the remote changes. Always safe to fetch; be mindful of what pull merges into.

What does --force-with-lease mean?

A safer version of --force for git push. Force push overwrites the remote branch regardless. --force-with-lease refuses to push if the remote branch has received commits you have not seen locally — preventing you from accidentally overwriting someone else's work. Always prefer --force-with-lease over --force when force-pushing is necessary.

Advanced Questions

Question

Answer

How does Git store data internally?

Git is a content-addressable filesystem. Every piece of data is stored as an object keyed by its SHA-1 hash. There are four object types: blob (file content), tree (directory listing), commit (snapshot with metadata), and tag (annotated tag). Objects are stored in .git/objects/ as files named by their hash. When objects accumulate, Git packs them into packfiles with delta compression.

What is a packfile?

A packfile is a compressed archive of Git objects. Git stores loose objects initially, but periodically runs git gc (garbage collection) to pack them. Packfiles use delta compression — instead of storing every version of a file, they store the base version and the differences (deltas) between versions. This dramatically reduces repository size. Packfiles have a companion .idx index file for fast lookup.

How does a three-way merge work?

Git finds three commits: the tip of branch A, the tip of branch B, and their merge base (most recent common ancestor). It compares A vs base and B vs base. If only one side changed a line, that change is accepted. If both changed the same line differently, that is a conflict. If both changed it the same way, the result includes that change once. The merge base is found with git merge-base A B.

What is the reflog and when is it useful?

The reflog is a chronological log of every position HEAD has been in your local repository. It records moves caused by commits, checkouts, rebases, resets, and merges. The reflog is never pushed — it is local only. It is your safety net for recovering from mistakes: git reflog shows the history, and git reset --hard <hash> can restore any state. Entries expire after 90 days (reachable) or 30 days (unreachable) by default.

What is the difference between a merge commit and a regular commit?

A regular commit has exactly one parent. A merge commit has two or more parents — one for each branch that was merged. This is how Git records that two lines of development were joined at that point in history. git log --graph shows merge commits as a junction in the branch graph. Octopus merges (merging more than two branches at once) produce commits with more than two parents.

What happens when you run git commit?

Git: (1) reads the index to create a tree object for the repository state, (2) creates a commit object pointing to that tree, containing author info, date, message, and parent commit SHA(s), (3) stores the commit object in .git/objects/, (4) updates the current branch ref in .git/refs/heads/ to point to the new commit, (5) updates HEAD if it points to the branch.

What is a shallow clone and what are its limitations?

A shallow clone (--depth=N) fetches only the last N commits rather than full history. Pros: much faster clone, smaller disk usage — ideal for CI. Cons: cannot perform operations that need the full history (git log --follow for renamed files, git blame far back, git bisect across the truncated boundary, git merge-base outside the shallow depth). Deepen with git fetch --deepen=N or git fetch --unshallow.

When would you use git worktree?

git worktree lets you have multiple working trees from the same repository simultaneously — each checked out to a different branch, in different directories. Useful for: reviewing a PR while you have uncommitted work on your current branch, running tests on a release branch while developing on main, building two versions in parallel. Unlike git stash or switching branches, worktrees let you have them both active at the same time.

Explain the Git object model with SHA-1.

Every object in Git is identified by the SHA-1 hash of its contents. This makes Git a content-addressable store — the same content always produces the same hash. Because commit hashes depend on the tree hash, which depends on blob hashes, which depend on file content, changing anything in history changes every commit hash from that point onward. This is why rebasing and amending produce new commit SHAs — they are new objects.

What is the difference between git log A..B and git log A...B?

Two-dot (A..B) shows commits reachable from B but not from A. This is "what is on B that is not on A" — equivalent to a PR diff. Three-dot (A...B) shows commits reachable from either A or B but not from their common ancestor — the symmetric difference. Used in git diff to show changes on a branch relative to where it diverged from base, not relative to the tip of base.

How would you split a large commit into smaller ones?

Use git rebase -i HEAD~N to reach the commit; mark it as edit. When Git pauses: git reset HEAD~1 (mixed reset) to unstage all files while keeping them in the working tree. Then stage and commit them in groups with multiple git add -p + git commit cycles. Finally git rebase --continue. The large commit is replaced by your smaller ones.

What is git filter-repo and when would you use it?

git filter-repo (a replacement for the deprecated git filter-branch) rewrites all commits in a repository's history. Use cases: remove accidentally committed secrets from all history, extract a subdirectory into its own repository with preserved history, remove large files from history to shrink the repository. Requires force-pushing and all contributors must re-clone. Very destructive — use only when truly necessary.

Scenario-Based Questions

Question

Answer

You accidentally committed a password to main and pushed it. What do you do?

  1. Immediately revoke/rotate the credential — assume it is compromised. 2. Remove from history using git filter-repo --path-glob "*.env" --invert-paths or git filter-repo --replace-text <(echo "SECRET_VALUE==>REMOVED"). 3. Force-push to all branches. 4. All collaborators must re-clone. 5. Inform your security team. History removal does NOT help if anyone already fetched the commit — the credential is gone from your repo but not from theirs.

Your feature branch is 50 commits behind main and has many conflicts. How do you handle this?

Option A (rebase): git fetch origin && git rebase origin/main. Resolve conflicts one commit at a time using git add + git rebase --continue. Option B (merge): git merge origin/main — resolve all conflicts in one step, creates a merge commit. For 50 commits behind with many conflicts, merge is often easier since you resolve everything at once rather than per-commit. After resolving: git push --force-with-lease.

A colleague force-pushed to main and now your local is behind. What do you do?

First, check if you have any commits not on the remote: git log origin/main..HEAD. If you have unique local commits, cherry-pick them onto the new history. If your local main just needs to match remote: git fetch origin && git reset --hard origin/main. Then recover: figure out what the colleague deleted (they should use reflog on their machine) and whether it needs to be restored.

How do you find which commit introduced a specific bug?

Use git bisect. Steps: git bisect start, git bisect bad (current commit has the bug), git bisect good v1.0.0 (this version was fine). Git checks out the midpoint. Test whether the bug exists. Run git bisect good or git bisect bad. Repeat until Git outputs "X is the first bad commit". Then git bisect reset to return to HEAD. You can automate it: git bisect run npm test.

Quick-Fire Reference Table

Concept

Key point to remember

git add -p

Stage individual hunks interactively — precise control over what goes in each commit

git commit --amend

Rewrites the last commit — never amend a commit that has been pushed to shared branches

git push --force-with-lease

Safer than --force — refuses push if remote has new commits you haven't seen

git rebase vs merge

Rebase = linear history, rewrites commits; merge = preserves history, creates merge commit

detached HEAD

HEAD points to commit, not branch; commits made here are lost when you switch away unless you create a branch

git reset --hard

Discards working tree changes permanently; use git reflog to recover

git stash

Temporary shelf for changes; not a substitute for branches

git cherry-pick

Apply a specific commit to any branch; creates duplicate commit with new SHA

git bisect

Binary search for bug introduction; automated with git bisect run

packfile

Delta-compressed storage of many objects; what makes git repositories small

ORIG_HEAD

Safety pointer set before risky operations; git reset --hard ORIG_HEAD undoes last merge/rebase

reflog

Local-only history of HEAD positions; 30–90 day window to recover anything

three-way merge

Uses common ancestor + both tips; only conflicts when both sides changed the same line differently

Note
Interviewers ask about Git not just to check familiarity, but to assess your mental model of how it works under the hood. Understanding that commits are SHA-1 hashed snapshots, branches are just pointers, and rebase rewrites commits (new SHAs) will help you reason correctly about any Git question you encounter.
Tip
Before your interview, be able to draw the commit graph for: a simple branch and merge, a rebase, and a cherry-pick. Visualising Git with commit nodes and arrows is the clearest way to explain these concepts.