Git Interview Prep

Practical Git concepts for interviews, daily development, and team workflows.

20 Concepts All Levels Team Workflows Revision Ready
Q01
What is Git?
Easy 2 min read
Say this first

Git is a distributed version control system that tracks changes in your code over time so you can go back, collaborate, and never lose work.

Think of Git like a time machine for your code. Every time you save a "snapshot" (called a commit), Git remembers exactly what every file looked like at that moment. Mess something up? Roll back. Want to try a crazy idea without breaking the main code? Create a branch.

The "distributed" part means everyone on your team has the full history on their own machine — not just a connection to one central server. So even if the server dies, nobody loses any work.

Git was created by Linus Torvalds in 2005 — the same guy who made Linux — specifically because he was frustrated with how slow and restrictive existing tools were for managing the Linux kernel.

What Interviewers Test
  • Git is a VCS (Version Control System), not a platform — GitHub/GitLab are platforms built on top of Git
  • It's distributed — every developer has the full repo copy locally
  • Git tracks changes, not full file copies (it's smart about storage)
  • Core concepts: commits, branches, merges, remotes
Competitive Edge

Most candidates say "version control tool." Go further: "Git uses a DAG (Directed Acyclic Graph) of commit objects internally, which is why branching is so cheap — it's just a pointer to a commit, not a copy of all files."

Q02
Difference between Git and GitHub?
Easy 2 min read
Say this first

Git is the tool (runs on your machine). GitHub is a website that hosts Git repositories in the cloud and adds collaboration features on top.

Git is like the engine. GitHub is like the car dashboard — it makes the engine easier to use and shows you everything nicely. You can use Git completely without GitHub (just local repos), but you can't use GitHub without Git under the hood.

GitHub adds things Git doesn't have: pull requests, issue tracking, Actions (CI/CD), project boards, a web UI to browse code, and social features like stars and forks. Alternatives to GitHub include GitLab, Bitbucket, and Azure DevOps — they all wrap around Git.

What Interviewers Test
  • Git = CLI tool, local, no internet needed for most operations
  • GitHub = cloud hosting + collaboration layer (owned by Microsoft)
  • Pull Requests, Issues, Actions — all GitHub features, not Git
  • GitLab / Bitbucket are GitHub alternatives, all use Git underneath
Common Mistake
  • Saying "I push to Git" when you mean "I push to GitHub." Sounds minor, but interviewers notice.
  • Thinking you need internet for git commit, git log, git branch — you don't. Only push/pull/fetch need internet.
Q03
What is a Repository?
Easy 2 min read
Say this first

A repository (repo) is a folder that Git is tracking — it contains your project files plus the entire history of every change ever made.

When you run git init in a folder, Git creates a hidden .git directory inside it. That .git folder IS the repository — it stores every commit, branch, tag, and config. The files you see in the folder are just your working copy.

There are two kinds: local repos (on your machine) and remote repos (on GitHub/GitLab/server). They sync through push and pull. You can have multiple remote repos — like origin pointing to your GitHub fork and upstream pointing to the original project.

Key Facts
  • The .git folder = the actual repo. Delete it and you lose all Git history
  • Local repo: on your machine. Remote repo: on a server
  • git init creates a new repo. git clone copies an existing one
  • A repo can have multiple remotes (origin, upstream, etc.)
Q04
git pull vs git fetch
Medium 3 min read
Say this first

git fetch downloads changes but doesn't touch your code. git pull downloads AND immediately merges them into your current branch.

Imagine you're working on a Google Doc with a team, but you turned off auto-sync. git fetch is like checking "what did others change?" without applying anything. git pull is like applying all those changes to your own doc right now.

git pull is literally just a shortcut for git fetch followed by git merge. In teams, many senior engineers prefer git fetch + manual review before merging, so they know exactly what's coming in before it hits their branch.

Visual — Fetch vs Pull
REMOTE (GitHub) remote/origin (local cache) Local Branch (your code) fetch merge git pull = fetch + merge
Key Facts
  • git fetch: safe, non-destructive, just updates remote-tracking branches
  • git pull: convenient but can cause unexpected merge commits
  • git pull --rebase: fetches + rebases instead of merging (cleaner history)
  • Use fetch when you want to review before merging — good practice in teams
Competitive Edge

Mention git pull --rebase — it avoids creating a merge commit for every pull, keeping history linear. Many teams set this as default: git config --global pull.rebase true.

Q05
git merge vs git rebase
Hard 4 min read
Say this first

Merge keeps both histories and creates a merge commit. Rebase moves your branch's commits on top of another branch, giving a clean, linear history — but rewrites commit history.

Imagine you're writing a book with a friend. Merge is like: "Here's my chapters, here's yours, here's a note saying we combined them on Tuesday." Rebase is like: "Let me rewrite my chapters as if I had started writing after you finished yours" — so the final result looks like a single clean story, with no "combination note" in the middle.

Merge is safer and more honest — it shows the real history of what happened. Rebase makes history look cleaner and easier to read with git log, but it literally rewrites commit hashes. That's why the golden rule of rebase is: never rebase commits that have already been pushed to a shared branch.

In practice: teams use merge for integrating feature branches into main (preserving history), and rebase for keeping a feature branch up to date with main (before opening a PR).

Merge vs Rebase — History Shape
MERGE A B X Y M merge REBASE A B X' replayed Y' replayed Clean linear history ✓ History preserved, merge commit added
Key Facts
  • Merge: non-destructive, safe for shared branches, creates a merge commit
  • Rebase: rewrites history, cleaner log, NEVER do on shared/public branches
  • Interactive rebase (git rebase -i) lets you squash, edit, reorder commits before a PR
  • Golden rule: rebase only local, unpushed commits
Follow-up Questions
When would you choose rebase over merge?
Use rebase to keep a feature branch up-to-date with main while working, or to clean up messy commit history before opening a PR. Use merge when integrating completed features into main — so the history shows exactly when and what was merged.
What is interactive rebase?
git rebase -i HEAD~N lets you modify the last N commits. You can squash multiple commits into one, reorder them, change commit messages, or drop commits entirely. Very useful before code review.
Traps
  • Rebasing a branch that others are working on will cause them to have conflicting history — serious team headache.
  • Rebase changes commit hashes — even if the code is identical, it's technically a new commit.
Q06
What is a Branch in Git?
Easy 2 min read
Say this first

A branch is just a lightweight pointer to a specific commit. It lets you work on a separate version of the code without touching the main codebase.

Think of the main branch as the "live" train track. When you create a branch, you're laying a new side track from a specific point. You can work on that side track as long as you want, and when your feature is ready, you merge it back into the main track.

Because a branch is literally just a file containing a commit hash (40-character string), creating a branch is basically free and instant. This is very different from SVN (an older VCS) where branching was expensive and slow. In Git, most teams create a new branch for every single feature or bug fix.

Key Facts
  • Default branch is usually called main (used to be master)
  • git branch feature-xyz creates a branch, git checkout -b feature-xyz creates AND switches to it
  • Branches are cheap — just pointers, no file duplication
  • You can switch between branches instantly using git checkout or git switch
Competitive Edge

A branch is just a file in .git/refs/heads/ containing a 40-char commit SHA. That's why creating or deleting a branch is O(1) in Git — it's essentially creating or deleting a single tiny file.

Q07
Why do we use Pull Requests?
Easy 2 min read
Say this first

A Pull Request is a formal request to merge your branch into another. It creates a space for code review, discussion, and automated checks before the code goes live.

Without PRs, developers could push anything directly to main. That's chaos in a team. PR is the "checkpoint" — your code needs a second pair of eyes before it can join the main codebase. It's standard in every real-world team.

PRs let reviewers leave comments, suggest changes, approve, or request changes. CI/CD pipelines (like GitHub Actions) run tests automatically on every PR, so bugs get caught before merging. It also creates a documented history of why changes were made.

Key Facts
  • PRs are a GitHub/GitLab feature, not a Git feature — Git itself doesn't have PRs
  • GitLab calls them "Merge Requests (MRs)" — same concept
  • A PR links a source branch to a target branch. Reviewers approve, then it gets merged
  • PRs can trigger CI/CD: automated tests, linting, deployments to staging
Q08
What is Git Stash?
Medium 2 min read
Say this first

Git stash temporarily saves your uncommitted changes so you can switch branches or pull updates — without making a commit or losing your work.

Imagine you're halfway through a feature, and your manager says "quick, fix this prod bug!" You can't commit half-done work. You can't throw it away. git stash is like a drawer where you shove your half-finished work, switch to fix the bug, then come back and pull your work out of the drawer with git stash pop.

You can have multiple stashes. git stash list shows them all. git stash pop applies the latest and removes it from stash. git stash apply applies it but keeps it in the stash (useful when applying the same changes to multiple branches).

Key Facts
  • git stash — stash all tracked modified files
  • git stash -u — also stash untracked (new) files
  • git stash pop — apply top stash and remove it
  • git stash apply stash@{2} — apply a specific stash entry
  • git stash drop — delete a stash entry
Traps
  • By default, stash doesn't include untracked files. Use git stash -u or --include-untracked to include them.
  • Stashes are local — they don't get pushed to remote.
Q09
git reset vs git revert
Hard 4 min read
Say this first

git reset moves the branch pointer backward (rewrites history). git revert creates a new commit that undoes a previous commit (safe for shared branches).

Think of git reset as going back in time and pretending commits never happened. The commits are gone (or detached). It's like erasing pages from a book. Safe for local work — dangerous if you've already pushed.

git revert is the opposite: you add a new page to the book that says "undo everything on page 37." The original page 37 is still there. It's transparent, safe for team repos, and doesn't rewrite history.

Reset has three modes: --soft (uncommit but keep changes staged), --mixed (default — uncommit, unstage, keep in working directory), --hard (uncommit AND delete changes from working directory — dangerous!).

Key Facts
  • git reset --soft HEAD~1 — undo last commit, keep changes staged
  • git reset --mixed HEAD~1 — undo last commit, unstage changes (default)
  • git reset --hard HEAD~1 — undo last commit AND delete changes (dangerous!)
  • git revert HEAD — create a new undo-commit, history stays intact
  • Rule: use revert on shared/public branches, reset only on local-only branches
Follow-up Questions
Can you undo a git reset --hard?
Yes! Using git reflog you can find the commit hash before the reset and do git reset --hard <old-hash>. Reflog keeps a local history of HEAD movements for about 90 days. This is a lifesaver.
Traps
  • git reset --hard after already pushing — forces you to git push --force, which can overwrite teammates' work on the same branch.
  • Many beginners use reset where they should use revert — and break the shared branch history.
Competitive Edge

Mentioning git reflog as the escape hatch for bad resets immediately separates you from candidates who don't know it. Reflog tracks all HEAD movements locally — even after --hard resets.

Q10
What is a Merge Conflict?
Medium 2 min read
Say this first

A merge conflict happens when two branches modify the same part of the same file in different ways, and Git can't automatically decide which version to keep.

Git is pretty smart about merging. If you changed line 5 and your teammate changed line 50, it handles that automatically. But if you both changed line 5? Git throws up its hands and says "I don't know which one you want — you decide." That's a conflict.

Git marks the conflicting section in the file with <<<<<<<, =======, and >>>>>>> markers. Above the ======= is your change. Below is theirs. You have to manually pick one (or combine them) and remove the markers.

Conflict Markers
<<<<<<< HEAD  (your branch)
const greeting = "Hello World";
=======
const greeting = "Hey there!";
>>>>>>> feature/update-greeting  (their branch)

// You manually choose one and delete the markers:
const greeting = "Hello World"; // keep yours
// Then: git add . && git commit
Q11
How do you resolve merge conflicts?
Medium 3 min read
Say this first

You open the conflicted file, manually edit it to have the correct final version, remove Git's conflict markers, then stage and commit the resolved file.

Step 1: Git tells you which files have conflicts after git merge or git pull. Run git status to see them listed under "Unmerged paths."

Step 2: Open each conflicted file. Look for the <<<<<<< markers. Edit the file to look exactly how you want the final version to be — you're not restricted to choosing one side, you can blend both if needed.

Step 3: After fixing the file, run git add <filename> to mark it as resolved. Do this for all conflicted files. Then run git commit to finalize the merge.

Modern editors like VS Code show conflicts with a nice UI — "Accept Current," "Accept Incoming," "Accept Both." Tools like git mergetool open a three-way diff viewer.

Step-by-Step
  • 1. git status — identify conflicted files
  • 2. Open file, find markers, decide final content, delete markers
  • 3. git add <file> — mark as resolved
  • 4. git commit — complete the merge
  • 5. Optionally use git mergetool or VS Code for visual help
Q12
Local Repository vs Remote Repository
Easy 2 min read
Say this first

Local is the repo on your machine. Remote is the repo on a server (like GitHub). You sync between them using push and pull.

Local repo lives in the .git folder on your laptop. You can commit, branch, and log without any internet. Remote repo is hosted online — it's the shared source of truth for the whole team.

When you git push, you send your local commits to remote. When you git pull, you bring remote commits down. A project can have multiple remotes — origin is just the conventional name for the primary one.

Key Facts
  • origin = default name for your remote (set when you clone or add a remote)
  • git remote -v — see all configured remotes
  • git remote add upstream <url> — add a second remote
  • You can work offline locally; just push/pull when you have internet
Q13
What is .gitignore?
Easy 2 min read
Say this first

.gitignore is a file that tells Git which files and folders to completely ignore — they won't be tracked, staged, or pushed.

Not everything in your project folder belongs in the repo. node_modules/ (huge, auto-generated), .env (has secret API keys), __pycache__/ (Python compiled files), dist/ (build output) — all of these should be ignored.

You put patterns in .gitignore and Git pretends those files don't exist. The .gitignore file itself should be committed to the repo so all teammates use the same rules. A good starting point: gitignore.io generates .gitignore files for your specific tech stack.

.gitignore example
# Dependencies
node_modules/
# Environment secrets
.env
.env.local
# Build outputs
dist/
build/
# OS junk
.DS_Store
Thumbs.db
# Python
__pycache__/
*.pyc
Traps
  • Adding a file to .gitignore after it's already been committed doesn't remove it. You need to run git rm --cached <file> first.
  • Never commit .env files with real secrets — people forget this and push credentials to public GitHub repos.
Q14
git clone vs git fork
Medium 2 min read
Say this first

Clone copies a repo to your local machine. Fork copies a repo to your GitHub account (creating your own cloud copy) — then you typically clone your fork.

Fork is a GitHub/GitLab concept, not a Git command. When you fork a public project (like an open-source library), you get your own copy in your GitHub account where you have full push access. Then you clone THAT fork to your machine, make changes, and send a Pull Request to the original project.

Clone is a pure Git operation — it just downloads a repo to your machine. The origin remote is set to whatever URL you cloned from.

Key Facts
  • Fork = server-side copy (GitHub account → GitHub account)
  • Clone = local copy (remote server → your machine)
  • Open source workflow: Fork → Clone fork locally → Push to your fork → PR to original
  • Direct team members usually just clone the main repo (no fork needed)
Q15
What is HEAD in Git?
Medium 2 min read
Say this first

HEAD is a pointer to your current position in the repo — usually pointing to the latest commit on your current branch.

You can think of HEAD as "you are here" on the Git map. It's a file in .git/HEAD that usually contains a reference to a branch name (like ref: refs/heads/main). When you make a new commit, HEAD moves forward to that new commit. When you switch branches, HEAD updates to point to that branch.

HEAD~1 means "one commit before HEAD." HEAD~3 means "three commits back." This syntax is used heavily with reset, log, and rebase commands.

Key Facts
  • HEAD normally points to a branch, which points to a commit
  • HEAD~1 = parent commit, HEAD~2 = grandparent
  • git log shows HEAD's current position
  • Detached HEAD = HEAD points directly to a commit, not a branch
Q16
git add . vs git add <file>
Easy 1 min read
Say this first

git add . stages all changed files in the current directory. git add <file> stages only that specific file.

git add . is convenient but can accidentally stage files you didn't mean to commit (debug logs, temporary test files). git add <file> gives you precise control. In professional teams, many engineers use git add -p (patch mode) to stage changes chunk by chunk — this lets you make one clean commit even if you changed multiple unrelated things in the same session.

Key Facts
  • git add . — all changed files in current and subdirectories
  • git add -A — all changes including deleted files across whole repo
  • git add -p — interactive mode, stage specific chunks/hunks
  • git status before adding — know what you're staging
Q17
Detached HEAD State
Hard 3 min read
Say this first

Detached HEAD happens when HEAD points directly to a commit instead of a branch. You can browse and even commit, but those commits will be lost if you switch away without creating a branch.

Normally: HEAD → branch → commit. In detached HEAD: HEAD → commit (no branch in between). It's like stepping off the main track onto a platform — you can look around, even write things down, but if you leave without marking where you are, you'll never find it again.

This happens when you git checkout <commit-hash> or git checkout v1.0.0 (a tag). It's useful for inspecting old code. But if you make new commits here and then git checkout main, those commits become unreachable — "dangling commits" that Git will eventually garbage-collect.

Fix: before switching away, run git branch my-save-branch to create a branch pointing to where you are. Now it's safe.

Key Facts
  • Triggered by: git checkout <commit-hash> or git checkout <tag>
  • Safe for browsing old code. Risky if you start committing
  • Fix: git branch rescue-branch to save commits, then checkout back to main
  • Git explicitly warns you when you enter detached HEAD state
Competitive Edge

Detached HEAD commits aren't immediately deleted — git reflog keeps them accessible for ~90 days. So even if you accidentally left detached HEAD without creating a branch, you can recover those commits via reflog.

Q18
Git Workflow in Teams
Medium 4 min read
Say this first

Teams use structured workflows — most commonly Git Flow or Trunk-Based Development — to coordinate how branches are created, reviewed, and merged without chaos.

Feature Branch Workflow (most common): Everyone branches off main for their feature, pushes when done, opens a PR, gets code reviewed, then merges back. Main is always deployable.

Git Flow: Has separate main, develop, feature/*, release/*, and hotfix/* branches. Used in projects with scheduled release cycles. More structure, more overhead.

Trunk-Based Development: Everyone pushes small, frequent commits directly to main (or short-lived feature branches that merge daily). Preferred by Google, Facebook, Netflix. Requires good CI/CD and feature flags. Moves fast, less merge pain.

Feature Branch Workflow (Most Common)
main feature/my-feature start branch PR merge PR Review
Key Facts
  • Feature Branch: branch off main → work → PR → review → merge — simple and universal
  • Git Flow: structured with develop/release branches — good for release cycles
  • Trunk-Based: small frequent commits to main — fast, needs CI/CD + feature flags
  • PRs always go through at least one reviewer in real teams
Competitive Edge

Knowing the difference between Git Flow and Trunk-Based Development — and being able to say which one you've used and why — shows genuine team experience. Most candidates only know "we used branches and PRs."

Q19
How do you undo a commit?
Medium 3 min read
Say this first

Depends on whether the commit is local or already pushed. For local: use git reset. For pushed: use git revert to avoid rewriting shared history.

If you just committed locally and want to undo it: git reset --soft HEAD~1 undoes the commit but keeps your changes staged. git reset --mixed HEAD~1 (default) unstages them too but keeps files. git reset --hard HEAD~1 deletes the changes entirely.

If it's already pushed to a shared branch: git revert HEAD creates a new "undo commit" on top. Everyone on the team can pull this cleanly without history conflicts. Never git push --force on shared branches unless you're absolutely sure and have team agreement.

Decision Map
  • Local only, keep changes staged: git reset --soft HEAD~1
  • Local only, unstage changes: git reset --mixed HEAD~1
  • Local only, delete changes: git reset --hard HEAD~1
  • Already pushed, shared branch: git revert HEAD
  • Already pushed, your own branch: git reset + git push --force-with-lease
Traps
  • git push --force on a shared branch can overwrite teammates' commits. Use --force-with-lease instead — it fails if someone else has pushed since your last fetch.
Q20
Code works locally but fails after merge — how to debug?
Hard 4 min read
Say this first

Systematically isolate whether the issue is a merge conflict that wasn't resolved correctly, a dependency difference, an environment difference, or a regression introduced by the merged branch.

This is a classic real-world scenario. First, look at what was actually merged. Run git log --merge to see commits that caused the conflict, or git diff HEAD~1 HEAD to see what changed in the latest merge commit.

Second, check for "resolved" conflicts where someone chose the wrong side. These are the sneakiest bugs — Git shows the conflict as resolved but the logic is now broken. Search the diff for lines around <<<<<<< markers that might've been removed but left incorrect code.

Third, use git bisect — an incredibly powerful command that does a binary search through your commit history to find the exact commit that introduced the bug. You run git bisect start, mark the current commit as bad (git bisect bad), mark a known-good older commit as good (git bisect good <hash>), and Git checks out commits in between for you to test. Takes O(log n) steps to find the culprit.

Debug Checklist
  • git diff main..feature-branch — see all changes that came in
  • Look for incorrectly resolved conflicts — logic broken silently
  • git log --oneline --graph — visualize the merge structure
  • git bisect — binary search to find the exact breaking commit
  • Check environment: env vars, config files, dependencies (package-lock.json changes)
Follow-up Questions
What is git bisect?
git bisect automates binary search through git history to find which commit introduced a bug. You mark a "bad" commit and a "good" commit, and Git checks out the midpoint. You test and mark it good or bad. Repeat until you find the culprit. Much faster than checking each commit manually.
How do you check what changed in a merge commit?
git show <merge-commit-hash> shows the diff. Or git diff HEAD~1 HEAD for the latest. For a merge commit with two parents, git diff HEAD^1 HEAD^2 shows the diff between the two merged branches.
Competitive Edge

Knowing git bisect and being able to explain it clearly — with the analogy of binary search — is something very few junior/mid engineers can do. It genuinely impresses senior interviewers because it shows you debug systematically, not randomly.

Ready to test Git?

Lock in branching, reset/revert, rebase, stash, and collaboration workflows.

Start practice
Home 01. DBMS 02. OOPs 03. Computer Networks 04. Operating System 05. C++ Core 05. Java Core 05. Python Core 06. Puzzles 07. Linux 08. Git 09. SQL 10. Projects 11. System Design 12. DSA Concepts