| Merge Commit | Individual Commits on Main |
|---|---|
| One atomic integration point | 500 commits sprawled on main |
git revert -m1 <merge> undoes everything |
Good luck reverting |
git bisect can skip the whole merge |
Bisect walks through 500 commits |
| Main history is readable | Main history is chaos |
| Commits still exist (on the branch) | Same commits, worse organization |
The merge commit doesn't hide anything - it's a pointer, not a wall. Git blame traverses into the merged branch to find the actual commit that introduced each line.
main: A --- B --- M --- C
/
feature: X - Y - Z
If line 42 was written in commit Y, git blame will show commit Y with its original author and message. The merge commit M is transparent.
Every merge commit has multiple parents:
- First parent: the branch you merged INTO (main)
- Second parent: the branch you merged FROM (feature)
--first-parent tells git "only follow the first parent" - i.e., stay on the mainline.
# Shows main's perspective: A, B, M, C (M is one line item, not 500)
git log --first-parent
# Shows everything flattened: A, B, X, Y, Z, M, C
git loggit bisect start --first-parentThis bisects across merge commits only. If the bug is in that 500-commit integration, bisect says "M broke it" and you then drill into M separately. Without --first-parent, bisect might walk you through all 500 commits interleaved with unrelated main commits.
The history is all still there - blame finds the original commits. The merge commit is just an organizing boundary that makes main readable and lets us revert/bisect at the integration level instead of commit-by-commit.