Git 2.56.0 (released 28 Sep 2026) ships a long list of changes (Release notes). 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.
% git --version
git version 2.54.0 (Apple Git-157)
  1. Install Git with Homebrew.
% brew update
% brew install git
  1. Put Homebrew's bin ahead of /usr/bin and reload the shell config.
% 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.

  1. Verify.
% 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.
% git log --oneline
d87473d Add feature two
e483de2 WIP: debug logging
07b6c06 Add feature one
e3e8ba4 Initial commit
  1. Preview with --dry-run. It prints the ref it would update, with the new and old hash, and changes nothing.
% git history drop --dry-run e483de2
update refs/heads/main 50c46c7f7cb74f730b95ff9879178a8010871a4a d87473dfab54ac495f08f0107613dfcf35b3dc30
  1. Drop it. Add feature two gets a new hash because it was replayed.
% 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)

  1. Fetch, so origin/main includes the merged pull requests.
% git fetch
  1. Check each branch's upstream.
% 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
  1. Preview with --dry-run.
% git branch --dry-run --delete-merged origin
Would delete branch fix-login (was af95100).
  1. Delete.
% 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.