DEV Community

ArchiveCreativity
ArchiveCreativity

Posted on

Why Git “Gets Weird”: Merge vs. Rebase, and Where Troubleshooting Comes From

Git isn’t hard because the commands are complicated. It’s hard because you’re manipulating history, and history has rules. Most headaches (conflicts, detached HEAD, “where did my commits go?”) come from confusing two different ways of combining work: merge and rebase.

This is the shortest possible tour of what’s actually happening, why things break, and how teams keep the pain low.


Two ways to combine work

1) Merge: keep all paths, stitch them together

  • You and your teammate diverge from main.
  • When you merge, Git creates a new merge commit with two parents.
  • Result: a true historical record. You see the branch split and the join.
  • Trade-off: history gets noisy (extra merge commits).
  • If your branch has diverged for a long time, a merge can pull in unrelated file changes you weren’t tracking, and you may not notice until they trigger a test failure later. Always scan the merge diff, not just your own commits.

Use when: multiple people are collaborating on the same branch, and you care about an audit trail that shows exactly when branches converged.


2) Rebase: replay your commits on top of another branch

  • Git lifts your commits off your branch and reapplies them as if they were created after main’s latest work.
  • Result: linear history. Looks clean, and bisecting is simpler.
  • Trade-off: you are rewriting commit IDs. If others already pulled your branch, you have changed the ground under their feet.
  • Rebasing a branch with merge commits can create “conflict déjà vu” the same conflict repeating multiple times for each commit that touched those lines. Squash related commits before rebasing to reduce pain.

Use when: it is a private feature branch, you want a neat history before merging, and you are comfortable rewriting your own local commits.


Where the trouble starts

Conflicts: unavoidable by design

Conflicts are not a failure of Git; they are Git refusing to guess. If two commits edit the same lines differently, Git stops and makes you choose. You will see this with both merge and rebase. The tool differs, the root cause does not.

Why it feels worse during rebase: you resolve conflicts commit by commit as Git replays your work. It is more steps, but each conflict is narrower and easier to reason about.


Detached HEAD: history editing without a branch

“Detached HEAD” means you are on a commit, not a branch. You can still make commits, but they are easy to lose if you check out something else.

If you pull or fetch in a detached HEAD and then reset, you can silently drop commits without warning. Anchoring them to a branch first avoids permanent loss.

How you end up here:

  • Checked out a raw commit (git checkout <sha>).
  • Mid rebase, mid bisect, or after an interrupted operation.

Why it is scary:

  • New commits are not anchored to a branch name. If you move away, they become hard to find unless you know to use git reflog.

“My commits disappeared”

They did not. Rebasing rewrites commit IDs, so your old IDs vanish from the current view. The actual work is still in the object database.

Reflog entries expire after a time limit (default 90 days for unreachable commits). If you wait too long, recovery might be impossible without a full .git backup.

  • Find them with git reflog.
  • Create a branch at the old position if needed.
  • Most “lost work” stories are just unfamiliarity with reflog.

Force push vs. force-with-lease

If you rebase a branch that others also push to, your local history no longer matches the remote. A raw --force overwrites whatever is there. Safer is:

csharp
CopyEdit
git push --force-with-lease

Enter fullscreen mode Exit fullscreen mode

That only updates the remote if it still points to what you last fetched, which protects teammates from accidental overwrites.

We’ve made every Git mistake so you don’t have to. Follow us for more battle-tested tips, straight from the trenches.

Top comments (0)