ProbableOdyssey

TIL: Fixing an incorrect Git rebase

Have you ever found yourself in this situation? You’ve used git rebase to clean up commit history or integrate changes from another branch. And now your changes appear out of sync, and somehow Git thinks you’ve deleted code from the branch you initially started from.

This happens because rebasing fundamentally alters Git history rather than preserving it.

Each commit is a snapshot of the repo at a particular point in time, and the order of these snapshots matters immensely. When you rebase, you’re essentially taking your commits and replaying them on top of a different base commit, which changes their context and can create conflicts with the existing history.

Unfortunately, this fundamental concept isn’t made clear when using Git in day-to-day operations — the commands feel simple, but they’re performing complex history manipulation under the hood.

Prevention is Better Than Cure

In my opinion, the way to avoid this is to use git merge instead of git rebase unless you absolutely need to rewrite history. Here’s why:

Once you’ve rebased incorrectly, a simple merge after the fact won’t solve the problem. The changes you made happened after those latest commits, so Git still believes you’ve deleted legitimate code.

The Solution: Diff and Apply

We’re trying to pull changes from <other-branch> into <my-branch>. After a bad rebase, the changes from <other-branch> are nowhere to be found. We’ll head to the terminal to fix it:

Let’s list the files that are different:

git diff HEAD..<other-branch> --name-only

The HEAD..<other-branch> syntax means “show me what changes will take me from HEAD (my current commit) to <other-branch>” — essentially, what’s in the other branch that I’m missing.

We only want to merge changes from a subset of files, so let’s exclude the files we don’t want to patch. (For example, let’s exclude the file uv.lock and all markdown files)

git diff HEAD..<other-branch> --name-only -- ':(exclude)uv.lock' ':(exclude)**/*.md'

Once we’re happy with the list of files, let’s make a patch:

git diff HEAD..<other-branch> -- ':(exclude)uv.lock' ':(exclude)**/*.md' > patch.diff

Open the file patch.diff in your editor — we can see all the changes that would occur if we apply the patch. There might be some unrelated changes, so let’s edit the patch and remove the changes we don’t want and save it.

Now we can apply the changes:

git apply patch.diff

There may be some conflicts, edit the files and resolve the conflicts one by one. Once we’re finished, we can remove the patch.diff file.

Now git add your changes and git commit as you normally would.

All good now!

Reply to this post by email ↪