linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Chapters
  • How it works
  • Lessons
  • Knowledge base
  • Interview prep
Cluster

← все кластеры

Branches, merge, rebase, cherry-pick

Comparing merge and rebase, fast-forward vs no-ff vs squash, when and why you reach for cherry-pick, what interactive rebase does. A standard block for interviews on any role where Git is more than "push to main".

6 вопросов · ~35 мин чтения

Questions

На этой странице

  1. 01How does merge differ from rebase in terms of history?
  2. 02Fast-forward vs no-ff vs squash when merging a PR. Who wants to see what in main?
  3. 03When do you honestly need `git cherry-pick`? Why is it a poor default?
  4. 04What does interactive rebase do? What commands are available?
  5. 05How does Git resolve a merge conflict? What is a three-way merge?
  6. 06The golden rule of rebasing. What is it and why is breaking it expensive?

#git-merge-vs-rebase-history

juniorчасто

How does merge differ from rebase in terms of history?

Что отвечать

`merge` keeps history as it is. The two trunks stay, and a merge commit appears with two parents. `rebase` takes the commits from your branch, detaches them, and replays them on top of the target branch. You get a linear history, but **with new SHAs**, because the parent of each commit changed. Merge is safe and rewrites nothing. Rebase buys you a clean history at the cost of rewritten commits.

Что хотят услышать

The candidate should: - say that rebase rewrites commit SHAs while merge does not - explain why a linear history is easier for `git log`, `bisect`, and PR review, while a merge commit "eats" context and reads poorly - say when merge is better: long-lived feature branches where the history needs to show "a parallel stream was developed here" - say when rebase is better: pull in fresh main before a PR, sync a local branch without a merge commit - mention that large teams often adopt rebase locally plus a merge when the PR lands (see squash-merge below)

Подводные камни

  • ✗ Saying "rebase is always better than merge". It is not. On a shared branch, rebase breaks other people's copies
  • ✗ Thinking a conflict-free merge is always a fast-forward. Not always. If main moved ahead, you get a three-way merge
  • ✗ Confusing `git rebase main` (replay my commits on top of main) with `git rebase --onto` (move an arbitrary range)

Follow-up

  • ? What happens to commit SHAs after `git rebase main` on a feature branch?
  • ? How do you undo a botched rebase?
  • ? How does a three-way merge differ from a fast-forward?

Глубина в базе знаний

  • git merge
  • git rebase
  • Fast-forward merge
  • PR merge strategies (GitHub)
tags: branching, merge, rebasebook: git.merge.vs.rebase.bytebytego.pdf · github.for.next.generation.coders.epub:ch5

#git-ff-noff-squash

intermediateчасто

Fast-forward vs no-ff vs squash when merging a PR. Who wants to see what in main?

Что отвечать

`fast-forward` moves the branch pointer forward with no merge commit. The history is linear, but there is no trace of where the PR was. `--no-ff` creates a merge commit even when a ff is possible. The history keeps a "dome" for each feature, handy for finding "where this came from". `squash` collapses all the PR commits into one new commit on the target. The history is clean, but the individual PR commits are lost along with their reflog and blame.

Что хотят услышать

A senior should: - name the trade-off: ff = cleanliness, the PR boundary is lost; no-ff = the boundary is visible, but the history is noisier; squash = one point per PR, but the authors of internal commits and the review trail are lost - say that squash is good when the PR commits are "drafts" (`fix typo`, `wip`, `address review`), and bad when the commits are logically independent and atomic - mention that GitHub/GitLab let you enable only one of the three modes through branch protection / repo settings - say that after a squash on GitHub the author of the resulting commit is whoever pressed merge, and the original author moves to Co-authored-by

Подводные камни

  • ✗ Saying "squash is a safe rebase". No. Squash deletes all intermediate commits, while rebase keeps them
  • ✗ Thinking `--no-ff` is a "medium safe" merge. It just forbids fast-forward, the risks are the same
  • ✗ Using squash on a 30-commit PR with meaningful atomic commits. You lose the whole history

Follow-up

  • ? What does `git log --graph --oneline` show after a squash-merge versus a no-ff merge?
  • ? How do you configure squash-only in GitHub branch protection?
  • ? Where do the original PR commit SHAs end up after a squash?

Глубина в базе знаний

  • git merge
  • PR merge strategies (GitHub)
  • Fast-forward merge
  • Pull Request (PR)
tags: branching, merge, prbook: git.merge.vs.rebase.bytebytego.pdf

#git-cherry-pick-when-honest

intermediateиногда

When do you honestly need `git cherry-pick`? Why is it a poor default?

Что отвечать

The honest case: a hotfix on main that also needs to land on a release branch, without carrying over the rest of the feature branch commits. Cherry-pick copies a specific commit as a **new** one (new SHA, same diff) onto the current branch. It is a poor default because it duplicates commits in the history (a later merge can then conflict with itself), loses context ("why this commit is here"), and does not pick up the dependent commits from the same branch.

Что хотят услышать

The candidate should: - name release branches and hotfix porting as the main legitimate case - say that cherry-pick creates a new commit with a different SHA but the same diff, that is **two commits with the same change** in the history - mention `git cherry-pick -x` for adding a `(cherry picked from commit <sha>)` reference to the message, which helps you find the original later - warn about a conflict on merge: if the branch with the original is later merged into release, Git will see two commits with one diff and may ask questions - name `git cherry-pick -m N` for cherry-picking a merge commit (you have to say which parent counts as the "main" one)

Подводные камни

  • ✗ Using cherry-pick instead of merge for routine branch sync. You get duplicated commits and broken dependencies
  • ✗ Running cherry-pick without `-x` and then being unable to find where the commit came from
  • ✗ Cherry-picking a merge commit without `-m`. You get the error "is a merge but no -m option was given"

Follow-up

  • ? What does the `-x` flag add to the commit message?
  • ? How do you cherry-pick a range of commits `A..B`?
  • ? What happens when a cherry-pick conflicts, and which commands resolve it?

Глубина в базе знаний

  • git cherry-pick
  • git merge
  • git rebase
tags: branching, cherry-pick, hotfix

#git-interactive-rebase-commands

intermediateчасто

What does interactive rebase do? What commands are available?

Что отвечать

`git rebase -i <base>` opens an editor with the list of commits from base to HEAD and offers an action for each: `pick` (keep as is), `reword` (change the message), `edit` (stop, let you fix things, then continue), `squash` (fold into the previous one, messages are combined), `fixup` (like squash, but this commit's message is thrown away), `drop` (delete), `exec <cmd>` (run a command after the commit is applied). Reorder the lines and the order changes.

Что хотят услышать

A senior should: - name `fixup` as the most common case before a PR: fold `wip` and `fix typo` commits into the main commit - explain `git commit --fixup=<sha>` + `git rebase -i --autosquash` as a convenient workflow: you commit fixes right away with metadata for a future autosquash - say that interactive rebase is a history rewrite, the SHAs change, and you should do it only on local, non-shared commits - mention `git rebase -i --root` for editing including the very first commit - say that during `edit` you can run `git reset HEAD^`, split the commit into several, and continue with `git rebase --continue`

Подводные камни

  • ✗ Using `squash` when you need `fixup`. You get an editor with two messages instead of one
  • ✗ Running `git rebase -i` on a branch you already pushed and someone pulled. You break their copies
  • ✗ Forgetting `git rebase --continue` after `edit`. You get stuck mid-rebase and `git status` shows something odd

Follow-up

  • ? Why is `git commit --fixup=<sha>` better than a manual `edit` in a rebase?
  • ? What does an `exec` line do in the interactive rebase todo list?
  • ? How do you cancel an interactive rebase you already started?

Глубина в базе знаний

  • git rebase
  • Interactive rebase
  • git commit --amend
tags: branching, rebase, history

#git-three-way-merge

seniorиногда

How does Git resolve a merge conflict? What is a three-way merge?

Что отвечать

Git takes three versions of the same file: yours (HEAD), theirs (MERGE_HEAD), and the common base, the merge-base, which is the last common ancestor. For each hunk it compares: if only one side changed, it takes that one; if both changed it **the same way**, it takes that; if they changed differently, that is a conflict, and markers `<<<<<<< HEAD ... ======= ... >>>>>>> MERGE_HEAD` are written into the file. After resolving by hand you run `git add` and `git commit` (or `git merge --continue`).

Что хотят услышать

A senior should: - name the three "versions" (ours/theirs/base) and say that the merge-base is found by walking the graph up to the common ancestor - explain the difference between `--ours` and `--theirs` in `git checkout` during a conflict: pick one side whole for the file - mention `git mergetool` and popular backends (vimdiff, meld, VSCode), but in production a manual resolve is often faster - name `git config merge.conflictStyle diff3` for adding a `||||||| base` block to the markers, which often makes the resolve easier - say that `rerere` (`reuse recorded resolution`) remembers a resolve and applies it automatically when the same conflict recurs

Подводные камни

  • ✗ Saying "merge will sort out everything Git considers resolvable". It will, but if changes differ on the same line, that is always a conflict, with no heuristics
  • ✗ Confusing ours and theirs in `git checkout --ours` during a rebase. The semantics there are inverted relative to merge (see the documentation)
  • ✗ Committing a file with `<<<<<<<` markers inside. It lands in the history

Follow-up

  • ? What happens during a merge with no common base (`--allow-unrelated-histories`)?
  • ? How does `git config merge.conflictStyle diff3` change the markers?
  • ? How is `rerere` useful on long-running feature branches?

Глубина в базе знаний

  • git merge
  • PR merge strategies (GitHub)
  • Auto-merge for PRs
tags: branching, merge, conflict

#git-golden-rule-rebase

seniorиногда

The golden rule of rebasing. What is it and why is breaking it expensive?

Что отвечать

The rule: **do not rebase commits that are already published and that others may build on**. Rebase rewrites SHAs. If a colleague already pulled your branch and is working on top of it, then after your rebase plus force-push their local commits point at SHAs that "vanished", their `git pull` will draw duplicates, and their new commits end up "orphaned". You fix it in a coordinated way, or not at all.

Что хотят услышать

A senior should: - state the rule in one sentence and explain **why** it exists (through the rewritten SHAs), not "because that is the convention" - name the exception: a feature branch with a single owner is yours, so rebase plus force-push there (better `--force-with-lease`) is fine - say that `git push --force-with-lease` refuses to push if the remote branch moved since your last fetch, a guard against overwriting other people's commits - name coordination through the PR description / Slack as a mandatory step even on a feature branch with two co-authors - mention that on main / release branches force-push should be forbidden through branch protection

Подводные камни

  • ✗ Believing `--force-with-lease` is absolutely safe. Not absolutely. If a colleague fetched but did not pull into local, you will not see their commits
  • ✗ Rebasing main and then force-pushing to main. That wipes the history for the whole team
  • ✗ Arguing "but the history is cleaner". On a shared branch the price of that cleanliness is rebuilding other people's work

Follow-up

  • ? What happens to a teammate's local branch after your force-push?
  • ? How does `--force-with-lease` differ from `--force`?
  • ? How do you configure branch protection to forbid force-push to main?

Глубина в базе знаний

  • git rebase
  • Force push
  • Branch protection rules
tags: branching, rebase, force-push
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies