Git Workflow & CI/CD
Rewriting history (rebase, amend), power tools (reflog, bisect, cherry-pick, hooks), team collaboration, submodules, and CI/CD pipelines.
15 questions
JuniorDesignVery commonWalk through the typical lifecycle of a pull request from branch to merge in a team using code review and CI. Then explain what properties make a PR easy and fast to review.
Walk through the typical lifecycle of a pull request from branch to merge in a team using code review and CI. Then explain what properties make a PR easy and fast to review.
Branch from main → push → open PR (what + why + how to test) → CI runs lint/build/tests → reviewers comment → author fixes → approval → merge. Easy-to-review PRs are small (<400 lines), single-concern, with a clear title, linked issue, and clean commit history.
Common mistakes
- ✗Mixing refactor and feature in one PR — reviewers miss the actual feature change
- ✗PR description without context — reviewer must read the code to know intent
- ✗Force-pushing during review — comments lose their anchors
Follow-up questions
- →What is a stacked PR and when does it help with large changes?
- →How do code-owners files automate reviewer assignment?
MiddleTheoryVery commonWhat is CI/CD and what benefits does it bring to developers?
What is CI/CD and what benefits does it bring to developers?
CI: every push triggers automated build and tests to catch integration bugs early. CD (Delivery): pipeline produces an artefact and auto-deploys to staging; production needs human approval. CD (Deployment): fully automated deploy to production on every green build.
Common mistakes
- ✗Treating CI as just running tests — CI should also run static analysis, coverage checks, and security scans; catching more issues in the pipeline
- ✗Running a single job sequentially for everything — use parallel jobs (lint, unit tests, integration tests, build) to reduce pipeline duration
- ✗Not caching dependencies in CI — downloading all packages on every run wastes 2-5 minutes; cache
~/.m2,build/, ornode_modulesbetween runs
Follow-up questions
- →What is the difference between a deployment pipeline and a release pipeline?
- →How do feature flags enable continuous deployment without exposing incomplete features to users?
MiddleDesignVery commonYour feature branch has fallen behind main and you need to integrate the latest changes before merging. Explain when you should rebase the branch and when you should merge it — how each affects history shape and commit SHAs, and which is unsafe on a shared branch.
Your feature branch has fallen behind main and you need to integrate the latest changes before merging. Explain when you should rebase the branch and when you should merge it — how each affects history shape and commit SHAs, and which is unsafe on a shared branch.
Rebase replays your commits on top of the target — linear history, but rewrites SHAs (never on shared branches). Merge preserves topology with a merge commit — accurate audit trail. Typical flow: rebase your feature onto latest main, then merge with --no-ff.
Common mistakes
- ✗Rebasing a published branch and forcing everyone to recover from reflog
- ✗Mass-squashing merges and losing commit-level review history
- ✗Avoiding rebase entirely and ending up with a tangled merge graph
Follow-up questions
- →What is
git pull --rebaseand when is it the right default? - →How does
git rebase --ontodiffer from a plain rebase?
JuniorTheoryCommonWhat does git rebase do to your commits at a basic level?
What does git rebase do to your commits at a basic level?
git rebase replays your branch's commits on top of a new base, creating new commits with new SHAs. Unlike merge it yields a linear history with no merge commit — but because it rewrites commit identity, it is only safe on commits you have not yet shared.
Common mistakes
- ✗Thinking rebase and merge produce the same commit objects — rebase creates new SHAs, merge does not
- ✗Rebasing a branch teammates have already pulled — it rewrites history they depend on
- ✗Assuming a linear history means the work was never done in parallel
Follow-up questions
- →When is
mergethe safer choice overrebase? - →What does
git rebase -ilet you do beyond moving commits?
JuniorTheoryCommonWhat's the difference between annotated and lightweight git tags, and how should releases use them?
What's the difference between annotated and lightweight git tags, and how should releases use them?
Lightweight tag (git tag v1.0) is a named pointer to a commit. Annotated tag (git tag -a v1.0 -m "...") is its own object with author, date, message, and optional GPG signature. Use annotated for releases — signable first-class objects.
Common mistakes
- ✗Using lightweight tags for releases and losing them on certain pushes
- ✗Forgetting
--tagsongit push— tags don't propagate by default - ✗Mixing semver tag styles (v1.0 vs 1.0) inconsistently
Follow-up questions
- →How do you sign a tag with GPG?
- →What is
git describeand how does it use tags?
MiddleTheoryCommonWhat does git cherry-pick do and when should you use it vs merge or rebase?
What does git cherry-pick do and when should you use it vs merge or rebase?
git cherry-pick <sha> applies one commit's diff on top of the current branch as a new commit (new SHA). Use it for backporting a single change (e.g. a bugfix to a release branch). Avoid for long-running branches — duplicates complicate future merges.
Common mistakes
- ✗Cherry-picking many commits instead of merging the branch — leaves duplicates
- ✗Cherry-picking a merge commit without
-m Nto choose the parent - ✗Cherry-picking commits that depend on each other in the wrong order
Follow-up questions
- →How do you cherry-pick a range of commits?
- →What does
cherry-pick -xdo?
MiddleTheoryCommonHow do you edit a commit (amend vs fixup)?
How do you edit a commit (amend vs fixup)?
git commit --amend replaces the last commit with a new one — rewrites history, so use only before push. For deeper commits: git commit --fixup <hash> then git rebase -i --autosquash <hash>^, or git rebase -i HEAD~N and mark the target edit.
Common mistakes
- ✗Using
--amendon an already-pushed commit — requiresgit push --force, which overwrites the remote and breaks anyone who pulled the original commit - ✗Forgetting
--no-editwith--amendwhen only changing files —git commit --amend --no-editadds staged changes without reopening the editor - ✗Running
git rebase -iwith too large a range — include only the commits you intend to change; a larger range increases conflict risk
Follow-up questions
- →What is the difference between
squashandfixupin an interactive rebase? - →How do you edit the commit message of a commit that is not the most recent one?
MiddleTheoryCommonExplain interactive rebase and when to use it.
Explain interactive rebase and when to use it.
git rebase -i <base> opens an editor listing commits from <base> to HEAD with actions: pick, reword, edit, squash, fixup, drop. Use it to clean WIP commits before a PR, reorder for a logical narrative, or replay onto updated main. Rule: only rebase local commits.
Common mistakes
- ✗Rebasing pushed commits on a shared branch — your
git push --forceoverwrites remote history and forces teammates to reset or re-clone - ✗Forgetting to stage changes and run
git rebase --continueafter aneditpause — leaves the rebase in a detached state - ✗Using rebase to 'hide' bugs — squashing commits doesn't remove bugs; don't use rebase to obscure debugging history for a bug being investigated
Follow-up questions
- →How does
git rebase --onto <newbase> <oldbase> <branch>work? - →What is the difference between
git merge --squashandgit rebase -isquash?
SeniorTheoryCommonDescribe branching strategies (Gitflow, trunk-based, etc.).
Describe branching strategies (Gitflow, trunk-based, etc.).
Gitflow: main + develop; features from develop, releases via release/x.y, hotfixes from main. Trunk-based: all commit to main via <1-day branches; feature flags hide unfinished work. GitHub Flow: feature branch from main, PR, merge, deploy.
Common mistakes
- ✗Choosing Gitflow for a small team — Gitflow overhead is justified for products with multiple release lines; small teams working on web services should use GitHub Flow or TBD
- ✗Feature branches lasting weeks — long-lived branches diverge from main and cause painful merge conflicts; break features into smaller mergeable increments
- ✗Not deleting merged branches — stale branches clutter the repository and confuse developers; automate deletion in the CI system after merge
Follow-up questions
- →How do feature flags enable trunk-based development and what are their operational risks?
- →When is a monorepo better than a polyrepo and how does branching strategy differ?
SeniorDesignCommonA growing organisation must decide whether to keep all its services in one monorepo or split them across many small per-service repositories. Compare the two layouts across cross-cutting changes, build scaling, code sharing, ownership boundaries, and dependency versioning, and explain what each choice costs.
A growing organisation must decide whether to keep all its services in one monorepo or split them across many small per-service repositories. Compare the two layouts across cross-cutting changes, build scaling, code sharing, ownership boundaries, and dependency versioning, and explain what each choice costs.
Monorepo: atomic cross-cutting changes, shared tooling, easy code sharing — but needs scaling builds (Bazel/Buck), coarse permissions. Polyrepo: clear ownership, smaller scope, standard tooling — but cross-cutting = multi-PR, dependency versioning harder.
Common mistakes
- ✗Adopting monorepo without investing in build system / sparse checkout
- ✗Polyrepo with lockstep versioning between many repos — worst of both worlds
- ✗Storing very different scales (frontend monorepo + huge data) in one tree without LFS
Follow-up questions
- →What is sparse checkout and how does it scale monorepo?
- →Compare Bazel and Buck for monorepo builds.
JuniorTheoryOccasionalWhat is the Conventional Commits standard and what does it enable?
What is the Conventional Commits standard and what does it enable?
Format: <type>(<scope>): <description> with types feat, fix, chore, docs, etc. A BREAKING CHANGE: footer (or !) signals incompatibility. Tools like semantic-release parse the log to auto-bump SemVer (feat = minor, fix = patch, breaking = major).
Common mistakes
- ✗Mixing types and scopes inconsistently — defeats automation
- ✗Adding
BREAKING CHANGE:for non-breaking refactors - ✗Using long, multi-purpose commits — single commit should map to single concern
Follow-up questions
- →How does semantic-release use commit history to publish versions?
- →What's the difference between SemVer and CalVer?
MiddleTheoryOccasionalHow does git bisect work and when should you use it?
How does git bisect work and when should you use it?
git bisect does a binary search of history to find the commit that introduced a bug. You give a known-good and known-bad commit; bisect checks out midpoints, you mark good/bad, narrowing in log₂ steps. Automate via git bisect run ./test.sh.
Common mistakes
- ✗Marking a commit good/bad after a flaky test result
- ✗Not running
git bisect resetand being stuck in detached HEAD - ✗Bisecting across a merge commit without
--first-parentwhen intent is the merge boundary
Follow-up questions
- →How does
git bisect skiphelp with non-buildable commits? - →What is
git blameand when does it complement bisect?
MiddleTheoryOccasionalWhat are git hooks and what's the difference between client-side and server-side hooks?
What are git hooks and what's the difference between client-side and server-side hooks?
Hooks are scripts in .git/hooks/ (or configured hooksPath) that fire on events. Client-side: pre-commit (lint), commit-msg (validate), pre-push (tests). Server-side: pre-receive, update, post-receive (enforce policy on push). Tools like Husky share them via the repo.
Common mistakes
- ✗Putting slow tests in
pre-commit— devs disable hooks to keep working - ✗Forgetting that
--no-verifyskips hooks — relying on client hooks alone for security - ✗Using server-side hooks where a CI pipeline is more visible/maintainable
Follow-up questions
- →How does
core.hooksPathlet you ship hooks via the repo? - →Why are server-side hooks not a substitute for branch protection on a hosted forge?
MiddleTheoryOccasionalWhat is git reflog and how does it save you from "lost" commits?
What is git reflog and how does it save you from "lost" commits?
Reflog is a per-ref log of every HEAD/branch-tip position for the last 90 days. After reset --hard, force-push, or rebase, prior commits are still reachable via git reflog show HEAD. Recover with git reset --hard <sha>. Local only.
Common mistakes
- ✗Panicking after
reset --hardwithout checking reflog first - ✗Forgetting reflog only persists in the local clone
- ✗Letting
git gcpurge old reflog entries when you needed them
Follow-up questions
- →How long does reflog keep entries by default?
- →How do you recover a deleted branch using reflog?
MiddleTheoryOccasionalHow do git submodules work and what are common alternatives?
How do git submodules work and what are common alternatives?
A submodule pins a child repo at a specific SHA inside the parent — .gitmodules holds the URL, parent tree holds the SHA. Pros: precise pinning. Cons: clones need --recursive, updates two-step, merge conflicts confusing. Alternatives: monorepo, Conan/vcpkg.
Common mistakes
- ✗Cloning without
--recursiveand getting empty submodule directories - ✗Updating a submodule's branch without committing the new SHA in parent
- ✗Letting submodule URLs drift between developers' configs
Follow-up questions
- →How does
git subtreediffer from submodules? - →What is sparse-checkout and when does it help in a monorepo?