Git and GitHub interview questions covering commits, branches, merge, rebase, pull requests, conflicts, workflows, tags, and collaboration.
Git is a distributed version control system that tracks changes to files over time. Every developer has a full local copy of the repository history, which allows commits, branching, diffs, and history inspection without constant server access. Git is used to coordinate code changes, recover previous versions, and support collaboration workflows.
Git is the version control tool. GitHub is a hosted collaboration platform built around Git repositories. GitHub adds pull requests, issues, code review, branch protection, Actions, releases, permissions, security scanning, projects, and team collaboration features.
The working tree contains files you are editing. The staging area, or index, contains the exact changes selected for the next commit. The repository stores committed history. This separation lets you commit only part of your local changes when needed.
git status
git add src/app.js
git commit -m "Add app entry point"
A commit is a snapshot of staged changes plus metadata such as author, timestamp, message, and parent commit references. Commits form a history graph. Good commits are small, logical, and explain why a change was made, not only what changed.
A branch is a movable pointer to a commit. Branches let developers work on features, fixes, or experiments without changing the main line immediately. Creating branches is cheap because Git stores commits and references, not full copies of the project.
git switch -c feature/login
git branch
git switch main
HEAD is Git current reference to the checked-out commit or branch. Usually HEAD points to the current branch, which points to the latest commit on that branch. In detached HEAD state, HEAD points directly to a commit instead of a branch.
git fetch downloads remote commits and updates remote-tracking branches without changing your current branch. git pull fetches and then integrates changes into your current branch by merge or rebase depending on configuration.
git fetch origin
git log --oneline main..origin/main
git pull --rebase origin main
origin is the default name for the remote repository you cloned from. In fork workflows, origin often points to your fork, while upstream points to the original project. Keeping upstream configured lets you sync your fork with the source repository.
git remote -v
git remote add upstream https://github.com/org/project.git
A merge combines histories from two branches. If the target branch has not diverged, Git can fast-forward. If both branches changed independently, Git creates a merge commit unless another strategy is chosen.
git switch main
git merge feature/login
A fast-forward merge happens when the target branch has no new commits since the feature branch started. Git simply moves the branch pointer forward. It creates linear history but does not record an explicit merge point.
A merge conflict happens when Git cannot automatically combine changes, usually because two branches edited the same lines or one branch deleted a file that another changed. The developer must inspect the conflict markers, choose the correct final content, stage the resolution, and continue.
git status
# edit conflicted files
git add src/user.js
git merge --continue
Rebase moves commits from one base commit to another, replaying them on top of the new base. It creates a cleaner linear history but rewrites commit hashes. Avoid rebasing public shared branches unless the team has agreed on that workflow.
git switch feature/login
git fetch origin
git rebase origin/main
Use merge when you want to preserve the true branch history or when integrating a shared branch. Use rebase to update a private feature branch before opening or updating a pull request. The key rule is to avoid rewriting history that other people are already using.
Squash merge combines all changes from a branch into one commit on the target branch. It keeps main history concise, but it removes the detailed commit-by-commit branch history from main. It works best when pull requests are reviewed as a unit and commit history inside the branch is noisy.
cherry-pick applies a specific commit from one branch onto another branch. It is useful for backporting hotfixes or copying a small change without merging the entire branch. It can create duplicate logical changes, so use it carefully.
git switch release/1.2
git cherry-pick a1b2c3d
git revert creates a new commit that undoes an earlier commit. It is safe for shared branches because it does not rewrite history. Use revert when a bad change already reached main or production branches.
git revert a1b2c3d
git reset moves the current branch to another commit and can change the staging area and working tree. --soft keeps changes staged, --mixed unstages changes, and --hard discards changes. Avoid reset --hard on shared work unless you fully understand the impact.
git reset --soft HEAD~1
git reset --mixed HEAD~1
# destructive: git reset --hard HEAD~1
git stash temporarily saves uncommitted changes so you can switch branches or pull updates. It is useful for interruptions, but stashes can be forgotten. For important work, a temporary commit on a branch is often safer.
git stash push -m "work in progress"
git stash list
git stash pop
git reflog records where HEAD and branch references have pointed locally. It is extremely useful for recovering commits after reset, rebase, or accidental branch movement. Reflog is local and not the same as shared repository history.
git reflog
git switch -c recovered-work HEAD@{2}
If the branch existed locally, use git reflog to find the commit it pointed to, then create a new branch from that commit. If it existed on GitHub, check the pull request, remote refs, or ask another developer who may still have it locally.
git reflog
git branch restored-feature a1b2c3d
git bisect uses binary search through commit history to find the commit that introduced a bug. You mark one commit as good and another as bad, then test the commits Git checks out until the bad commit is identified.
git bisect start
git bisect bad
git bisect good v1.0.0
# test each checkout, then run:
git bisect good
# or
git bisect bad
git blame shows which commit last changed each line in a file. It is useful for understanding context, but it should not be used to shame people. Good teams use blame to find history, related discussions, and reasons behind code.
git blame src/payment.js
A tag is a reference to a specific commit, commonly used for releases. Lightweight tags are simple pointers. Annotated tags include metadata and can be signed. Release automation often builds artifacts from version tags.
git tag -a v1.4.0 -m "Release v1.4.0"
git push origin v1.4.0
Semantic or conventional commit messages use a structured prefix such as feat, fix, docs, test, or chore. They make history easier to scan and can power automated changelogs and semantic versioning.
feat(auth): add password reset flow
fix(api): handle empty search query
A pull request proposes changes from one branch into another. It provides a place for code review, CI checks, discussion, approvals, file diffs, linked issues, and merge decisions. Pull requests are both a technical integration tool and a collaboration workflow.
A good pull request is small enough to review, has a clear description, links the issue or context, includes tests where appropriate, avoids unrelated changes, passes CI, and explains any risky migration or rollout concerns. Reviewers should be able to understand both what changed and why.
Code review catches bugs, clarifies design, spreads knowledge, checks maintainability, enforces standards, and improves shared ownership. It should focus on correctness, security, behavior, tests, and clarity rather than personal style preferences already handled by tooling.
Protected branches restrict direct changes to important branches such as main or release branches. Rules can require pull requests, approvals, status checks, signed commits, linear history, conversation resolution, and admin enforcement.
Common main branch rules require pull requests, at least one approval, passing CI checks, up-to-date branches, CODEOWNERS review for sensitive paths, no force pushes, and no deletion. These rules reduce accidental production-impacting changes.
CODEOWNERS maps files or directories to responsible users or teams. GitHub can automatically request reviews from owners when matching files change. It is useful for security-sensitive areas, platform code, database migrations, and domain-owned modules.
# .github/CODEOWNERS
/security/ @org/security-team
/database/migrations/ @org/backend-team
*.md @org/docs-team
In a fork workflow, contributors copy a repository into their own GitHub account, push branches to the fork, and open pull requests back to the original repository. It is common for open source projects because maintainers do not need to grant direct write access.
git remote -v
# origin -> your fork
# upstream -> original repository
git fetch upstream
git rebase upstream/main
GitHub Issues tracks bugs, tasks, feature requests, discussions, and project work. Good issues include context, expected behavior, actual behavior, reproduction steps, logs or screenshots when useful, and acceptance criteria.
GitHub releases are usually attached to tags and can include notes, changelogs, and build artifacts. Good release notes explain user-visible changes, breaking changes, migrations, fixes, known issues, and upgrade steps.
Signed commits cryptographically verify that a commit was created by a trusted key. GitHub can show commits as verified and branch protection can require signed commits. Signing improves supply-chain trust but requires key management and developer setup.
git config --global commit.gpgsign true
git commit -S -m "Update payment validation"
GitHub repository permissions control who can read, triage, write, maintain, or administer a repository. Teams should use least privilege, grant admin access sparingly, and prefer teams over individual permission management for auditability.
SSH keys authenticate Git operations over SSH. A user SSH key belongs to a person, while a deploy key is attached to a repository and often used by automation. Deploy keys should be scoped carefully and rotated when access is no longer needed.
ssh-keygen -t ed25519 -C "dev@example.com"
git clone git@github.com:org/repo.git
GitHub tokens authenticate API, Git, and automation actions. Fine-grained personal access tokens and GitHub App tokens are preferred over broad classic tokens. Tokens should have limited scopes, expiration, secret storage, and rotation.
Git LFS stores large files outside normal Git objects and keeps lightweight pointers in the repository. It is useful for binaries, datasets, design files, and media. Teams must consider bandwidth, storage quotas, checkout behavior, and backup policies.
git lfs install
git lfs track "*.psd"
git add .gitattributes
Large files increase clone size, slow fetches, bloat history, and remain in repository history even after deletion unless history is rewritten. Use Git LFS, artifact storage, package registries, or object storage for large generated or binary assets.
Submodules let one Git repository reference a specific commit of another repository. They are useful for external dependencies that must be pinned, but they add workflow complexity because clones, updates, and commits require extra care.
git submodule add https://github.com/org/lib.git vendor/lib
git submodule update --init --recursive
A monorepo stores multiple projects or packages in one repository. It can improve shared refactoring, visibility, and dependency coordination, but it needs good tooling for CI filtering, ownership, build caching, permissions, and release management.
GitHub Actions is GitHub CI/CD and automation platform. It can run tests, lint code, build artifacts, publish packages, deploy applications, label issues, and enforce checks on pull requests. Workflows live in .github/workflows.
name: CI
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
A common hotfix workflow branches from the production or release branch, applies the fix, opens a pull request with focused review and tests, merges it, tags or deploys it, then backports or merges the fix into main if needed. Avoid mixing unrelated cleanup into hotfix branches.
Good branch names are short, descriptive, and grouped by purpose, such as feature/login, fix/payment-timeout, chore/update-deps, or hotfix/null-pointer. Consistent names help automation, searching, and team communication.
Fetch the remote main branch and either merge or rebase it into your feature branch depending on team workflow. Rebase keeps a linear feature history, while merge preserves the integration point. After rebasing a pushed branch, use force-with-lease rather than plain force.
git fetch origin
git switch feature/login
git rebase origin/main
git push --force-with-lease
git push --force-with-lease updates a remote branch only if it still points where your local Git expects. It is safer than --force because it helps avoid overwriting someone else recent pushed work.
git push --force-with-lease origin feature/login
Common mistakes include committing secrets, force-pushing over shared work, using broad tokens, granting excessive repository permissions, skipping branch protection, ignoring unsigned release artifacts, and keeping large sensitive files in history after deletion.
First revoke and rotate the secret immediately. Then remove it from history with a tool such as git filter-repo or BFG Repo-Cleaner, force-push rewritten history if appropriate, and coordinate with all clones. Deleting the file in a new commit is not enough because the secret remains in old commits.
git filter-repo --path .env --invert-paths
# then rotate the leaked secret and coordinate the force-push
Common anti-patterns include huge unrelated pull requests, vague commit messages, committing generated files unnecessarily, long-lived branches with no integration, force-pushing shared branches, bypassing review, using latest release notes without tags, and treating git blame as a people-management tool.
A strong demo creates a branch, makes a small commit, opens a pull request, explains the diff, handles review feedback, resolves a conflict, runs checks, and merges according to branch rules. For command-line depth, show fetch, rebase, reflog recovery, and revert versus reset.
git switch -c feature/readme-update
git add README.md
git commit -m "docs: update setup instructions"
git push -u origin feature/readme-update
Explore 500+ free tutorials across 20+ languages and frameworks.