# How to Squash Multiple Commits Into One With Git Rebase

'https://travismedia.gumlet.io/src/assets/images/2025/09/git-squash-commits-rebase-boot.jpg';

Ever made a small change, committed it, then made another tweak, and another—and now your pull request is full of little “fix typo” or “remove extra space” commits?

Squashing lets you combine them into a **single, clean commit** so your project history is easier to read.

<Image src={gitSquashImage} alt="a boot squashing a bunch of git commits with sha hashes showing" />

## Why Squash?

- Keeps the commit history tidy and logical.
- Makes `git log` more useful for future debugging.
- Groups related changes together for easier code review.

## Hypothetical Example

Let’s say you’re working on a branch called `feature/add-greeting` and you made these commits:

- abc123 Add greet() function
- def456 Fix typo in greet() message
- ghi789 Remove extra blank line

Your reviewer says: _“Looks good, but please squash these into one commit with a clear message.”_

---

## Step 1 — Start an Interactive Rebase

Run this from your feature branch:

```bash
git rebase -i HEAD~3
```

We’re rebasing the last 3 commits (adjust the number if you have more or fewer).

## Step 2 — Mark Commits to Squash

Git opens an editor showing something like:

```bash
pick abc123 Add greet() function
pick def456 Fix typo in greet() message
pick ghi789 Remove extra blank line
```

Change the second and third lines from pick to squash (or just s):

```bash
pick abc123 Add greet() function
squash def456 Fix typo in greet() message
squash ghi789 Remove extra blank line
```

Save and close.

## Step 3 — Write a Clear Commit Message

Git will now combine the commits and open another editor with all the old commit messages.

Replace them with one concise, clear message:

```bash
greet: add function to display welcome message

- Added greet() to print "Hello, world!"
- Fixed a typo in the greeting text
- Removed extra blank line for cleaner output

Reason:
Keeps greeting logic simple and output clean.
```

The top line will be the commit title and the rest the commit description.

Save and close.

## Step 4 — Handle Any Conflicts

If Git stops and says there’s a conflict:

```bash
# Fix the file(s) manually, then:
git add <file>
git rebase --continue
```

## Step 5 — Verify Your New Commit

```bash
git log --oneline -n 3
git show HEAD
```

You should now see a single commit with your new message and the combined changes.

## Step 6 — Push Your Changes

Because you’ve rewritten history, you need to force push:

```bash
git push --force-with-lease origin feature/add-greeting
```

The `--force-with-lease` option ensures you don’t overwrite someone else’s work on the branch.

## Extra tips

### Accidentally messed up?

```bash
git rebase --abort
```

This cancels the rebase and puts your branch back to where it started.

### Don’t like `vi`?

What's wrong with you!

Just kidding.

```bash
git config --global core.editor "nano"    # or "code --wait"
```

### PR Descriptions vs. Commit Messages

The PR description is great during review, but the commit message is what lives on forever in the repo. Don’t skimp on it.

## TLDR

```bash
git rebase -i HEAD~3 # or whatever total number of commits
# mark 2nd+ commits as squash
# write a clear, why-first commit message
git push --force-with-lease origin <branch>
```