Git & GitHub Interview Questions

TL;DR

35+ Git & GitHub interview questions organized by topic. Click "Show Answer" to reveal detailed answers. Covers basics, branching, merging, pull requests, GitHub Actions, and advanced internals.

Short on time? Focus on Git Basics and Branching & Merging — they come up most often in interviews.

Git Basics

Q: What is Git and why is it called "distributed"?

Git is a version control system that tracks changes to files. It's "distributed" because every developer has a full copy of the entire repository history on their machine — not just the latest version. You can commit, branch, and view history completely offline. There's no single point of failure.

Q: What are the three areas in Git and how do changes flow between them?

Working Directorygit addStaging Area (Index)git commitRepository (.git/). The working directory is where you edit files. The staging area lets you select which changes go into the next commit. The repository stores permanent snapshots (commits).

Q: What is a commit in Git?

A commit is an immutable snapshot of your staged changes. Each commit has: a unique SHA-1 hash, a pointer to its parent commit(s), a tree object (snapshot of all files), the author, timestamp, and a message. Commits form a directed acyclic graph (DAG) — the backbone of Git's history.

Q: What's the difference between git fetch and git pull?

git fetch downloads new commits and refs from the remote but doesn't modify your working directory. git pull = git fetch + git merge — it downloads AND integrates changes. Fetch is safer because you can inspect remote changes before merging.

Q: What is HEAD in Git?

HEAD is a symbolic reference that points to the current branch, which in turn points to the latest commit. When you commit, HEAD advances. In detached HEAD state, HEAD points directly to a commit (not a branch) — this happens when you checkout a specific commit or tag.

Q: What does git stash do and when would you use it?

git stash temporarily saves uncommitted changes (both staged and unstaged) and reverts your working directory to a clean state. Use it when you need to switch branches but aren't ready to commit. Restore with git stash pop (apply + delete) or git stash apply (apply + keep).

Q: Explain git reset --soft, --mixed, and --hard.

All three move HEAD to a specified commit. --soft: keeps changes staged (ready to re-commit). --mixed (default): keeps changes in working directory but unstages them. --hard: discards all changes — working directory matches the target commit. --hard is destructive and can lose work.

Branching & Merging

Q: What is a branch in Git internally?

A branch is just a lightweight pointer (a file containing a 40-character SHA) that points to a commit. Creating a branch is O(1) — Git writes 41 bytes to a file. No files are copied. This is why branching in Git is nearly instant, unlike SVN where branches copy the entire directory tree.

Q: What's the difference between merge and rebase?

Merge creates a new merge commit with two parents, preserving the full branch history (non-linear). Rebase replays your commits on top of the target branch, rewriting their SHAs to create a linear history. Merge is safe for shared branches; rebase is great for local cleanup. The golden rule: rebase local, merge shared.

Q: Explain fast-forward vs three-way merge.

Fast-forward: when the target branch hasn't diverged, Git just moves the pointer forward — no merge commit needed. Three-way merge: when both branches have new commits, Git compares three points (common ancestor, source tip, target tip) and creates a merge commit. Use --no-ff to force a merge commit even when fast-forward is possible.

Q: How do you resolve a merge conflict?

(1) Git marks conflicts with <<<<<<<, =======, >>>>>>> markers. (2) Edit the file: choose one version, combine both, or write new code. (3) Remove all conflict markers. (4) git add the resolved file. (5) git commit to complete the merge. Use git mergetool for a visual merge tool.

Q: What is git cherry-pick and when should you use it?

git cherry-pick <sha> applies a specific commit from one branch to your current branch as a new commit. Use it for: hotfixes (apply a fix from develop to main without merging everything), selectively moving commits between branches. Avoid overusing it — it can create duplicate commits.

Q: Compare Git Flow, GitHub Flow, and trunk-based development.

Git Flow: long-lived branches (main, develop, feature, release, hotfix). Best for versioned releases. GitHub Flow: main is always deployable, short-lived feature branches, PRs for review. Best for continuous delivery. Trunk-based: commit to main directly or via tiny branches (< 1 day). Requires feature flags + strong CI. Used by Google, Netflix. Simplest to fastest: Git Flow → GitHub Flow → trunk-based.

Pull Requests & Code Review

Q: What is a pull request and why is it important?

A pull request is a proposal to merge one branch into another on GitHub. It's important because it enables: (1) Code review — peers review changes before they reach main. (2) Discussion — inline comments on specific lines. (3) CI validation — automated tests run before merge. (4) Audit trail — who approved what, when, and why.

Q: What are the three GitHub merge strategies and when would you use each?

Merge commit: preserves all commits + merge commit. Use when you want full history. Squash and merge: combines all PR commits into one clean commit. Use when PRs have messy WIP commits. Rebase and merge: replays commits linearly without merge commit. Use when you want linear history but want to keep individual commits.

Q: What is CODEOWNERS and how does it work?

CODEOWNERS is a file (.github/CODEOWNERS) that maps file patterns to GitHub users/teams. When a PR modifies matching files, those owners are automatically assigned as reviewers. Combined with branch protection's "Require review from Code Owners," it ensures domain experts review changes to their code.

Q: What branch protection rules would you recommend for a production branch?

(1) Require pull request reviews (min 1-2 approvals). (2) Require status checks to pass (CI must be green). (3) Include administrators (no exceptions). (4) Dismiss stale reviews on new pushes. (5) Require linear history if using squash merge. Optional: require signed commits, restrict who can push.

Q: How do you handle a PR that's too large to review effectively?

Use stacked PRs: break the feature into sequential, small PRs that build on each other. Each PR should be < 400 lines. Use draft PRs for early feedback. Add clear PR descriptions explaining the strategy: "This is PR 2/4 — adds auth middleware. PR 1 (merged) added the user model." Alternatively, split by layer: one PR for DB changes, another for API, another for UI.

Q: Explain the fork-and-PR workflow for open-source contributions.

(1) Fork the repo to your account. (2) Clone your fork locally. (3) Add the original repo as upstream remote. (4) Create a feature branch, make changes, push to your fork. (5) Open a PR from your fork's branch to the original repo's main. (6) Respond to review feedback. (7) Keep your fork in sync with git pull upstream main.

GitHub Actions & CI/CD

Q: What is GitHub Actions and how is it structured?

GitHub Actions is a CI/CD platform built into GitHub. Structure: Workflows (YAML files in .github/workflows/) are triggered by events (push, PR, schedule). Each workflow contains jobs that run on runners (VMs). Each job has steps that run commands or use pre-built actions.

Q: How do you securely handle secrets in GitHub Actions?

Store secrets in Settings → Secrets and variables → Actions (encrypted at rest). Reference with ${{ secrets.NAME }}. Secrets are automatically masked in logs. Use Environments for environment-specific secrets with approval gates. Never hardcode secrets in workflow files. Use OIDC for cloud providers instead of long-lived tokens.

Q: What's the difference between uses and run in a workflow step?

uses references a pre-built action (e.g., actions/checkout@v4) — reusable, maintained by others, can accept inputs. run executes shell commands directly on the runner (e.g., run: npm test). Use uses for common tasks (checkout, setup); run for custom commands.

Q: How would you optimize a slow CI pipeline?

(1) Cache dependencies (actions/cache or built-in caching). (2) Run jobs in parallel where possible. (3) Use path filters to skip irrelevant runs. (4) Concurrency groups to cancel outdated runs. (5) Split tests into parallel shards. (6) Use faster runners or self-hosted runners. (7) Only run expensive checks (e.g., E2E) on main, not every PR.

Q: What are reusable workflows and how do they differ from composite actions?

Reusable workflows (workflow_call) share entire job definitions across repos — they run as separate jobs with their own runner. Composite actions bundle multiple steps into a single action — they run within an existing job. Use reusable workflows for complete CI/CD pipelines; composite actions for reusable step sequences.

Advanced Git

Q: How does Git store data internally?

Git is a content-addressable filesystem. It stores four types of objects: (1) Blob — file content (no filename). (2) Tree — directory listing (filenames + pointers to blobs/trees). (3) Commit — points to a tree + parent commit(s) + metadata. (4) Tag — named pointer to a commit. All objects are identified by their SHA-1 hash and stored in .git/objects/.

Q: What is git reflog and how can it save you?

git reflog records every time HEAD moves — commits, checkouts, rebases, resets. Even after a destructive git reset --hard, the old commits still exist in the reflog for ~90 days. To recover: git reflog to find the commit SHA, then git reset --hard <sha> or git checkout <sha>. Reflog is local-only — it's not pushed to remotes.

Q: What is git bisect and how does it work?

git bisect performs a binary search through commit history to find which commit introduced a bug. (1) git bisect start. (2) git bisect bad (current commit is broken). (3) git bisect good <sha> (last known working commit). Git checks out the midpoint; you test and mark it good/bad. Repeats until the culprit is found. O(log n) instead of checking every commit.

Q: What are Git hooks? Give 3 useful examples.

Git hooks are scripts that run automatically at certain Git events. Stored in .git/hooks/. Examples: (1) pre-commit: run linter/formatter before each commit (reject if it fails). (2) commit-msg: enforce commit message format (e.g., conventional commits). (3) pre-push: run tests before pushing. Use Husky or pre-commit framework to share hooks via the repo.

Q: How would you remove sensitive data (like an API key) from Git history?

(1) Rotate the key immediately — assume it's compromised. (2) Use git filter-repo --path secrets.txt --invert-paths to remove the file from all commits. (3) Force push all affected branches. (4) Ask all collaborators to re-clone (their local copies still have the old history). (5) Contact GitHub support to clear cached views. (6) Add the file to .gitignore and enable push protection.

Q: What are Git submodules and when should you use them?

Git submodules embed one repo inside another at a fixed commit. The parent repo tracks which commit the submodule points to. Use them for: shared libraries, vendored dependencies, or monorepo-like structures. Downsides: complex workflow (git submodule update --init), easy to get out of sync, confusing for new team members. Consider alternatives like package managers.

Scenario-Based Questions

Q: You accidentally committed to main instead of a feature branch. How do you fix this?

(1) Create a new branch at the current commit: git branch feature/my-work. (2) Reset main to the previous commit: git reset --hard HEAD~1. (3) Switch to the feature branch: git switch feature/my-work. Your changes are now on the feature branch and main is clean. If already pushed to main, you'll need to force push (coordinate with team first).

Q: Your teammate force-pushed to a shared branch and your local branch is out of sync. What do you do?

(1) git fetch origin to get the new history. (2) If you have no local unpushed commits: git reset --hard origin/branch-name. (3) If you have local commits to preserve: git rebase origin/branch-name to replay your commits on top of the new history. (4) Have a conversation with your teammate about why force-pushing shared branches is problematic.

Q: A deployment broke production. How do you use Git to quickly revert?

Use git revert <sha> to create a new commit that undoes the changes of the bad commit. This is safer than git reset because it doesn't rewrite history — important for shared branches. Push the revert, and the deploy pipeline will automatically roll out the fix. For a merge commit: git revert -m 1 <merge-sha>.

Q: You need to work on two features simultaneously that depend on different states of the codebase. How?

Use git worktree to check out multiple branches simultaneously in separate directories: git worktree add ../feature-a feature/a. Each worktree has its own working directory but shares the same .git database. Alternative: use git stash to save/restore changes when switching branches.

Q: Your CI pipeline takes 20 minutes. How would you make the developer feedback loop faster?

(1) Cache dependencies aggressively. (2) Parallelize test suites across multiple runners. (3) Path filters — only run relevant tests. (4) Fail fast — run linting first, skip slow tests if lint fails. (5) Concurrency groups — cancel outdated runs. (6) Move slow E2E tests to a post-merge pipeline. (7) Use faster runners or self-hosted runners. Target: < 5 minutes for PR checks.