Git Interview Questions and Answers Part 01
30 real-world Git scenario-based interview questions and answers covering branching strategies, merge/rebase, undoing changes, conflict resolution, Git internals, hooks, submodules, security, monorepos, and troubleshooting — Senior DevOps Engineer Edition.
origin is simply a nickname for a remote repository. Git usually assigns this name automatically when you clone a repository, so commands such as git pull origin main know where to get changes from.
It is not a special server or reserved word. You can rename it or add other remotes when a project uses more than one repository.
.gitignore tells Git which files it should not normally show as untracked. It is useful for generated files such as logs, build output, editor settings, caches, and local environment files.
.env
node_modules/
*.log
dist/
One important detail: .gitignore does not remove a file that is already tracked. Remove it from the index first with git rm --cached <file>.
A Version Control System records changes to files over time. It answers practical questions such as: who changed this file, what changed, and which version was working before the last deployment?
Git is a distributed VCS, so each clone contains the project history locally. That makes branching, reviewing history, and working offline fast and reliable.
Git is popular because it makes everyday collaboration safer and easier:
- Developers can work in separate branches without blocking one another.
- Every clone has the history locally, so most operations are fast and work offline.
- Changes can be reviewed, tested, merged, or rolled back in a controlled way.
- It works with small projects, large codebases, and common CI/CD platforms.
- It is open source and supported by nearly every development tool.
Git can merge many changes automatically, but a conflict occurs when it cannot safely decide what the final result should be. Common examples are:
- Two branches edit the same line of a file differently.
- One branch deletes a file that another branch has modified.
At that point Git pauses the operation. A developer must choose the correct content, test it, stage the file, and then finish the merge or rebase.
The index, usually called the staging area, is the draft of the next commit. git add copies selected changes from the working tree into the index; git commit records what is currently in the index.
This lets you create a focused commit even when several unrelated files have changed.
Use git commit --amend when the last commit needs a small correction, such as a missing file or a better message:
- Make your changes to the files.
- Stage them with
git add. - Run the amend command:
git commit --amend
Git will open your default editor to update the commit message. Save and close to apply.
Note: Amending changes the commit ID. Avoid it for a commit that others may already have pulled. If it was pushed, coordinate with the team before force-pushing.
The commands depend on whether the branch is checked out:
git branch -m <new_branch_name>
- Rename a different branch:
git branch -m <old_branch_name> <new_branch_name>
- Push the renamed branch to remote and update tracking:
git push origin -u <new_branch_name>
git push origin --delete <old_branch_name>
The delete command removes the old branch from the remote; it does not delete the new local branch.
| Feature | git fetch | git pull |
|---|---|---|
| Purpose | Downloads changes from the remote but does not apply them | Downloads changes and then integrates them into the current branch |
| Working Directory | No changes — safe to inspect before merging | Changes are applied immediately |
| Use Case | When you want to review changes before merging | When you want to update your branch quickly |
| Workflow | Often followed by git merge or git rebase | Combines fetch + merge in one step |
Using git fetch with manual merge:
git fetch origin
git log origin/main # inspect incoming changes
git merge origin/main # apply after review
Using git pull directly:
git pull origin main
Pull Requests (PRs) give a team a controlled checkpoint before code reaches a shared branch:
- Review: Teammates can catch bugs, unclear code, and missing tests before merging.
- Discussion: Design decisions and requested changes stay attached to the proposed code.
- Automation: CI checks can run against the exact branch being reviewed.
- Traceability: The PR records who reviewed, approved, and merged the change.
git stash puts unfinished changes aside so you can temporarily switch tasks. It is useful when you need to change branches but are not ready to make a commit yet.
| Command | Purpose |
|---|---|
git stash | Save current uncommitted changes |
git stash list | View all saved stashes |
git stash pop | Reapply the most recent stash and remove it from stash list |
git stash apply | Reapply a stash without removing it from history |
git stash drop stash@{n} | Delete a specific stash entry |
Use git revert for a commit that is already shared. It creates a new commit that reverses the earlier change, so everyone keeps the same history:
- Switch to the target branch:
git checkout <branch_name>
- Find the commit hash:
git log
- Revert the commit:
git revert <commit-hash>
Git opens an editor to confirm the revert message. Save and close.
Push the revert commit:
git push origin <branch_name>
Why not
git reset? Reset moves a branch pointer and can make shared commits disappear from the branch. Revert is usually the safer choice for public branches.
| Parameter | git reset | git revert |
|---|---|---|
| History | Moves a branch pointer and can remove commits from its visible history | Creates a new commit that undoes an earlier change |
| Safety | Risky on shared/public branches | Safe to use on shared repositories |
| Use Case | Undoing local, unpushed commits | Undoing commits that are already pushed |
git reflog | git log |
|---|---|
Records movements of HEAD, including resets and branch switches | Displays commits reachable from the selected history |
| Shows references even if they are no longer part of any branch | Only shows commits reachable from the current branch |
| Can help recover lost commits or deleted branches | Does not track changes outside the commit chain |
| Useful for disaster recovery and debugging | Used for reviewing past changes and audit trails |
HEAD tells Git where you are currently working:
- Points to the latest commit on the currently checked-out branch.
- When you switch branches, HEAD automatically updates to the tip of the new branch.
- A detached HEAD state occurs when it points directly to a commit instead of a branch. This is fine for inspecting old code, but create a branch before making work you want to keep.
git tag -a creates an annotated tag, which stores additional metadata alongside the tag reference:
- Tagger’s name and email
- Date and time of tagging
- A custom descriptive message
Create an annotated tag:
git tag -a v1.0 -m "Version 1.0 Release"
Push the tag to remote:
git push origin v1.0
Annotated tags are generally preferred for official releases because the tag records who created it, when, and why.
| Concept | HEAD | Working Tree | Index (Staging Area) |
|---|---|---|---|
| Definition | The commit currently checked out | Your editable project files | The proposed contents of the next commit |
| Contains | Pointer stored in .git/HEAD | Unstaged edits and new files | Changes staged with git add, ready to commit |
| Location | .git/HEAD | Your local project folder | .git/index |
edit files] -->|git add| IDX[Index / staging area] IDX -->|git commit| HIST[Repository history] HIST -->|git push| REMOTE[Remote repository] REMOTE -->|git fetch / pull| WT
The goal is not to accept “ours” or “theirs” blindly. The goal is to produce the version that is correct for the application.
- Identify conflicting files:
git status
- Open the conflicted file. Git marks the competing sections like this:
Incoming changes
Manually edit the file to keep your changes, the incoming changes, or a combination of both. Remove all conflict markers.
Stage the resolved file after testing it:
git add <file>
- Commit the merge:
git commit
- If rebasing, continue with:
git rebase --continue
| # | git merge | git rebase |
|---|---|---|
| How it works | Combines two lines of history, often with a merge commit | Replays one branch’s commits on top of another |
| History | Preserves both branches’ full history | Rewrites commit history to produce a linear timeline |
| Merge commit | Yes — a merge commit is created | No — history is rewritten without merge commits |
| Best for | Collaborative branches where history matters | Personal branches or cleanup before opening a PR |
Rule of thumb: Merge is a good default for shared branches because it preserves history. Rebase is useful for cleaning up your own feature branch before review. Never rebase commits that teammates are actively building on without agreement.
git push origin --delete <branch_name>
To remove stale remote-tracking references locally:
git fetch --prune
git cherry-pick copies the change from one specific commit onto the branch you currently have checked out. Git creates a new commit with a different ID.
Key use cases:
- Selective commit application: Pick only the commits you need.
- Bug fixes: Backport a specific fix to another branch (e.g., a release branch).
- No full branch merge required: Incorporate isolated changes cleanly.
- New commit: The picked changes are applied as a new commit on the current branch.
git cherry-pick <commit-hash>
A Git hook is a script Git runs at a particular point in an operation. Hooks can catch mistakes locally, such as a bad commit message or failed tests, before the change reaches the shared repository.
| Hook | Trigger | Common Use |
|---|---|---|
pre-commit | Before a commit is created | Run linters or unit tests |
commit-msg | After commit message is written | Enforce commit message format |
post-commit | After a commit is completed | Trigger notifications or logging |
pre-push | Before pushing to remote | Run full test suite |
Example — pre-commit hook to run ESLint:
#!/bin/sh
npx eslint . || exit 1
Make hooks executable:
chmod +x .git/hooks/pre-commit
The hooks inside .git/hooks are local to one clone. For team-wide checks, use a versioned tool such as Husky, pre-commit, or enforce the same checks in CI.
For an unpushed commit, choose the reset mode based on what you want to keep:
- Keep changes staged (soft reset):
git reset --soft HEAD~1
- Keep changes in working directory but unstaged (mixed reset — default):
git reset --mixed HEAD~1
- Discard all changes completely (hard reset):
git reset --hard HEAD~1
Use
--hardwith caution. It discards tracked working-tree changes; recovery may be possible throughgit reflog, but it should not be your plan.
Interactive rebase lets you edit a series of local commits before sharing them. For example, to combine the last three commits:
git rebase -i HEAD~<number-of-commits>
- In the editor, leave the first commit as
pickand change subsequent ones tosquash(ors):
pick a1b2c3d First commit message
squash e4f5g6h Second commit message
squash i7j8k9l Third commit message
Save and close. Git opens another editor to combine the commit messages — edit as needed and save.
If the branch was already pushed, update it with the safer form of force-push:
git push origin <branch_name> --force-with-lease
Use a soft reset when you want to move HEAD back but keep the changes staged for a new commit:
git reset --soft <commit-hash>
The old commits are no longer on the current branch, but their content remains in the index, ready to be reorganized or committed again.
| Command | What it changes | Affects tracked files | Affects untracked files |
|---|---|---|---|
git reset --hard | HEAD, index, and working directory to a specific commit | ✅ Yes — discards modifications | ❌ No — leaves untracked files untouched |
git clean -fd | Only the working directory | ❌ No — ignores tracked files | ✅ Yes — removes untracked files and directories |
Combined usage — this is destructive and removes both tracked edits and untracked files:
git reset --hard HEAD
git clean -fd
A file normally moves through these states:
| State | Description |
|---|---|
| Untracked | Newly created file not yet known to Git |
| Modified | File has been edited since the last commit |
| Staged | File added via git add, queued for the next commit |
| Committed | File permanently saved to repository history via git commit |
Full lifecycle example:
# Create a new file
touch feature.js
# Stage it
git add feature.js
# Commit it
git commit -m "Add feature.js"
# Modify it
vim feature.js
# Stage and commit the update
git add feature.js
git commit -m "Update feature.js"
The important detail is that Git commits the staged snapshot, not every change currently visible in the working directory.
The three reset modes differ in what they leave behind:
| Type | Command | Behaviour |
|---|---|---|
| Soft | git reset --soft <commit> | Moves HEAD only — index and working directory remain unchanged. Changes stay staged. |
| Mixed | git reset --mixed <commit> | Moves HEAD and clears the index — changes remain in the working directory as unstaged. |
| Hard | git reset --hard <commit> | Moves HEAD, clears the index, and discards working directory changes completely. |
Decision guide:
- Use
--softto re-commit with a different message or grouping. - Use
--mixedto unstage changes and re-evaluate what to commit. - Use
--hardonly when you are certain you want to throw away all changes.
Git tags are readable names attached to specific commits. Teams commonly use them for releases such as v1.0 or v2.1. A tag normally stays at that commit, while a branch moves forward as new commits arrive.
Types of tags:
| Type | Description |
|---|---|
| Lightweight | A simple pointer to a commit, no extra metadata |
| Annotated | Stores tagger name, email, date, and a message — recommended for releases |
Common tag commands:
| Command | Purpose |
|---|---|
git tag v1.0 | Create a lightweight tag |
git tag -a v2.0 -m "Release 2.0" | Create an annotated tag |
git tag | List all tags |
git show v2.0 | View tag details |
git push origin v2.0 | Push a specific tag to remote |
git push origin --tags | Push all local tags to remote |
git bisect narrows down a regression by binary search. You identify one known-good commit and one known-bad commit; Git checks out a midpoint, and you tell it whether the bug is present. Each answer removes roughly half of the remaining commits.
- Start bisecting:
git bisect start
- Mark the current (bad) commit:
git bisect bad
- Mark a known good commit:
git bisect good <commit-hash>
- Git checks out a commit halfway between. Test your code, then tell Git the result:
git bisect good # if the bug is not present
git bisect bad # if the bug is present
Repeat until Git identifies the exact commit that introduced the bug.
End the session:
git bisect reset
For large repositories,
git bisectcan find the culprit commit inO(log n)steps — dramatically faster than manual search.
MCQ Practice
MCQ practice questions for Git are coming soon.
Scenario Based
Scenario-based questions for Git are coming soon.
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form