git rebase skips reapplied commits
If the same commit is made and then reverted on both <upstream> and <branch>, and then reapplied only on <branch>, thengit rebase <upstream> <branch> will skip the reapplied commit.
The following script demonstrates the issue:
```
#!/bin/sh -eu
# Set up a repo for the following commands.
repo_directory="./rebase-test-repo"
rm -rf "${repo_directory}"
mkdir -p "${repo_directory}"
cd "${repo_directory}"
git init -b main
git config user.name test
git config user.email [email protected]
# Create a branch 'br' starting from a commit other than the tip of the
# 'main' branch. Switch to it.
git commit --allow-empty -m 'initial commit'
git commit --allow-empty -m 'another empty commit'
git switch --create br HEAD^
# Create a non-empty commit on 'br', then revert it.
touch a
git add a
git commit -m 'Add a'
git revert --no-edit HEAD
# Make identical commits on 'main'.
git switch main
touch a
git add a
git commit -m "Add a (on 'main')"
git revert --no-edit HEAD
# Reapply the reverted commit to 'br'.
git switch br
git revert --no-edit HEAD
# Rebase 'br' onto 'main'.
git rebase main br
git -P log --graph --all --oneline
# Sample output:
#
# * 5b4d655 (HEAD -> br, main) Revert "Add a (on 'main')"
# * 7881a38 Add a (on 'main')
# * 907f1a8 another empty commit
# * 6c094a9 initial commit
#
# What we expect to see:
# The commit 'Reapply "Add a"' should have been rebased onto 'main'.
#
# What we see:
# This commit was skipped during the rebase and has been lost.
```Using the '--reapply-cherry-picks' option prevents this from happening, but it also creates empty commits, so it's not a proper workaround.
[System Info]
git version:
git version 2.48.1
cpu: x86_64
no commit associated with this build
sizeof-long: 8
sizeof-size_t: 8
shell-path: /gnu/store/jlqbjxk51bdq5w7wlnbmwxm1j0pnllpx-bash-minimal-5.1.16/bin/sh
zlib: 1.3
compiler info: gnuc: 11.4
libc info: glibc: 2.39
$SHELL (typically, interactive shell): /gnu/store/cdwviyfnsfv7k57qrwmym0mrynjixc1i-bash-5.1.16/bin/bash
[Enabled Hooks]
not run from a git repository - no hooks to show
Quoted 4 lines · On Tue, Mar 11, 2025 at 11:11 AM 45mg <[email protected]> wrote:
If the same commit is made and then reverted on both <upstream> and <branch>, and then reapplied only on <branch>, then
git rebase <upstream> <branch>will skip the reapplied commit.
Yes, as expected and as documented. Another commit exists upstream which introduces the same change, so it is omitted.
Quoted 26 lines
The following script demonstrates the issue:
```
#!/bin/sh -eu# Set up a repo for the following commands.
repo_directory="./rebase-test-repo"
rm -rf "${repo_directory}"
mkdir -p "${repo_directory}"
cd "${repo_directory}"
git init -b main
git config user.name test
git config user.email [email protected]# Create a branch 'br' starting from a commit other than the tip of the # 'main' branch. Switch to it.
git commit --allow-empty -m 'initial commit'
git commit --allow-empty -m 'another empty commit'
git switch --create br HEAD^# Create a non-empty commit on 'br', then revert it. touch a
git add a
git commit -m 'Add a'
git revert --no-edit HEAD
Quoted 6 lines
# Make identical commits on 'main'.
git switch main
touch a
git add a
git commit -m "Add a (on 'main')"
git revert --no-edit HEAD
Note that this does not match your original description, and your comment here, "Make identical commits on 'main'" is not (always) correct. If there's even a little lag between when the last two commands run and the ones before them, then the commits on 'br' and the commits on 'main' are not the same.
Quoted 6 lines
# Reapply the reverted commit to 'br'.
git switch br
git revert --no-edit HEAD# Rebase 'br' onto 'main'.
git rebase main br
I would have expected
git rebase --onto main br~1 br
due to the non-identical commits issue I mentioned above, though without --reapply-cherry-picks it doesn't really matter. With --reapply-cherry-picks, though, it matters because I would have expected you wanted 5 commits rather than 7 (empty initial commit, another empty commit, Add a on main, revert add a on main, Add a, revert that, Reapply add a).
Quoted 6 lines
git -P log --graph --all --oneline
# Sample output:
#
# * 5b4d655 (HEAD -> br, main) Revert "Add a (on 'main')" # * 7881a38 Add a (on 'main')
# * 907f1a8 another empty commit
Quoted 8 lines
# * 6c094a9 initial commit
#
# What we expect to see:
# The commit 'Reapply "Add a"' should have been rebased onto 'main'. #
# What we see:
# This commit was skipped during the rebase and has been lost. ```
Yes, it's behaving as documented.
Quoted 2 lines
Using the '--reapply-cherry-picks' option prevents this from happening, but it also creates empty commits, so it's not a proper workaround.
It'll only create an empty commit if (a) the commit being cherry-picked is empty, or (b) the application of the changes from the commit result in no-change.
In this example you provided, no empty commit would be created (whether or not you used your original rebase command or the modification I expected).
So, it looks like precisely the appropriate workaround if you really want to reapply these commits. Why do you think it's not the right workaround?