An opinionated guide for humans · not just developers

Git Branches, Commits
and PRs, oh my!

You don't need to be a wizard to understand git. You just need the right story. This guide starts from absolute zero — what a branch even is — and ends with the single most debated button in software development.

scroll to explore

So what is Git, exactly?

Before we talk about branches, commits, or pull requests — before any of the vocabulary — let's answer the one question most guides skip: what problem does Git actually solve?

Imagine this nightmare
📄 website_FINAL.html
📄 website_FINAL_v2.html
📄 website_FINAL_v2_REAL.html
📄 website_FINAL_Janes_edits.html
📄 website_use_this_one.html
😰 website_FINAL_FINAL_OK_THIS_ONE.html

Everyone who's worked on a shared document has lived this. It's chaos. Nobody knows which file is current, what changed, or who did what.

Git was invented to make that chaos impossible. It's a version control system — a piece of software that watches every change made to a collection of files, records who made it, when they made it, and what exactly changed. You never need FINAL_v2_REAL_this_one.html again. There is always one authoritative version, and a complete, inspectable history of how it got there.

Git was created in 2005 by Linus Torvalds — the same person who created the Linux operating system — specifically because he needed a better way to coordinate thousands of developers contributing to Linux from all over the world. He needed something fast, distributed, and impossible to corrupt. That's git.

⚙️
Git
The tool

Free, open-source software that runs on your computer. It tracks changes, manages history, and handles the entire branching/merging system. It has no interface — it's a command-line program. Git works completely offline. You could use it entirely alone, forever, and it would still be useful.

🐙
GitHub
The service built on top of the tool

A website and cloud service owned by Microsoft that hosts git repositories online. It adds a web interface, pull requests, code review, issue tracking, and team collaboration features. GitHub is to git what Google Docs is to a word processor — a polished, cloud-connected layer on top of the underlying technology.

Alternatives include GitLab, Bitbucket, and Gitea — all hosting services for git repos.

When developers say "push to GitHub" they mean: take the history git is tracking locally on my machine, and upload it to the shared online copy. When they say "clone the repo" they mean: download the entire project, including its full history, onto my machine so git can track my changes locally.

The words you'll hear. Decoded.

Here are the terms that come up constantly — the ones people nod at in meetings while quietly having no idea what they mean. Every single one of these will make sense by the end of this guide, but here's a cheat sheet to start.

Repository (a.k.a. "repo")
The entire project — all its files, plus the complete history of every change ever made. Think of it as a folder that remembers everything.
Commit
A saved snapshot of changes at a specific moment in time. Like hitting Save, except it's permanent, timestamped, and described. Every commit has a unique fingerprint called a SHA.
Branch
A parallel copy of the project where you can make changes safely without touching the main version. Branches let multiple people work on different things simultaneously.
Main (a.k.a. "master" in older repos)
The official, production-ready branch. The source of truth. The one everyone's working toward. Changes only land here after they've been reviewed and approved.
Pull Request (a.k.a. "PR" or "Merge Request" on GitLab)
A formal proposal to merge your branch into main. It opens a space for teammates to review your changes, leave comments, and approve or request changes before anything goes live.
Merge
The act of combining one branch's changes into another. When your PR gets approved and someone clicks the button, that's a merge. How it happens is exactly what this guide is about.
Clone
Downloading a full copy of a repository — including its entire history — from a remote server like GitHub onto your local machine.
Push / Pull
Push: upload your local commits to the remote server. Pull: download commits from the remote server that you don't have yet. Two directions of the same sync operation.
SHA (a.k.a. "hash" or "commit hash")
A 40-character fingerprint that uniquely identifies every single commit. We'll dedicate a whole section to this — it's more important than it sounds.
Diff
The difference between two versions of a file — what lines were added, removed, or changed. When you review a PR, you're reading a diff.
🗺️
You've got the map

That's the vocabulary. Now let's walk through how these pieces connect in practice — starting with the journey every piece of code takes from idea to the official codebase.

Before we talk about merging,
let's talk about what you're merging

A lot of guides assume you already understand branches, commits, and pull requests. Most people nod along and quietly don't. This section fixes that — in plain English, with the same storytelling world we'll use for the rest of the guide.

Step 1
🌿

The Branch

Your own private writing desk

Imagine the codebase is a grand shared library — thousands of books, all neatly organised, all officially approved. This is main. It's the source of truth. Everyone on the team reads from it. No one is allowed to just walk in and scribble changes directly into the books. That would be chaos.

So instead, when you want to work on something new, you walk to a side room and make yourself a perfect photocopy of the entire library. This copy is yours alone. Your private writing desk. You can do whatever you want here — tear out pages, rewrite chapters, experiment wildly — and none of it touches the real library until you say so.

That private copy is a branch.

In plain git terms

When you run git checkout -b my-feature, git creates a new branch — a pointer that says "I'm working on a parallel version of this codebase, starting from where main is right now." Your changes stay on your branch until you choose to bring them back.

The name main is just convention — it's the branch everyone agreed is "the real one." Some older repos call it master. The important thing is: it's the official, published, everyone-reads-from-this version. Your branch is the scratchpad you work on before you're ready to publish.

Step 2
✉️

The Commits

Your sealed, timestamped envelopes

You're sitting at your writing desk — your branch — and you start working. You write a new feature. You fix a bug. You rename a variable. At some point, you pause and think: "I want to save a snapshot of exactly where things stand right now."

So you gather up all the changes you've made, seal them in an envelope, and stamp the exact date and time on the outside. You write a short note on the front describing what's inside: "Added login button" or "Fixed crash on mobile" or, honestly, sometimes just "WIP". You drop it in your out-tray.

That sealed, timestamped envelope is a commit.

Three things that make commits special
🔒
Immutable. Once sealed, the contents of a commit can never change. Git gives every commit a unique fingerprint (called a SHA) based on its exact contents. If you change anything, you get a different commit entirely.
Timestamped. Every commit carries the exact moment it was created. The archive is ordered by these timestamps. This is why the "re-stamping" in rebase is such a big deal — you're altering the official record.
🔗
Chained. Each commit knows which commit came before it — its parent. This chain is how git constructs history. Pull on any commit and you can trace the entire lineage of the codebase back to the very first change ever made.

On your branch, you might make one commit or fifty. Small, frequent commits are generally better — they're easier to understand, easier to undo, and easier to describe. But in practice, most developers accumulate a messy pile of them: "fix", "fix again", "ok this time for real". This is normal. This is human. And — spoiler — it's exactly why the squash strategy exists.

Step 3
📮

The Pull Request

Knocking on the library door

You've been working at your desk for a few days. You have a stack of envelopes — your commits — and you think you're done. The feature works. The bug is fixed. You're ready to bring this back to the shared library.

But you can't just walk in and start re-filing things. That's not how good libraries work. Instead, you go to the front desk and say: "I'd like to propose adding these envelopes to the official collection. Here's what they contain. I think they belong."

The librarians — your teammates — come over to inspect your work. They read through what you've done, ask questions, suggest improvements, maybe point out a typo or a better approach. This conversation is the code review. The formal request that started it is the pull request — you're requesting that the library pull in your changes.

Why "pull request" and not "push request"?

Great question. You've already pushed your branch up to the server. The PR is you asking main to pull your changes in. It's a request directed at the destination, not the source. GitHub calls them Pull Requests. GitLab calls them Merge Requests. Same thing, different name.

Once the librarians are satisfied — approvals given, concerns resolved — comes the moment of truth. Someone clicks the big green button. And that is exactly when your merge strategy matters. Because that click is what decides how your envelopes get filed into the archive forever.

🌿 Branch Your private desk
✉️✉️✉️ Commits Your sealed envelopes
📮 Pull Request Knock on library door
🏛️ Merge Filed into the archive
🌪️
You're not in Kansas anymore

Now you understand what a branch is, what commits are, and what a PR does. There's one question left: when those envelopes get filed into the archive, how should they be filed? That's where the real debate begins.

Why this matters more than you think

Git gives you three ways to integrate a branch into main. GitHub puts all three options in a dropdown button on every pull request — right before you click merge. Most developers click the green button without thinking. That's a mistake.

Your merge strategy is your history strategy. A messy git log isn't just aesthetically offensive — it makes debugging harder, reverting riskier, and onboarding slower. The good news: once you understand what each strategy actually does to the commit graph, the right choice becomes obvious for almost every situation.

Two of these are pure git. One is GitHub's terminology. One of them is almost always the right default. Let's get into it.

🔬
Quick technical detour
The SHA — git's unbreakable fingerprint
Understanding this unlocks why one strategy is reserved for those who know what they're doing. Takes 2 minutes. Worth every second.

Remember how we said each commit gets stamped with a unique fingerprint? That fingerprint has a name: the SHA. Understanding what it is — and what it means to change one — is the single most important thing you can know before choosing a merge strategy.

SHA stands for Secure Hash Algorithm. That sounds intimidating, so forget the name. Here's what it actually is in plain terms.

A real git commit SHA looks like this:
a3f9b2c1d4e8f7a6b5c9d0e2f3a4b5c6d7e8f9a0b1
40 hexadecimal characters. Completely unique to that exact commit. Always.

Git takes everything about a commit — every line of code changed, the commit message, the author, the timestamp, and crucially the SHA of the commit that came before it — feeds it all into a mathematical blender, and out comes that 40-character fingerprint. Change even a single character anywhere in that input and the entire SHA becomes something completely different.

🪄
Think of it as a wax seal on an envelope

When a medieval messenger sealed a letter with wax and pressed their signet ring into it, that seal was proof: this letter has not been touched since it left my hands. If someone broke the seal and resealed it — even perfectly — it would be a different seal from a different moment in time. The SHA is git's wax seal. It is mathematically impossible to fake.

Why does the SHA chain matter?

Here's what makes git genuinely remarkable — and genuinely unforgiving. Every commit's SHA is calculated using its parent's SHA. Which means every commit is cryptographically tethered to every commit that came before it, all the way back to the very first commit ever made in the repo.

Pull on any link in the chain and you can verify the entire history back to the beginning. Nothing can be quietly altered. If someone changes a commit from three weeks ago, its SHA changes — which forces the next commit's SHA to change — which cascades through every single commit that came after it. The tampering is immediately visible.

Each commit contains its parent's SHA — creating an unbreakable chain
C1
a3f9b2c
First commit.
No parent.
C2
7d1c4e8
SHA includes
parent's SHA.
C3
f2a8b5d
SHA includes
parent's SHA.
C4
9e3c7a1
SHA includes
parent's SHA.

So what does it mean to "rewrite" a SHA?

This is where rebase becomes genuinely consequential. When you rebase, git takes your commits and replays them on top of a different parent commit. The code changes inside each commit are identical. But the parent SHA changed. Which means the input to the fingerprint calculation changed. Which means the SHA itself changes.

To git, a commit with a new SHA is a completely different commit — full stop. It doesn't matter that it has the same message, the same diff, the same author. The old commit and the new commit are two distinct objects in git's database. The old one still exists on your feature branch. The new one is what lands on main. They are not the same thing.

⚠️ The danger scenario

Your teammate Alex has been working on a branch that forks off your feature branch at commit a3f9b2c. Alex's branch has a3f9b2c as a parent — it's baked into Alex's commit chain. Then you rebase and merge. Your commits now have new SHAs. a3f9b2c no longer exists in main's history — it's been replaced by something like b7d2e4f.

Alex's branch is now pointing at a commit that, as far as main is concerned, does not exist. When Alex tries to sync, git has no idea how to reconcile these two histories. Conflicts. Lost work. Confusion. All because a SHA got rewritten without warning.

When it's completely fine

You're the only person who ever worked on your feature branch. Nobody forked off it. Nobody has those SHAs saved anywhere. You rebase and merge. New SHAs land on main. The old ones evaporate quietly when you delete the branch.

This is why experienced solo developers reach for rebase confidently. The SHA rewrite only matters if someone else has a reference to those old SHAs. If nobody does — it's a non-event. Clean history, zero drama.

Why rebase is "advanced"

Rebase isn't dangerous because it's hard to execute. It's dangerous because it silently breaks the assumptions of anyone who trusted those original SHAs. A developer who doesn't understand SHA chaining will use rebase carelessly, cause chaos, and have no idea why. A developer who does understand it will use rebase deliberately — knowing exactly whose world they might be disrupting, and checking first whether they're disrupting anyone at all.

📖
Detour complete · back to the story
You now know what a SHA is, why it's sacred, and why rewriting one is serious business. Hold onto that — it's exactly what makes Option C so much more loaded than it first appears.

Your stack of envelopes
just got approved.

The PR is reviewed. The librarians are happy. The green button is right there. All that's left is deciding how your envelopes get filed into the archive — and this, right here, is the crux of one of the most reliably heated debates in software development.

You've got a stack of sealed, timestamped envelopes — your commits. Some are polished. Some say "WIP" or "fix typo" or "ok seriously this time." The archive doesn't care about your feelings. It just wants to know: in what form do these arrive on the shelf? Developers have been arguing about the answer since git was invented, with the passion of people who feel it says something about their professional character.

📬
⬡ Option A
Ship every envelope, exactly as-is

You hand the Publisher every single envelope, in the exact order you sealed them. Your "fixed a typo" envelope from 2am goes on the shelf. Your "WIP, not sure about this" envelope goes on the shelf. The brilliant final version goes on the shelf. All of them.

The Publisher then adds one special envelope on top — a cover note that says "these N envelopes arrived together as a delivery on this date." It doesn't contain any new writing. It just records that a group of work arrived together and now belongs to the archive. The shelf shows your authentic, warts-and-all creative process. Every decision, every false start, every 2am correction. The timeline is sacred and unbroken.

📢 "The purists love this. They believe every moment of the work deserves to exist in history. They are not wrong — for certain kinds of projects."
🔑 What happens to the SHAs
PRESERVED
All 14 of your original commit SHAs land on main completely unchanged. Every fingerprint is exactly what you sealed in your side room. Nothing was touched.
+1 NEW
One brand new SHA is created for the merge commit itself — the cover-note envelope the Publisher adds. That's the only new fingerprint in the system.
SAFE
Because the original SHAs are untouched, anyone who referenced them — teammates, bug trackers, notes, other branches — can still find them. Nothing breaks. Nothing is orphaned.
In git, this is called…
The Merge Commit
That cover-note envelope the Publisher adds? That's the merge commit itself — a real commit with two parents, permanently recording that these two timelines converged right here. Verbose, meticulous, and extremely nerdy. The purists adore it.
📦
⬡ Option B
Melt everything into one book. Ship the book.

You take your entire stack of envelopes — all 14 of them, including the drafts, the "WIP", the "ok this time for real" — and you feed them through a machine that extracts every single change from every envelope and presses them all into one single, brand new book. "The Authentication Feature." Done.

The individual envelopes are destroyed in the process. They don't go into storage. They don't get archived somewhere. They cease to exist. The Publisher's shelf gets one entry: the finished book, with today's date.

📌 What this means going forward — forever
The shelf is beautiful. Six months from now, anyone reading the archive sees a clean, human-readable story: one entry per feature, one per bug fix. They can understand the history of the project in minutes.
The individual steps are gone. Permanently. If a bug appears three weeks later and it turns out it was introduced in step 9 of your 14 commits — too bad. There is no step 9 anymore. There is only the book. You can undo the entire book at once, but you cannot surgically remove one page from it. The detail is gone forever.
📢 "The pragmatists love this. A bug in step 9 of 14 is a problem for your debugging skills — not a reason to pollute the archive with 14 entries every time. One PR, one commit. This is my camp."
🔑 What happens to the SHAs
GONE
All 14 of your original commit SHAs are destroyed and never reach main. They exist only on your feature branch, which gets deleted after the merge. From main's perspective, those 14 fingerprints never existed.
+1 NEW
One single brand new SHA is created for the squashed commit. This is the only fingerprint that enters the archive. It has no relationship to any of your 14 original SHAs.
NOTE
If anyone saved one of your original 14 SHAs — in a bug report, a note, a Slack message — and tries to look it up in the main history later, it won't be there. It only exists if they still have a copy of the deleted branch, which they probably don't.
In git, this is called…
Squash & Merge
Git takes all your commits, extracts the combined changes, and creates a single brand new commit on main. Your 14 individual commits never touch the main branch. The branch and everything on it is deleted after. Simple. Clean. Irreversible.
🗂️
⬡ Option C
File every envelope individually — but re-stamp every single one

Unlike Option B, nothing gets destroyed here. All 14 of your envelopes go onto the shelf — every draft, every fix, every individual step — in the exact order you wrote them. Someone reading the archive can see the full story of how your feature was built, one envelope at a time.

But here's where it gets complicated. Before each envelope hits the shelf, the Publisher re-stamps it. Not just the date — the entire identity fingerprint gets replaced. Remember those wax seals from the SHA section? Every single one gets broken and re-sealed with a brand new seal. The words inside each envelope are identical to what you wrote. But officially, as far as the archive is concerned, these are now completely different envelopes from the ones you sealed in your side room.

The shelf looks clean and linear — as if you wrote all 14 envelopes one after another, in perfect sequence, right alongside everyone else's work. No trace of the side room. No evidence of parallel development. Just a tidy, single-file timeline.

📌 What this means going forward — forever
Every step is preserved and searchable. A bug appeared? You can scan back through all 14 individual envelopes to find exactly which step introduced it. You can undo step 9 without touching steps 1–8 or 10–14. This surgical precision is why experienced developers love rebase.
The re-stamping is a ticking time bomb if anyone else touched your envelopes. If a teammate had referenced your original envelopes — built their own work on top of them, cited their original fingerprints — those references now point at envelopes that no longer exist in the archive under those identities. Their branch becomes an orphan pointing at a ghost. Merge conflicts. Lost work. Confusion. All silent, all preventable, all caused by not knowing this rule.
📢 "The perfectionists love this. Full history preserved, shelf stays linear, every step debuggable. But use it wrong and you'll get a very angry message from Alex on Slack."
🔑 What happens to the SHAs
REPLACED
All 14 of your original commit SHAs are replaced with 14 brand new SHAs — one new fingerprint per commit. The content inside each commit is identical. But the identity? Completely new. Git treats these as 14 different commits from the ones you originally sealed.
OLD = GONE
Your 14 original SHAs still exist on your feature branch until you delete it. The moment you delete the branch, they evaporate. They will never be in main's history under those fingerprints. Anyone who referenced a3f9b2c will find a ghost.
DANGER
This is the only strategy that rewrites existing SHAs. Unlike Option B where the old SHAs simply never reached main, here the old SHAs look like they should exist — they were real, they were shared, teammates may have built on them. When they're replaced, references break silently, with no warning from git. This is the root cause of almost every rebase horror story.
In git, this is called…
Rebase & Merge
Unlike squash, every individual commit lands on main — but each one gets a brand new SHA in the process. Full granularity preserved. History stays linear. The catch: anyone who had references to your old SHAs now has broken references. That's not a theoretical risk. It bites real teams regularly.
📏
But wait — is all this risk actually worth it?
Let's talk about linear history. What it is. Why people care so much.

When developers talk about "linear history" they mean something very simple: the entire timeline of the project is one single, unbroken line. Every commit follows the previous one. There are no forks. No branches converging. No parallel lanes. Just: A → B → C → D → E, all the way from the first commit ever to the most recent one.

Non-linear history
(what Merge Commit produces)
two lanes · must track both

The history forks into multiple parallel lanes and then rejoins. Reading it requires you to track several timelines at once. On a project with 10 developers and hundreds of PRs a month, this becomes a web of tangled branches — what developers call "spaghetti history."

vs
Linear history
(what Rebase & Merge produces)
one lane · read left to right

One single, unbroken line. Every commit, from every developer, in perfect chronological sequence. You can read git's history like a book — left to right, one thing at a time, no lane-switching required.

So why does this single line justify all the SHA risk?
🔍
Bug hunting becomes a superpower. Git has a built-in tool called git bisect that can automatically find the exact commit that introduced a bug by doing a binary search through history. It cuts the list in half, tests the midpoint, cuts again. On a straight line of 1,000 commits it finds the culprit in about 10 steps. On a tangled non-linear graph? Bisect gets confused by the forks and becomes unreliable or useless. A linear history makes this tool work at full power.
📖
The history reads like a story. Run git log on a linear repo and you get a clean, chronological narrative — every change, from every developer, in the order it happened. You can answer "what changed on this codebase between March and April?" in seconds. On a non-linear history, the same question requires mentally untangling a web of parallel timelines. It's genuinely exhausting at scale.
↩️
Reverting is surgical and safe. Because there are no forks, every commit is a clean, self-contained unit. If commit #847 broke something, you can revert exactly that commit. On a non-linear history with merge commits, reverting becomes complicated — you may need to revert the merge commit too, which carries its own set of gotchas and is a frequent source of confusion even for experienced developers.
📐
It scales with team size. On a small team with 2 developers, non-linear history is manageable. On a team of 20 with dozens of PRs merging daily, the graph becomes a visual disaster. This is why large engineering organisations — and famously the Linux kernel project itself — insist on linear history. It's not aesthetic snobbery. It's an operational requirement at scale.
⚖️
The honest trade-off, stated plainly: Rebase gives you all 14 commits individually and a clean linear history. Merge Commit gives you all 14 commits individually but leaves the history non-linear. That difference — linear vs non-linear — is the entire reason rebase exists and why people accept the SHA risk to get it. If linear history doesn't matter to your team, there is almost no reason to choose rebase over a merge commit.
The crux, stated plainly

Every team is deciding: does the shelf belong to the reader — clean, curated, easy to navigate — or to the writer, a faithful record of every moment the work was touched? Neither answer is wrong. But picking one and enforcing it across your whole team is non-negotiable. A shelf where some items are books, some are pamphlets, and some have been re-stamped without warning is a shelf no one trusts.

Strategy History shape Individual commits Pure git? SHA rewrite?
Merge Commit Non-linear (graph) ✓ All preserved ✓ Yes ✗ No
Squash & Merge Linear ✗ Collapsed to one Partial ✗ No
Rebase & Merge Linear ✓ All preserved Partial ✓ Yes
01

Create a
Merge Commit

git merge --no-ff · the original

You've met Option A. Here's what it actually looks like inside git — the graph, the command, and when to reach for it.

git log --graph — merge commit result
C1 C2 M C5 C6 F1 F2 F3 main feature merge commit
BASH · the git command
git merge --no-ff feature-branch
# GitHub does this automatically when you click "Create a merge commit"
My take

"The right choice for open source projects where contributor history is sacred. A poor default for product teams who'll drown in merge commits within a week."

Reach for this when…
✓ Open source — contributor attribution matters
✓ Long-lived parallel branches (v1 vs v2 rewrites)
✓ Audit teams that need to trace every merge point
✗ Fast-moving product teams — the graph becomes spaghetti
✗ Small teams shipping daily — too much noise
Overall usage today
6
Open source libraries
9
Solo / small team projects
3
Long-lived feature branches
9
Fast-moving startup codebase
2
Audit / compliance teams
8
02

Squash
& Merge

git merge --squash · the pragmatist's choice

You've met Option B. Here's the git reality — and why this is the one I'd set as your team's default today.

git log --oneline — squash result (linear, clean)
Before (feature branch) C1 C2 F1 F2 F3 F4 "WIP" "fix typo" "try again" "finally" ▼ SQUASH & MERGE C1 C2 FEAT one clean commit ✓
BASH · the git commands
# Git's underlying mechanics:
git merge --squash feature-branch
git commit -m "feat: add user authentication"

# GitHub does both steps for you in one click
My take

"This is the right default for the vast majority of product teams. It's the only strategy that explicitly forgives messy development workflow while still producing a clean, readable history."

Reach for this when…
✓ Product / startup teams — one PR, one commit
✓ Your team doesn't enforce commit message standards
✓ Hotfixes — a fix is a fix, one commit is the right shape
✓ You want git log to read like a human changelog
✗ You need to bisect individual steps of a large refactor
✗ Open source — squashing contributor commits is bad form
Overall usage today
8
Product / startup teams
10
Hotfixes
9
Open source projects
6
Large refactors
4
Teams without commit standards
10
03

Rebase
& Merge

git rebase + fast-forward · the perfectionist's trap

You've met Option C. Here's what the SHA rewrite looks like in actual git — and the exact conditions under which this becomes worth it.

git log --oneline — rebase result (linear, all commits, new SHAs)
Before (feature branch off old main) A B C F1 abc1234 F2 def5678 F3 ghi9012 ▼ REBASE & MERGE A B C F1' NEW SHA F2' NEW SHA F3' NEW SHA
BASH · the git commands
# What GitHub does under the hood:
git checkout feature-branch
git rebase main              # replays commits, creates new SHAs
git checkout main
git merge --ff-only feature-branch  # fast-forward, no merge commit
My take

"Beautiful in theory. Dangerous as a default. If your team writes careful, atomic, well-described commits every time — use it. If they don't — and most teams don't — this is complexity with no reward."

Reach for this when…
✓ Solo dev — no shared SHAs, clean history, zero risk
✓ Your team writes careful, atomic, well-labelled commits
✓ You need full git bisect power for complex debugging
✗ Anyone else has branched off your feature branch
✗ Your team doesn't understand SHA rewriting — it will bite
✗ You want a simple, enforced default — too much trust required
Overall usage today
5
Teams with strong commit hygiene
9
Solo developers
8
Collaborative branches
2
Teams without commit discipline
1
When you need to bisect later
8

My recommendation

If you're setting up a new repo right now, go into GitHub's branch protection settings and disable everything except Squash and merge. You can always open it up later.

Here's the thing most articles won't say directly: picking one strategy and enforcing it matters more than which strategy you pick. A mixed-strategy repo has a history that's impossible to reason about — some PRs are one commit, some are twenty, some have a merge commit. You can't write meaningful git log filters. You can't automate changelogs. It's chaos.

Pick one. Stick to it.

Enforced via GitHub's allowed merge methods setting.

1
SQUASH & MERGE

The right default for most teams. Forgives messy development, produces readable history, and maps perfectly to a PR-based workflow. Enable this, disable the others.

9
2
REBASE & MERGE

Excellent if your team has genuine commit discipline and every developer understands SHA rewriting. Otherwise it's squash with extra risk.

8
3
MERGE COMMIT

The right choice for open source and long-lived parallel branches. The wrong choice as a product team default unless you love reading merge spaghetti.

7 OSS / 4 product

One last thing: the GitHub dropdown defaults to whatever strategy was last used. That means if one developer clicks "Create a merge commit" once, the next person to open a PR will see that as the default. Lock your strategy in GitHub's repository settings under Settings → General → Pull Requests and uncheck the strategies you don't want. This is a five-second change that prevents months of history inconsistency.