Core Concepts • Branching and Merging • Rebase • Undo and Recovery • Team Workflow • 2026

Git Interview Questions

30 questions What each one tests, an answer frame, a spoken answer 38 min read

This page is for developers facing a Git round or Git questions inside a wider coding interview, from a first job to a lead role. Most interviewers start with the basics: Git versus GitHub, the staging area and what a commit really is. Then they push on branches, merge versus rebase, conflicts, and how to undo things safely, with reset, revert, stash and reflog. Senior rounds add force pushes, branching strategy, pull request habits and a story about a real mess you cleaned up. Each question shows what the interviewer is checking and an answer you can say out loud.

Search all questions by round, difficulty and level, or save the ones you want to practise.

Git Basics 6 questions

Easy Technical round Fresher Practice question

1. What is the difference between Git and GitHub? Can you use one without the other?

What the interviewer is really testing:
Whether you know Git is a local tool and a hosting service is something built around it, which shapes how you think about offline work and remotes.
Answer frame:

Git: a distributed version control tool that runs on your machine; every clone holds the full history.

GitHub: a hosting service for Git repositories that adds pull requests, reviews, issues, CI and access control.

Independence: Git works fully without any host; GitHub is one of several hosts, next to GitLab, Bitbucket or a plain server.

Sample spoken answer:

"Git is the version control tool itself. It runs on my laptop, and because it's distributed, every clone has the whole history, so I can commit, branch, look at logs and diff old versions with no network at all. GitHub is a hosting service built around Git. It stores a copy of the repository on a server and adds the team features: pull requests and code review, issues, permissions, and CI through Actions. So yes, I can use Git without GitHub, for a personal project or with another host like GitLab or Bitbucket, or even a bare repository on a shared server. Using GitHub without Git doesn't really make sense, because what GitHub hosts is a Git repository. The web editor just makes Git commits for you."

Red flag to avoid:

Treating Git and GitHub as the same thing, or saying you need an internet connection to commit.

They may ask next:
  • What does 'distributed' actually buy you compared with a central version control system?
  • If the GitHub server lost your repository tomorrow, what would you still have?
Say it in 60 seconds
Easy Technical round Fresher, Mid-level Practice question

2. Walk me through the working tree, the staging area and the repository. What moves a change from one to the next?

What the interviewer is really testing:
Whether you have the three-area model that makes status, diff, add, commit and reset make sense instead of feeling like magic.
Answer frame:

Working tree: the files you edit on disk.

Index (staging area): the exact snapshot the next commit will contain; git add copies changes into it.

Repository: the .git folder with all commits; git commit turns the index into a permanent commit.

Seeing the gaps: git diff is working tree versus index, git diff --staged is index versus the last commit.

Sample spoken answer:

"There are three places a change can be. The working tree is just my files on disk, where I edit. The index, or staging area, is the draft of my next commit. When I run git add, Git copies the current content of that file into the index. Then git commit takes whatever is in the index and saves it as a commit in the repository, which is the .git folder. The useful part is that the index lets me commit only part of my work. If I fixed a bug and also tidied some formatting, I can stage just the bug fix, even just some hunks with git add -p, and commit that alone. To see where things are, git status shows all three, git diff shows what I changed but haven't staged, and git diff --staged shows what's about to be committed."

Code:
git status              # what differs in each area
git diff                # working tree vs index
git add -p src/cart.js  # stage only some hunks
git diff --staged       # index vs last commit
git commit -m "Fix rounding in cart total"
Red flag to avoid:

Thinking git commit saves whatever is in your files right now, rather than what is in the index.

They may ask next:
  • If you edit a file after running git add on it, what ends up in the commit?
  • How would you unstage a file without losing your edits?
Say it in 60 seconds
Medium Technical round Fresher, Mid-level Practice question

3. What is a Git commit under the hood? Is it a diff or a snapshot?

What the interviewer is really testing:
Whether you understand that commits are immutable, hash-named snapshots with parents, which explains why amend and rebase create new commits.
Answer frame:

Snapshot: a commit points to a tree that describes the whole project at that moment, not a list of changes.

Metadata: it also records its parent commit or commits, author, committer, time and message.

Hash: the commit is named by a hash of all that content, so changing anything gives a new commit.

Storage: unchanged files are shared between commits, and packfiles compress similar objects, so snapshots stay cheap.

Sample spoken answer:

"Conceptually a commit is a snapshot, not a diff. It points to a tree object, which lists every file and folder in the project at that moment, and the files themselves are stored as blobs. On top of that it records its parent, or two parents for a merge, the author and committer with timestamps, and the message. The whole thing is hashed, and that hash is the commit's ID. Because the parent is part of what gets hashed, each commit locks in the full history behind it. That's why commits are effectively immutable: if I amend a message or rebase, I don't change a commit, I create a new one with a new hash. Diffs you see in git log or git show are computed on the fly by comparing snapshots. It stays space-efficient because an unchanged file is the same blob in every commit, and packfiles compress similar content."

Red flag to avoid:

Saying a commit stores only the lines that changed, or that you can edit an existing commit in place.

They may ask next:
  • Why does rebasing change every commit hash after the first rewritten one?
  • What are blobs and trees, and why doesn't a blob store the file name?
Say it in 60 seconds
Easy Technical round Fresher, Mid-level Practice question

4. You're halfway through a change and need to switch branches to fix something urgent. How does git stash help, and what are its gotchas?

What the interviewer is really testing:
Whether you use stash sensibly and know what it leaves behind, especially untracked files.
Answer frame:

Save: git stash push -m "msg" shelves tracked changes, staged and unstaged, and cleans the working tree.

Untracked files: not included unless you add -u.

Restore: pop applies and drops the entry; apply keeps it; on a conflict, pop keeps the entry too.

Alternative: a quick wip commit on the branch is often safer for anything long-lived.

Sample spoken answer:

"Stash takes my uncommitted changes, saves them on a stack, and gives me a clean working tree, so I can switch branches and fix the urgent thing. When I'm back, git stash pop puts the changes back and removes the entry. There are a few gotchas. By default it only stashes tracked files, so a brand new file I haven't added stays behind in the working tree; I use -u to include untracked files. If popping causes a conflict, Git keeps the stash entry so nothing's lost, and I resolve and drop it myself. And stashes pile up with vague names, so I always add a message with -m. For anything I'll be away from for more than an hour, I honestly prefer a quick 'wip' commit on my branch and amending it later, because a commit lives on a branch and is harder to forget about than an old stash entry."

Code:
git stash push -u -m "half-done filter panel"
git switch hotfix/login-timeout
# ...fix, commit, push...
git switch feature/filters
git stash list
git stash pop
Red flag to avoid:

Assuming stash saves brand new untracked files by default, or treating the stash as long-term storage.

They may ask next:
  • What is the difference between git stash pop and git stash apply?
  • How would you turn a stash into its own branch?
Say it in 60 seconds
Easy Technical round Fresher, Mid-level Practice question

5. How do tags differ from branches, and what is the difference between a lightweight and an annotated tag?

What the interviewer is really testing:
Whether you know how releases are marked in Git and the small details that trip people up, like tags not being pushed by default.
Answer frame:

Tag vs branch: both point at a commit, but a tag is meant to stay put while a branch moves with new commits.

Lightweight: just a name for a commit, nothing else.

Annotated: a full object with tagger, date and message, and it can be signed; the right choice for releases.

Pushing: a plain git push doesn't send tags; push them by name or with --tags.

Sample spoken answer:

"A branch and a tag both point at a commit. The difference is that a branch moves forward every time someone commits on it, while a tag is meant to stay fixed, so it's how we mark releases like v1.4.0. There are two kinds. A lightweight tag is only a name pointing at a commit, fine for a private bookmark. An annotated tag is a proper object stored in the repository, with who created it, when, and a message, and it can be signed so people can verify it. For releases I always use annotated tags. One thing that catches people: a normal git push doesn't send tags. I push the tag by name, or use --tags. And moving a published tag is a bad idea, because anyone who already fetched it keeps the old one, so if a release was wrong I cut a new version instead."

Code:
git tag -a v1.4.0 -m "Release 1.4.0"
git push origin v1.4.0
git tag -l "v1.*"            # list matching tags
Red flag to avoid:

Thinking tags are pushed automatically, or treating a tag like a branch you keep committing to.

They may ask next:
  • How would you check out the exact code that shipped in v1.3.2?
  • Why is re-pointing a tag that others have fetched a problem?
Say it in 60 seconds
Medium Coding round Fresher, Mid-level Practice question

6. You added a file to .gitignore but Git still shows changes to it. Why, and how do you fix it?

What the interviewer is really testing:
Whether you know .gitignore only affects untracked files, and the side effect of untracking a file on teammates' machines.
Answer frame:

Cause: .gitignore only stops untracked files from being added; a file already tracked stays tracked.

Fix: git rm --cached <file> removes it from the index but keeps it on disk; commit that with the ignore rule.

Side effect: when teammates pull that commit, Git deletes the file from their working trees, so warn them.

Debug: git check-ignore -v <file> shows which rule matches.

Sample spoken answer:

"The .gitignore file only applies to untracked files. It tells Git not to pick up new files that match. If the file was committed before the rule existed, Git is already tracking it and keeps showing changes. To fix it, I run git rm --cached on the file. That removes it from the index, so it'll be deleted from the repository in the next commit, but it stays on my disk. I commit that together with the .gitignore change. There's one side effect to warn the team about: when they pull that commit, Git removes the file from their working trees too, so for something like a local config file they should back it up first. And if the file ever held secrets and was pushed, ignoring it now doesn't help, because it's still in history, so the secret needs rotating. For debugging rules, git check-ignore -v tells me exactly which pattern matched a path."

Code:
echo ".env" >> .gitignore
git rm --cached .env      # stop tracking, keep the file on disk
git commit -m "Stop tracking .env"
git check-ignore -v .env  # shows the matching rule
Red flag to avoid:

Expecting .gitignore to affect files already tracked, or deleting the file from disk to make it disappear.

They may ask next:
  • Where would you put ignore rules that are personal to you and shouldn't be committed?
  • How do you ignore everything in a folder except one file?
Say it in 60 seconds

Branching and Merging 5 questions

Medium Technical round Fresher, Mid-level Practice question

7. What actually is a branch in Git, what is HEAD, and what does 'detached HEAD' mean?

What the interviewer is really testing:
Whether you know branches are just movable pointers, which is the key to understanding reset, rebase and why commits can seem to vanish.
Answer frame:

Branch: a named pointer to one commit; committing moves it forward. That's why branches are cheap.

HEAD: points to the branch you're on, so Git knows which pointer to move on the next commit.

Detached HEAD: HEAD points straight at a commit, for example after checking out a tag or hash.

The risk: commits made while detached belong to no branch; create one with git switch -c to keep them.

Sample spoken answer:

"A branch is just a name that points to one commit. Internally it's a tiny file holding a commit hash. When I commit on that branch, Git makes the new commit with the old tip as its parent and moves the pointer forward. That's why creating a branch is instant: it's not a copy of anything. HEAD tells Git where I am. Normally it points to a branch, like main, so a new commit moves main. Detached HEAD means HEAD points directly at a commit instead of a branch, which happens if I check out a tag or an old hash to look around. I can still commit there, but no branch moves, so if I switch away those commits aren't on any branch and are easy to lose. If I want to keep them, I run git switch -c with a new branch name right there. And if I already switched away, the reflog still has the hash."

Red flag to avoid:

Describing a branch as a separate copy of the code, or saying detached HEAD means the repository is broken.

They may ask next:
  • Where does Git store a branch, and what is inside that file?
  • You made three commits in detached HEAD and switched back to main. How do you get them back?
Say it in 60 seconds
Easy Technical round Fresher, Mid-level Practice question

8. What is a fast-forward merge, and why might a team turn it off with --no-ff?

What the interviewer is really testing:
Whether you can predict what a merge will do to history and know the trade-off between a tidy line and a visible record of each feature.
Answer frame:

Fast-forward: the target branch has no new commits since you branched, so Git just moves its pointer to your tip. No merge commit.

Merge commit: when both sides moved, Git makes a commit with two parents.

--no-ff: forces a merge commit even when a fast-forward is possible, so each feature stays grouped and easy to revert as one unit.

--ff-only: the opposite guard: merge only if it can fast-forward, otherwise stop.

Sample spoken answer:

"A fast-forward happens when the branch I'm merging into hasn't moved since I branched off. Say main is at commit A, I branch, and add B and C. If nobody touched main, merging my branch doesn't need a new commit, because C already contains everything. Git just slides main forward to C. The history stays a straight line. Some teams use --no-ff to always create a merge commit anyway. The benefit is that the history shows 'feature X came in here', all its commits hang off that merge, and if the feature has to come out, I can revert that one merge commit. The cost is more merge commits in the log. There's also --ff-only, which I like for pulling main: it refuses to merge if my local branch has diverged, so I never get a surprise merge commit."

Code:
git switch main
git merge --ff-only feature/search   # only if main hasn't moved
git merge --no-ff feature/search     # always record a merge commit
Red flag to avoid:

Saying a fast-forward merge creates a merge commit, or not knowing when Git can fast-forward.

They may ask next:
  • After a fast-forward merge, how could you tell from the log which commits came from the feature branch?
  • How is a squash merge different from both of these?
Say it in 60 seconds
Medium Technical round Fresher, Mid-level, Senior Practice question

9. Merge or rebase: how does each one bring your feature branch up to date with main, and when do you pick which?

What the interviewer is really testing:
Whether you understand what each does to history and commit hashes, and can make a sensible team choice rather than a tribal one.
Answer frame:

Merge: keeps both histories and adds a merge commit with two parents; nothing existing is rewritten.

Rebase: replays your commits one by one on top of the new base, creating new commits with new hashes and a straight line.

Conflicts: a merge surfaces them once; a rebase can surface them per replayed commit.

When: rebase your own unshared work for a clean history; merge when the branch is shared or you want the true record.

Sample spoken answer:

"Both get main's changes into my branch, but they shape history differently. A merge takes the two tips and creates a merge commit with two parents. Nothing that already exists changes, so it's safe on any branch, and the log shows what really happened, but it can get noisy with lots of 'merge main into feature' commits. A rebase takes my commits, sets them aside, moves my branch to the tip of main, and replays them one by one. The result looks like I started from the latest main, a clean straight line, but every replayed commit is new with a new hash. If there are conflicts, I may resolve them commit by commit. My rule is simple: I rebase my own branch while nobody else is building on it, to keep it tidy before review. Once a branch is shared, I merge, because rewriting commits other people have makes a mess for them."

Code:
git fetch origin
# option 1: merge main into my branch
git merge origin/main
# option 2: replay my commits on top of main
git rebase origin/main
Red flag to avoid:

Saying rebase is always better because it looks cleaner, without mentioning that it rewrites commits.

They may ask next:
  • Why do you have to force push after rebasing a branch you already pushed?
  • What is the downside of a perfectly linear history when you're debugging later?
Say it in 60 seconds
Medium Coding round Fresher, Mid-level Practice question

10. You run a merge and Git reports a conflict in two files. Talk me through exactly what you do next.

What the interviewer is really testing:
Whether you can resolve conflicts calmly and correctly, including checking the result actually works, not just deleting markers.
Answer frame:

Find: git status lists the unmerged paths.

Understand: read both sides between the markers and work out what each change was for.

Resolve: edit to the correct combined result, remove the markers, run the tests.

Finish or back out: git add then git commit, or git merge --abort to return to where you started.

Sample spoken answer:

"First I run git status to see which files are unmerged. In each file, Git has put conflict markers: the part between the opening marker and the equals line is my side, HEAD, and the part after is the incoming branch. I don't just pick one side. I read both and figure out what each change was trying to do, and if it's not obvious I look at the commits on each side or ask the person who wrote them. Then I edit the file to what the combined code should be, delete all the markers, and search for any stray ones. Before committing I build and run the tests, because a file can merge cleanly and still be broken. Then git add on each resolved file and git commit to finish the merge. If I realise it's messier than I thought, git merge --abort puts me back exactly where I was before the merge."

Code:
git merge feature/login
# CONFLICT (content): Merge conflict in src/auth.js
git status                 # lists unmerged paths
# edit src/auth.js: keep the right lines, remove the markers
npm test
git add src/auth.js src/session.js
git commit                 # completes the merge

# changed your mind?
git merge --abort
Red flag to avoid:

Resolving by blindly keeping 'mine' or 'theirs' everywhere, or committing without running the code.

They may ask next:
  • How is resolving a conflict during a rebase different from during a merge?
  • How would you take the other branch's version of one whole file without editing it by hand?
Say it in 60 seconds
Hard Technical round Mid-level, Senior Practice question

11. How does Git decide whether two changes conflict? What role does the merge base play?

What the interviewer is really testing:
Whether you understand the three-way merge well enough to predict conflicts, and know that a clean merge is not proof of correct code.
Answer frame:

Merge base: the best common ancestor of the two branches (git merge-base).

Three-way compare: Git diffs base to ours and base to theirs; a region changed on only one side is taken automatically.

Conflict: both sides changed the same region differently; identical changes on both sides are fine.

Blind spot: changes to different lines can merge cleanly and still break, so tests decide, not Git.

Sample spoken answer:

"Git compares each branch tip to their common ancestor, the merge base. That's the three-way merge. For each part of a file, if only my side changed it compared to the base, Git takes my version. If only their side changed it, Git takes theirs. If both sides made the identical change, that's fine too. It's only a conflict when both sides changed the same region in different ways, because Git has no way to know which is right. That model also explains the blind spot: Git works on text, not meaning. If I rename a function on my branch and a teammate adds a new call to the old name in a different file, the merge is perfectly clean and the build is broken. So a clean merge tells me there's no textual overlap, and the tests tell me if it works. I also like the diff3 conflict style, which shows the base version inside the markers."

Code:
git merge-base main feature/pricing   # the common ancestor
git config --global merge.conflictStyle diff3
Red flag to avoid:

Saying Git conflicts whenever both branches touch the same file, or trusting a clean merge without testing.

They may ask next:
  • Why can a long-lived branch produce far more conflicts than the same work merged in small pieces?
  • What example have you seen of a merge that was clean but still wrong?
Say it in 60 seconds

Rewriting History 4 questions

Medium Technical round Mid-level, Senior Practice question

12. Why do people say never rebase a branch others are working on? What exactly goes wrong?

What the interviewer is really testing:
Whether you understand the mechanics behind the rule, not just the slogan, and know when rewriting is actually fine.
Answer frame:

Rewrite: rebase replaces commits with new ones that have different hashes.

Others' copies: teammates still have the old commits, and their work is built on them.

Fallout: you must force push; they get diverged branches, duplicate commits or lost work when they sync.

Where it's fine: your own branch that nobody has pulled or built on, with the team's agreement.

Sample spoken answer:

"Rebase doesn't move commits, it makes new copies with new hashes and drops the old ones from the branch. On my own branch that's harmless. But say I rebase a branch two teammates have pulled, and force push it. Their local branches still point at the old commits, and anything they committed since is built on top of those. When they pull, Git sees two different histories with the same changes in different commits. Depending on what they do, they get a merge that brings the old commits back next to the new ones, so every change appears twice, or they reset to the remote and lose their own work. Either way someone spends an afternoon untangling it. So the real rule is: don't rewrite commits that other people have based work on. Rebasing my feature branch before I open the pull request, or while I'm the only one pushing to it, is fine and I do it all the time."

Red flag to avoid:

Reciting 'never rebase public branches' without being able to explain why commit hashes changing causes the problem.

They may ask next:
  • If a teammate has already rebased a shared branch, how do you safely get your work onto the new version?
  • Does the same rule apply to git commit --amend? Why?
Say it in 60 seconds
Medium Coding round Mid-level, Senior Practice question

13. Your feature branch has twelve messy commits like 'wip' and 'fix typo'. How do you clean them up before opening a pull request?

What the interviewer is really testing:
Whether you can use interactive rebase confidently and know the safety steps around rewriting a pushed branch.
Answer frame:

Interactive rebase: git rebase -i origin/main opens the list of your commits, oldest first.

Actions: pick keeps, squash or fixup folds into the one above, reword edits a message, lines can be reordered or dropped.

Aim: a few commits that each make sense on their own, with clear messages.

Pushing: the hashes changed, so push with --force-with-lease, and only on your own branch.

Sample spoken answer:

"I use an interactive rebase. I fetch first, then run git rebase -i against origin/main, so it covers exactly the commits on my branch and also puts them on top of the latest main. Git opens a list of my commits, oldest at the top. I keep the meaningful ones as pick, mark the 'wip' and 'fix typo' ones as fixup so they fold into the commit above them and their messages disappear, and use reword where a message needs fixing. I can also reorder lines to group related changes. I'm aiming for a handful of commits that each tell one part of the story. When I save, Git replays them. Because the hashes are new, I push with --force-with-lease, which is fine since it's my branch and nobody's built on it. Going forward, git commit --fixup plus rebase with --autosquash saves me doing this by hand."

Code:
git fetch origin
git rebase -i origin/main
# in the editor (oldest first):
# pick   a1b2c3d Add search endpoint
# fixup  d4e5f6a wip
# fixup  0718293 fix typo
# reword 9a8b7c6 add paging
git push --force-with-lease
Red flag to avoid:

Cleaning up with rebase on a shared branch and plain force push, or not knowing how to get out with git rebase --abort.

They may ask next:
  • What is the difference between squash and fixup?
  • Your team squash-merges every pull request anyway. Is cleaning up commits still worth it?
Say it in 60 seconds
Easy Coding round Fresher Practice question

14. You just committed and realise the message has a typo and you forgot to add one file. How do you fix it?

What the interviewer is really testing:
Whether you know amend, and that it replaces the commit rather than editing it, which matters once you've pushed.
Answer frame:

Stage the missing file: git add it first.

Amend: git commit --amend replaces the last commit with one that has the new content and message.

New hash: amend makes a new commit, so if it was pushed you'd need a force push; on a shared branch, make a new commit instead.

Sample spoken answer:

"If I haven't pushed yet, it's one command. I git add the file I forgot, then run git commit --amend with the corrected message. That replaces my last commit with a new one containing both the original changes and the file, with the fixed message. If the message was fine and I only forgot the file, I add --no-edit so it keeps the old message. The thing to remember is that amend doesn't edit the commit, it creates a new one with a new hash. So if I'd already pushed, the remote has the old commit and a normal push would be rejected. On my own feature branch I'd amend and push with --force-with-lease. If other people might have pulled it, I'd leave history alone and just make a small follow-up commit adding the file."

Code:
git add src/config/defaults.js
git commit --amend -m "Add retry settings to API client"
# keep the old message:
git commit --amend --no-edit
Red flag to avoid:

Not realising amend changes the commit hash, and amending commits on a shared branch.

They may ask next:
  • How would you fix a typo in a commit message three commits back?
  • What happens if you amend a commit that is already on the remote and then run a plain git push?
Say it in 60 seconds
Medium Technical round Mid-level, Senior Practice question

15. What does git cherry-pick do, and when is it the right tool versus a merge?

What the interviewer is really testing:
Whether you know cherry-pick copies a change as a new commit, and can name the real uses and the cost of duplicated commits.
Answer frame:

What it does: applies the changes from one existing commit onto your current branch as a brand new commit.

Good uses: backporting a fix to a release branch, rescuing a commit made on the wrong branch.

Cost: the same change now exists as two commits with different hashes, which can confuse history and cause later conflicts.

Tip: -x records the original hash in the message so people can trace it.

Sample spoken answer:

"Cherry-pick takes the change introduced by one commit, the diff between it and its parent, and applies it on my current branch as a new commit. It's the same change, but a different commit with a different hash. The classic use is a hotfix: we fix a bug on main and also need it on the release branch that's already in testing, but we can't merge main there because it would drag in unfinished features. So I switch to the release branch and cherry-pick just the fix. I use -x so the message records which commit it came from. Another use is when I committed on the wrong branch and want to move that one commit. I don't use it as a substitute for merging whole features, because you end up with duplicate commits all over the place, and when the branches are merged later, Git may have to reconcile the same change twice."

Code:
git switch release/2.4
git cherry-pick -x 4e1c9a2
# on conflict: fix, git add, then
git cherry-pick --continue
Red flag to avoid:

Thinking cherry-pick moves the original commit, or using it routinely to sync long-lived branches.

They may ask next:
  • How would you cherry-pick a range of commits, and is the first one included?
  • What happens if you cherry-pick a merge commit?
Say it in 60 seconds

Undoing Changes 4 questions

Medium Technical round Fresher, Mid-level Practice question

16. Explain git reset with --soft, --mixed and --hard. What does each one leave behind?

What the interviewer is really testing:
Whether you can use reset precisely and know which mode can destroy work.
Answer frame:

All three: move the current branch pointer to the commit you name.

--soft: stops there; index and files untouched, so the undone changes show as staged.

--mixed (default): also resets the index; your files keep the changes, now unstaged.

--hard: also resets the working tree; uncommitted changes are gone for good.

Sample spoken answer:

"All three modes start the same way: they move the branch I'm on back to the commit I give, say HEAD~1. The difference is how far the reset spreads into the other two areas. With --soft, it only moves the branch. My index and files stay as they were, so the changes from the undone commit show up as staged, ready to recommit. I use that to redo a commit or combine the last few into one. --mixed is the default. It also resets the index, so the changes are still in my files but unstaged. Good for splitting a commit differently. --hard also resets the working tree to match, so everything since that commit is thrown away, including any edits I hadn't committed. Committed work can usually be found again through the reflog, but uncommitted changes wiped by --hard are usually gone for good. So I run git status before any hard reset."

Code:
git reset --soft HEAD~1   # undo commit, changes stay staged
git reset HEAD~1          # mixed: undo commit, changes unstaged
git reset --hard HEAD~1   # undo commit and discard the changes
Red flag to avoid:

Not knowing that --hard discards uncommitted work, or not knowing which mode is the default.

They may ask next:
  • How would you squash your last three commits into one using reset?
  • You ran reset --hard by mistake. What can you get back and what can't you?
Say it in 60 seconds
Easy Technical round Fresher, Mid-level Practice question

17. When would you use git revert instead of git reset to undo a commit?

What the interviewer is really testing:
Whether you know the one rule that keeps shared history safe: undo pushed commits by adding a commit, not by removing one.
Answer frame:

reset: moves the branch back, so the commits disappear from it; history is rewritten.

revert: adds a new commit that applies the opposite of the old one; history only grows.

Rule: reset for local, unpushed work; revert for anything already shared.

Sample spoken answer:

"They undo things in opposite ways. Reset moves my branch pointer backwards, so the commits I reset past are no longer on the branch. That's rewriting history, which is fine when the commits only exist on my machine. Revert doesn't remove anything. It creates a new commit that does the exact opposite of the one I'm undoing, so the bad change is cancelled but both commits stay in the history. That's what I use once a commit has been pushed to a shared branch like main. Everyone can just pull the revert like any other commit, nobody's history breaks, and there's a clear record that the change was backed out and why. If I reset and force pushed main instead, I'd be pulling commits out from under everyone who already has them."

Code:
git revert 7d3f0b1          # new commit that undoes 7d3f0b1
git revert --no-edit HEAD   # undo the latest commit
Red flag to avoid:

Suggesting reset plus force push to undo a commit that's already on main.

They may ask next:
  • Can you revert a revert, and why might you want to?
  • How do you revert several commits in one go?
Say it in 60 seconds
Hard Technical round Mid-level, Senior Practice question

18. A feature branch was merged into main and pushed, and now it has to come out. How do you undo a merge commit safely?

What the interviewer is really testing:
Whether you know revert -m for merges and the trap it leaves when the same branch is merged again later.
Answer frame:

Revert the merge: git revert -m 1 <merge>; -m 1 says the first parent, main, is the line to keep.

Why -m: a merge has two parents, so Git needs to know which side to undo against.

The trap: Git still considers the branch merged, so merging it again later won't bring those changes back.

Re-landing: revert the revert first, then merge the fixes.

Sample spoken answer:

"Because main is shared, I revert rather than reset. A merge commit has two parents, so a plain revert doesn't know which side to go back to. I run git revert -m 1 with the merge hash. Parent one is the branch that was merged into, main, so this says: make main look like it did before the feature came in. That lands as a normal new commit everyone can pull. The part people miss comes later. The feature's commits are still in main's history, the revert just cancelled their effect. So when the team fixes the feature and merges the same branch again, Git sees those old commits as already merged and only brings in the new fixes, and the original code stays missing. The fix is to revert the revert first, which restores the feature's changes, and then merge the new work on top."

Code:
git log --merges --oneline -5     # find the merge commit
git revert -m 1 b8e21f4
git push origin main

# later, when the feature is ready again:
git revert <hash-of-that-revert>
Red flag to avoid:

Resetting main and force pushing, or not knowing why re-merging the branch later won't restore the feature.

They may ask next:
  • How do you check which parent is number one before you revert?
  • Would your answer change if the pull request had been squash-merged?
Say it in 60 seconds
Medium Situational round Fresher, Mid-level, Senior Practice question

19. You merged your pull request, and ten minutes later main is red and the team can't deploy. What do you do?

What the interviewer is really testing:
Whether you restore the team first, undo safely with revert rather than rewriting main, and follow up properly.
Answer frame:

Own it: tell the team straight away that it's your merge and you're on it.

Unblock: if the fix isn't obvious within minutes, revert the merge with a new commit; never reset and force push main.

Fix forward: find the cause on your branch, add a test that would have caught it, and re-land.

Learn: ask why CI or review didn't catch it and close that gap.

Sample spoken answer:

"First I'd post in the team channel that it's my merge and I'm looking at it, so nobody else wastes time investigating. Then I'd check whether it's a one-line obvious fix. If it isn't clear within a few minutes, I'd revert. If it was a merge commit, that's git revert -m 1 on the merge; if it was squash-merged, a plain revert of that commit. I'd push the revert through the normal path, so main goes green and people can deploy again. I wouldn't reset main and force push, because others have already pulled it. Then, with no pressure, I'd find the cause on my branch. Often it's something that passed on my branch but conflicts with what landed on main in between. I'd add a test that fails without the fix, re-open the pull request, and afterwards ask whether our checks should run against the latest main before merging."

Red flag to avoid:

Resetting main and force pushing, or quietly trying fixes on main while everyone stays blocked.

They may ask next:
  • Your teammate says 'just fix it forward, don't revert'. When would you agree?
  • How could the team stop a green pull request from breaking main after merging?
Say it in 60 seconds

Remotes 3 questions

Easy Technical round Fresher, Mid-level Practice question

20. What is the difference between git fetch and git pull, and why do some developers avoid pull?

What the interviewer is really testing:
Whether you know about remote-tracking branches and can update safely without surprise merges.
Answer frame:

fetch: downloads new commits and updates remote-tracking branches like origin/main; your branches and files don't change.

pull: a fetch followed by integrating the remote branch into yours, by merge or rebase.

Why fetch first: you can look at what changed before deciding how to combine it.

Config: setting pull.rebase to true, or pull.ff to only, makes pull behave predictably.

Sample spoken answer:

"git fetch talks to the remote, downloads any new commits, and updates my remote-tracking branches, like origin/main. It doesn't touch my own branches or my files, so it's always safe to run. git pull is a fetch plus a second step that integrates the remote branch into my current branch, by default with a merge, or with a rebase if I pass --rebase or set it in config. Some developers avoid pull because that second step can surprise you: if your branch and the remote both have new commits, you get an automatic merge commit or a conflict you weren't expecting. Recent versions of Git refuse and tell you to choose merge or rebase when the branches have diverged and you haven't configured it. I usually fetch, look at git log HEAD..origin/main to see what came in, then rebase or merge deliberately."

Code:
git fetch origin
git log --oneline HEAD..origin/main   # what's new on the remote
git rebase origin/main
# or set a default once:
git config --global pull.rebase true
Red flag to avoid:

Saying fetch and pull are the same, or that fetch changes your working files.

They may ask next:
  • What is origin/main, and how is it different from main?
  • What does git pull --rebase do when your local branch has two commits the remote doesn't?
Say it in 60 seconds
Medium Technical round Fresher, Mid-level Practice question

21. You try to push and get 'rejected, non-fast-forward'. What does it mean and how do you fix it properly?

What the interviewer is really testing:
Whether you integrate first instead of reaching for force push, which is the habit that protects teammates' work.
Answer frame:

Meaning: the remote branch has commits you don't have, so your push would drop them.

Wrong fix: force pushing, which deletes their commits from the remote.

Right fix: fetch, then rebase onto or merge the remote branch, resolve, test, push again.

Sample spoken answer:

"It means someone pushed to that branch after I last synced. My branch and the remote have diverged, so if Git accepted my push, the remote branch would jump to my commit and their commits would drop off it. Git refuses rather than lose work. The wrong fix is adding --force, because that's exactly what deletes their commits. The right fix is to bring their work in first. I run git fetch, check what came in, then either rebase my commits on top of origin's version, which is what I do on a feature branch to keep it tidy, or merge it if that's the team's habit. git pull --rebase does both steps in one. If there are conflicts I resolve them, run the tests, because their change and mine now meet for the first time, and then push again, which goes through as a normal fast-forward."

Code:
git fetch origin
git rebase origin/feature/checkout
# resolve any conflicts, run tests
git push origin feature/checkout
Red flag to avoid:

Immediately suggesting git push --force to make the error go away.

They may ask next:
  • When is it acceptable to get this error and force push anyway?
  • Why run the tests again after a rebase that had no conflicts?
Say it in 60 seconds
Hard Technical round Mid-level, Senior Practice question

22. What is the difference between git push --force and --force-with-lease, and is --force-with-lease completely safe?

What the interviewer is really testing:
Whether you understand what the lease checks and its blind spot, which separates people who've been burned from people who've read a blog post.
Answer frame:

--force: overwrites the remote branch with yours no matter what is there now.

--force-with-lease: only overwrites if the remote still points where your origin/<branch> says it did; otherwise it refuses.

Blind spot: a background fetch updates origin/<branch> without you looking, so the lease passes and can still drop new commits.

Extra guards: --force-if-includes, and protected branches that block force pushes to main.

Sample spoken answer:

"Plain --force says: make the remote branch equal to mine, whatever's there. If a teammate pushed five minutes ago, their commits are gone from the remote. --force-with-lease adds a check. It compares the remote branch with my remote-tracking ref, origin slash that branch, which is what I last saw. If the remote has moved since, it refuses, so I don't overwrite work I haven't seen. That's why I use it after rebasing my own branch. It isn't perfectly safe, though. The check is against my last fetch, not against what I actually looked at. If my editor fetches in the background, origin's ref updates to include the teammate's commit, the lease passes, and I overwrite it anyway. The --force-if-includes option closes that gap by also checking that the remote tip I last fetched is something I actually integrated into my local branch. And for main and release branches, the real protection is branch protection on the server, so nobody can force push there at all."

Code:
git push --force-with-lease origin feature/billing
# stricter: also require that you've integrated the remote tip
git push --force-with-lease --force-if-includes origin feature/billing
Red flag to avoid:

Calling --force-with-lease completely safe, or using plain --force on shared branches as a habit.

They may ask next:
  • If your force push did drop a teammate's commit, how would you get it back?
  • Which branches in your team should never accept a force push, and how do you enforce that?
Say it in 60 seconds

Recovery 3 questions

Hard Technical round Mid-level, Senior Practice question

23. You ran git reset --hard and three commits disappeared from your branch. How do you get them back?

What the interviewer is really testing:
Whether you know the reflog, understand that commits outlive the branch pointer, and know the limits of recovery.
Answer frame:

Commits survive: reset only moved the pointer; unreferenced commits stay in the repository for a while.

Reflog: git reflog lists every position HEAD has been in, with the hash before the reset.

Recover: pin the hash with a new branch first, then reset or merge back.

Limits: the reflog is local and entries expire; uncommitted changes wiped by --hard were never commits and aren't in it.

Sample spoken answer:

"The commits aren't gone, the branch just stopped pointing at them. Git keeps unreferenced commits around until garbage collection eventually cleans them up, and the reflog records every place HEAD has pointed, locally. So I run git reflog and look for the line just before the reset, something like 'commit: add export'. That hash is my old tip. Before doing anything clever I pin it by creating a branch at that hash, so it can't be lost again. Then I can reset my branch back to it, or merge it. The same trick recovers a deleted branch or commits made in detached HEAD. The limits matter. The reflog exists only on my machine, it's not pushed, and old entries expire. And if the reset --hard also wiped changes I never committed, the reflog can't help, because those were never commits. If they had been staged, git fsck can sometimes find the loose file content, but that's a last resort."

Code:
git reflog
# 3f9e2a1 HEAD@{0}: reset: moving to HEAD~3
# 8c4d7b0 HEAD@{1}: commit: Add CSV export
git branch rescue 8c4d7b0   # pin the lost work first
git reset --hard rescue     # move my branch back to it
Red flag to avoid:

Saying the commits are permanently gone, or not knowing the reflog exists.

They may ask next:
  • How would you find a branch you deleted last week?
  • Why can't you recover a teammate's lost commits from your own reflog?
Say it in 60 seconds
Hard Situational round Mid-level, Senior Practice question

24. You notice you pushed a commit containing a live API key to the shared repository an hour ago. Walk me through your response.

What the interviewer is really testing:
Whether you treat it as a security incident first and a Git problem second, and know that deleting it in a new commit is not enough.
Answer frame:

Contain first: revoke or rotate the key immediately; assume it's already been copied.

Tell people: inform your lead or security contact and check the key's usage logs.

Clean up: remove it from the code, load it from the environment or a secrets manager, and ignore the file.

History: a new commit leaves it in history; rewriting with a tool like git filter-repo needs a coordinated force push, and copies may already exist.

Sample spoken answer:

"The first step isn't a Git command, it's revoking the key. Once it's been pushed, I have to assume someone has it, especially on a public repository, where automated scanners look for exactly this. So I'd rotate it with the provider, update the running services with the new key, and tell my lead or the security team, and check the provider's logs for any use I don't recognise. Then the code: remove the key, read it from an environment variable or the secrets manager, and add the config file to .gitignore. Deleting it in a new commit doesn't remove it from history, so the old commit still shows it. Whether to rewrite history depends on the team. If we do, I'd use git filter-repo to strip it, force push with everyone warned, and have people re-clone. But clones, forks and caches may still hold it, which is exactly why rotating the key is the real fix and rewriting is just tidying up."

Red flag to avoid:

Deleting the key in a new commit and calling it fixed, or rewriting history before revoking the key.

They may ask next:
  • What would you set up so this can't happen again?
  • If the repository were private and only four people had access, would you still rotate the key?
Say it in 60 seconds
Hard Situational round Mid-level, Senior Practice question

25. A teammate force-pushed the shared feature branch and your two commits from yesterday are gone from the remote. What do you do?

What the interviewer is really testing:
Whether you can recover calmly using your local copy, avoid making it worse with a counter force push, and fix the process without blame.
Answer frame:

Don't overwrite back: a counter force push would drop their new work.

Your copy is safe: your local branch, or its reflog, still has your commits.

Rebuild: fetch, keep a rescue branch, match the new remote, cherry-pick only your commits, push normally.

Fix the cause: talk to the teammate, agree on --force-with-lease or no force pushes on shared branches.

Sample spoken answer:

"First, I don't force push back, because that would wipe whatever they just pushed, and we'd be taking turns deleting each other's work. My commits are almost certainly still on my machine, on my local branch. Even if I'd already pulled, the reflog would have them. So I'd fetch, then create a rescue branch at my current local tip so nothing can be lost. I'd compare it with the new remote to find the commits the remote no longer has and pick out my two. Then I'd reset my local branch to match the new remote and cherry-pick just those two commits on top, run the tests, and push normally, with no force needed. Then I'd talk to the teammate, not to blame them, but because they probably rebased without realising others were pushing to the branch. We'd agree that shared branches never get force pushed, or only with --force-with-lease after a heads-up in the channel."

Code:
git fetch origin
git branch rescue feature/reports        # keep my old copy safe
git log --oneline origin/feature/reports..rescue
git switch feature/reports
git reset --hard origin/feature/reports  # match the new remote
git cherry-pick 2b7c1e0 91fd3a4          # only my two commits
git push origin feature/reports
Red flag to avoid:

Force pushing your version back over theirs, or assuming the commits are lost because the remote no longer has them.

They may ask next:
  • Why not just run git rebase origin/feature/reports on your old branch?
  • How would you check which of the listed commits are yours and which were your teammate's old versions?
Say it in 60 seconds

Team Workflow 3 questions

Medium Technical round Mid-level, Senior Practice question

26. Compare trunk-based development with Git Flow. Which would you choose for a team shipping a web app several times a day?

What the interviewer is really testing:
Whether you can connect a branching model to how the team releases, instead of treating one model as always right.
Answer frame:

Trunk-based: everyone merges small, short-lived branches into main often; unfinished work hides behind feature flags; strong CI is required.

Git Flow: long-lived develop and main branches plus feature, release and hotfix branches; fits scheduled, versioned releases.

Trade-off: fewer, smaller conflicts and faster feedback versus more process and a separate stabilising step.

Choice: for many daily deploys, trunk-based; for boxed releases or several supported versions, something closer to Git Flow.

Sample spoken answer:

"In trunk-based development, main is the one branch that matters. People work on small branches that live a day or two at most, merge them often, and anything unfinished ships switched off behind a feature flag. It needs good automated tests and CI, because main must always be releasable. Git Flow has a develop branch where features collect, release branches where a version is stabilised, main holding what's been released, and hotfix branches for urgent fixes. It fits software that ships as numbered versions on a schedule, like a mobile app or a library where you support several versions at once. For a web app deploying several times a day, I'd pick trunk-based. Git Flow's extra branches slow that down, and long-lived branches are exactly what causes big painful merges. I'd back it with branch protection, required checks on every pull request, and feature flags, so merging often doesn't mean releasing half-built features."

Red flag to avoid:

Calling one model best in all cases, or describing trunk-based as everyone committing untested code straight to main.

They may ask next:
  • What do you need in place before a team can safely move to trunk-based development?
  • How do you handle a hotfix for a version that's already released under trunk-based development?
Say it in 60 seconds
Medium Technical round Fresher, Mid-level, Senior Practice question

27. What makes a good pull request, both as the author and as the reviewer?

What the interviewer is really testing:
Whether you'd be easy to work with in review: small focused changes, clear context and respectful, useful feedback.
Answer frame:

Size: one purpose per pull request, small enough to review properly in one sitting.

Context: title and description say what and why, how to test, and link the ticket; self-review and green CI before asking.

During review: answer every comment, push follow-up commits so reviewers see what changed, don't rewrite history silently.

As reviewer: be prompt and specific, explain why, and mark what blocks versus what's a nit.

Sample spoken answer:

"As an author, the biggest thing is size. One pull request does one thing, so a reviewer can actually read it instead of skimming. The description says what changed, why, and how to test it, with screenshots for UI work and a link to the ticket. I review my own diff first, because I always catch something, and I make sure CI is green before I ask anyone. During review I reply to every comment, even if it's just 'done', and I push fixes as new commits so reviewers can see what changed since last time, rather than force pushing over everything silently. As a reviewer, I try to respond within the day, because a pull request waiting three days turns into a merge conflict. I explain why I'm asking for a change, I separate blocking issues from nits, and I comment on the code, not the person. Approving with small suggestions is fine."

Red flag to avoid:

Seeing review as a formality, or opening huge mixed-purpose pull requests with an empty description.

They may ask next:
  • A pull request comes in with two thousand changed lines. What do you do?
  • How do you handle a reviewer who keeps blocking on personal style preferences?
Say it in 60 seconds
Hard Behavioral round Senior Practice question

28. Tell me about a time you changed how your team used branches, reviews or releases. How did you get people on board?

What the interviewer is really testing:
Whether you can lead a process change with evidence and buy-in, and judge whether it actually worked.
Answer frame:

Problem: the pain the old way caused, with something concrete you observed.

Proposal: what you changed and why that fit the team.

Buy-in: how you handled doubts, trialled it and adjusted.

Outcome: how you knew it worked, and what you'd still change.

Sample spoken answer:

"At my last company we used Git Flow with a develop branch and fortnightly release branches, but we deployed a web app and customers were waiting two weeks for tiny fixes. Worse, release branches regularly needed a day of conflict fixing and cherry-picks. I pulled the last few releases' history and showed the team how much time went into merging rather than building. I proposed trunk-based development: short branches merged to main within a couple of days, feature flags for unfinished work, and main protected, with required CI and one approval. Some people worried about half-built features going live, so we ran it on one service for a month first, with flags and a clear rollback plan, which was just reverting. It worked, merge pain mostly disappeared, and we went from fortnightly releases to deploying most days. Then we rolled it out to the rest. What I'd change is investing in tests earlier, because a flaky suite nearly killed the trial."

Red flag to avoid:

Imposing a new workflow without evidence or a trial, or claiming success with no way of measuring it.

They may ask next:
  • Who pushed back hardest, and what convinced them?
  • What would have made you roll the change back?
Say it in 60 seconds

Real Work 2 questions

Medium Behavioral round Fresher, Mid-level, Senior Practice question

29. Tell me about a time you or a teammate thought work was lost in Git. How did you get it back, and what changed afterwards?

What the interviewer is really testing:
Whether you stay calm under pressure, actually know the recovery tools, and turn an incident into a habit change for the team.
Answer frame:

Situation: what was lost, how, and why it mattered right then.

Action: the steps you took, in order, and why you avoided making it worse.

Result: what was recovered and how long it took.

Change: the habit or guard the team added so it doesn't repeat.

Sample spoken answer:

"In my last job, the evening before a client demo, a teammate ran git reset --hard on the wrong branch and his whole afternoon of commits vanished. He was about to start rewriting. I asked him to stop and not run anything else, because the commits were almost certainly still there. We ran git reflog, found the commit line from just before the reset, and I had him create a branch at that hash first so it was safe, then reset his branch back to it. Everything was back in about ten minutes and the demo went fine. Afterwards we changed two things. We agreed to push feature branches at least daily, so work always lives somewhere besides one laptop. And I did a short session for the team on reflog and on using git status before any hard reset. Since then, when someone panics about lost work, they check the reflog before messaging anyone."

Red flag to avoid:

A story where the fix was luck or re-typing the work, with no understanding of why it was recoverable.

They may ask next:
  • What would you have done if the lost work had never been committed?
  • How do you teach Git recovery to someone who's nervous about the command line?
Say it in 60 seconds
Medium Behavioral round Fresher, Mid-level Practice question

30. Describe a painful merge or rebase you had on a team project. How did you work through it with the other developer?

What the interviewer is really testing:
Whether you handle a technical collision as a collaboration problem, and whether you learned why it happened, not just how to fix it.
Answer frame:

Cause: what made it painful, such as a long-lived branch or overlapping refactors.

Collaboration: how you involved the other person rather than guessing their intent.

Verification: how you proved the combined result worked.

Prevention: what you changed so it didn't happen again.

Sample spoken answer:

"In my final-year project, I spent three weeks on a branch reworking the booking module while a teammate refactored the same service layer for a new feature. Neither of us had merged main in that time. When I tried, there were conflicts in about fifteen files, and in several the right answer needed both our changes combined. Instead of resolving her side by guessing, I asked her to sit with me for an hour. We went file by file: she explained the intent of her changes, I explained mine, and we wrote the combined version together. Then we ran the full test suite and clicked through the booking flow, because a couple of files had merged cleanly but called methods she'd renamed. The lesson was about branch lifetime, not Git. After that we rebased on main every day and split work into smaller pull requests, and we never had a merge like that again."

Red flag to avoid:

Resolving someone else's side without asking, or blaming the teammate instead of the long-lived branch.

They may ask next:
  • Looking back, what warning signs did you miss before the merge?
  • How would you have handled it if the other developer wasn't available?
Say it in 60 seconds
Were you asked something else? Share it A person checks every question before it goes on the site. No name is shown.
For the call itself

The questions above are the prep. The call has ten more.

ClapAssist is an AI interview assistant for Mac and Windows. It listens to the interview on your computer and shows you what to say, in short lines you can read while you talk. Your resume and notes are never stored on our servers. It stays out of screen share on every plan; only you can see it.

Download ClapAssist with 10 free minutes
Mac and Windows · Stays out of screen share · No card