The difference between merge and rebase in Git

Neither rebase nor merge during pull themselves “erase” your work — in both cases, your commits remain in the repository (in the branch history or as old SHAs while reflog is active).

  • pull.rebase false (merge): git pull will create a merge commit; your and others’ commits are not rewritten — the branch history simply merges together. Visually “safer” for the brain: you clearly see the converging lines.
  • pull.rebase true (rebase): your local commits are copied over the remote ones (new hashes). The content of commits is usually the same, but “old” commits after a successful rebase may remain only in git reflog — this is normal; they can be restored (git reset --hard to the desired ref from reflog) if something goes wrong.

If the main concern is “not losing work”:

  1. Before risky steps — commit (or git stash) and optionally a separate branch (git branch backup-tgisn-46) — a copy of the pointer, cheap backup.
  2. Don’t confuse with loss from commands like git reset --hard, force push without need, git clean -fd.
  3. After rebase/merge, don’t run aggressive git gc for a few days — reflog holds a backup exit.

Practical for “not losing work, not overly complicating history”: git config pull.rebase false — when diverging, you’ll always get a merge, without rewriting local commits. If you’ve already gotten used to the rebase approach (as in previous pull --rebase) — you can leave pull.rebase true, just don’t push --force to shared branches without agreement.

Conclusion: losing work due to pull strategy choice doesn’t happen; the risk lies in other commands and force push; for peace of mind — commit + backup branch before unclear operations.

Here’s the same situation you had: one common commit C, then five commits r1…r5 on origin, and one local commit L (my work).

1. Before pull (diverged)

gitGraph
  commit id: "C (common)"
  branch local
  checkout local
  commit id: "L (my commit)"
  checkout main
  commit id: "r1"
  commit id: "r2"
  commit id: "r3"
  commit id: "r4"
  commit id: "r5"

Meaning: tip of local = L, tip of main = r5, common ancestor = C. This is not lost in either case — only how the history is stitched together changes.


2. After git pull without rebase (pull.rebase falsemerge)

gitGraph
  commit id: "C"
  branch local
  checkout local
  commit id: "L"
  checkout main
  commit id: "r1"
  commit id: "r2"
  commit id: "r3"
  commit id: "r4"
  commit id: "r5"
  checkout local
  merge main
  commit id: "M (merge commit)"

A merge commit M with two parents (L and r5) appears. Commits L and r1…r5 remain as objects; history is forked, no rewriting.


3. After git pull with rebase (pull.rebase truerebase)

gitGraph
  commit id: "C"
  commit id: "r1"
  commit id: "r2"
  commit id: "r3"
  commit id: "r4"
  commit id: "r5"
  commit id: "L′ (same patch, new hash)"

History is linear: your work sits on top of remote commits. Your commit L in history becomes a new commit L′ (same diff relative to r5, different hash); the old L remains visible in git reflog for some time until you remove reflog expire.


In short: merge — fork + merge node; rebase — one line, your commit “rewritten” on top. Your work in terms of file changes doesn’t disappear in either normal scenario; only the shape of history and hash of the local commit differ under rebase.