Rebase vs merge & resolving conflicts

Your feature branch and main have both moved forward. There are two ways to bring them together, and teams argue about them a lot. Knowing what each does to history lets you pick deliberately.

Merge: join the histories

git switch feature/gst-report
git merge main          # creates a merge commit with two parents

A merge preserves exactly what happened, including when branches diverged. The history is truthful but can look like a tangle of lines on busy projects.

Rebase: replay your commits on top

git switch feature/gst-report
git fetch origin
git rebase origin/main  # re-applies your commits one by one after the latest main

Rebase gives a straight, linear history, as if you had started your work from today's main. But it creates new commits with new hashes. That is fine for your own unpublished branch, and harmful for commits others have based work on.

Merge Rebase
History Real, branched Linear, rewritten
New commits created One merge commit A new copy of each of your commits
Safe on shared branches Yes No (golden rule: don't rebase public history)
Conflict resolution Once Possibly once per replayed commit

Interactive rebase (git rebase -i HEAD~4) lets you squash "fix typo" commits, reorder or reword them before opening a pull request. The -i flag needs an editor, so use it in your normal terminal.

Resolving conflicts

A conflict happens when both sides changed the same lines. Git stops and marks the file:

<<<<<<< HEAD
GST_RATE = 0.18
=======
GST_RATE = Decimal("0.18")
>>>>>>> feature/gst-report

The part above ======= is the current side, below it the incoming side. Steps:

  1. Run git status to list conflicted files.
  2. Edit each file to the correct final version and delete all the marker lines.
  3. Run tests.
  4. git add the resolved files.
  5. Finish with git commit (for a merge) or git rebase --continue (for a rebase).

Changed your mind? git merge --abort or git rebase --abort returns you to the state before you started.

During a rebase, "ours" and "theirs" are swapped compared with a merge: "ours" is the branch you are rebasing onto. Read the marker labels rather than trusting memory.

Pushing after a rebase

A rebased branch no longer matches its remote copy, so a normal push is rejected. Use:

git push --force-with-lease

Unlike plain --force, it refuses if someone else pushed to the branch since you last fetched.

Common mistakes

  • Rebasing main or any branch teammates are using.
  • Leaving conflict markers in the code and committing them.
  • Picking one side blindly; often the right result combines both changes.
  • Using --force instead of --force-with-lease.

Practice

Create a repo where main and feature both edit the same line of config.py. Resolve it once with a merge, then reset and resolve it with a rebase. Compare git log --oneline --graph --all after each.

B

Written by Bablu Kumar Jha

Founder, BeeProton AI · Mumbai, Maharashtra, India