---
title: git history drop and git branch --delete-merged in Git 2.56
url: https://calvin.my/posts/git-history-drop-and-git-branch-delete-merged-in-git-2-56
published: 2026-10-03
updated: 2026-10-03
category: Development
tags:
- git
- Homebrew
- MacOS
- CLI
summary: Git 2.56 adds tools for simplifying local repository maintenance. One removes an unpushed commit from the middle of a branch by replaying later work, offering a safer preview first; pushed commits should instead be reverted to avoid disrupting collaborators. Another removes local branches already merged into their configured upstream, also with preview support. It skips unmerged, checked-out, and separately tracked branches, while squash or rebase merges may require manual deletion.
---

# git history drop and git branch --delete-merged in Git 2.56

**Git 2.56.0** (released 28 Sep 2026) ships a long list of changes ([Release notes](https://github.com/git/git/blob/master/Documentation/RelNotes/2.56.0.adoc)). Two of them caught my eye because I can use them every day: `git history drop` removes a commit from the middle of a branch, and `git branch --delete-merged` cleans up local branches whose work has already landed. Apple Git on my Mac is still 2.54.0, so this article starts with switching to Homebrew Git.


-----

## 1) Switch from Apple Git to Homebrew Git

1. Check the current version.

```bash
% git --version
git version 2.54.0 (Apple Git-157)
```

2. Install Git with Homebrew.

```bash
% brew update
% brew install git
```

3. Put Homebrew's `bin` ahead of `/usr/bin` and reload the shell config.

```bash
% echo 'export PATH="/opt/homebrew/bin:$PATH"' >> ~/.zshrc
% source ~/.zshrc
```

**NOTE:** `/opt/homebrew` is the Apple Silicon prefix. On an Intel Mac, use `/usr/local/bin`. If your `~/.zprofile` already runs `brew shellenv`, Homebrew's `bin` is on the `PATH` already and a new terminal tab is enough.

4. Verify.

```bash
% which git
/opt/homebrew/bin/git
% git --version
git version 2.56.0
```

-----

## 2) git history drop

`git history drop <commit>` removes a commit and replays everything after it onto that commit's parent. Previously this meant a `git rebase -i`, changing `pick` to `drop` in the todo list.

1. Find the commit to remove.

```bash
% git log --oneline
d87473d Add feature two
e483de2 WIP: debug logging
07b6c06 Add feature one
e3e8ba4 Initial commit
```

2. Preview with `--dry-run`. It prints the ref it would update, with the new and old hash, and changes nothing.

```bash
% git history drop --dry-run e483de2
update refs/heads/main 50c46c7f7cb74f730b95ff9879178a8010871a4a d87473dfab54ac495f08f0107613dfcf35b3dc30
```

3. Drop it. `Add feature two` gets a new hash because it was replayed.

```bash
% git history drop e483de2
% git log --oneline
50c46c7 Add feature two
07b6c06 Add feature one
e3e8ba4 Initial commit
```

### Which command to use

| The unwanted commit is | Use |
|---|---|
| Unpushed, the last one | `git reset --soft HEAD~1` |
| Unpushed, in the middle | `git history drop <commit-hash>` |
| Pushed | `git revert <commit-hash>` |

- `git reset --soft HEAD~1` undoes the commit but keeps its changes staged, ready to fix and commit again. To throw the changes away instead, `git history drop HEAD` works on the last commit too.
- Dropping a pushed commit rewrites every commit after it, which needs a force push and leaves everyone who pulled it with a diverged branch. `git revert` adds a new commit that undoes it, so play safe.

---

## 3) git branch --delete-merged

`git branch --delete-merged <pattern>` deletes local branches whose upstream matches `<pattern>`, but only when the branch tip is already reachable from that upstream, i.e. the work has landed. Given a remote name, it uses the branch the remote's `HEAD` points at, so `origin` means `origin/main`. ([Reference](https://git-scm.com/docs/git-branch))

1. Fetch, so `origin/main` includes the merged pull requests.

```bash
% git fetch
```

2. Check each branch's upstream.

```bash
% git branch -vv
  add-search 06d355d [origin/main: ahead 1, behind 4] Add search
  fix-login  af95100 [origin/main: behind 3] Fix login redirect
  fix-typo   df6b8d8 [origin/fix-typo] Fix typo
* main       859f1d4 [origin/main: behind 4] init
```

3. Preview with `--dry-run`.

```bash
% git branch --dry-run --delete-merged origin
Would delete branch fix-login (was af95100).
```

4. Delete.

```bash
% git branch --delete-merged origin
Deleted branch fix-login (was af95100).
```

Only `fix-login` goes. `add-search` has a commit that is not on `origin/main` yet, and `main` is checked out. `fix-typo` was merged too, but it tracks its own remote branch, which the command skips.

### Things to take note of

1. Squash and rebase merges create new commits, so the branch tip never becomes reachable from `origin/main` and the branch is skipped. Delete those with `git branch -D`.
2. Unmerged branches are skipped silently.
