Jamie
Jamie

Reputation: 2081

The previous cherry-pick is now empty when not cherry-picking

I am trying to drop a list of commits by using git rebase -i HEAD~19. I have successfully used this method in the past, but when I try running and then quitting vim without any changes(:q!) I get this error:

The previous cherry-pick is now empty, possibly due to conflict resolution.
If you wish to commit it anyway, use:

    git commit --allow-empty

Otherwise, please use 'git cherry-pick --skip'
interactive rebase in progress; onto dd0b851

I am not cherry picking and not sure why I'm getting an error to skip.

Upvotes: 4

Views: 3904

Answers (2)

VonC
VonC

Reputation: 1324347

You might need to git rebase --empty(=drop|keep|ask) option:

How to handle commits that are not empty to start and are not clean cherry-picks of any upstream commit, but which become empty after rebasing (because they contain a subset of already upstream changes).
With drop (the default), commits that become empty are dropped.

This is especially useful (now Q2 2024) because the git cherry-pick done in the background by git rebase also understand --empty(=drop|keep|ask)

With Git 2.45 (Q2 2024), batch 14, allow git-cherry-pick(1) to automatically drop redundant commits via a new --empty option, similar to the --empty options for git-rebase(1) and git-am(1).

See commit ec79d76, commit bd2f9fd, commit 661b671, commit 1b90588, commit c282eba, commit 64a443e, commit 0af3889 (25 Mar 2024) by Brian Lyles (brianmlyles).
(Merged by Junio C Hamano -- gitster -- in commit 17381ab, 03 Apr 2024)

cherry-pick: add --empty for more robust redundant commit handling

Signed-off-by: Brian Lyles

As with git-rebase(1) and git-am(1), git-cherry-pick(1) can result in a commit being made redundant if the content from the picked commit is already present in the target history.
However, git-cherry-pick(1) does not have the same options available that git-rebase(1) and git-am(1) have.

There are three things that can be done with these redundant commits: drop them, keep them, or have the cherry-pick stop and wait for the user to take an action.
git-rebase(1) has the --empty option added in commit e98c426 ("rebase (interactive-backend): fix handling of commits that become empty", 2020-02-15, Git v2.26.0-rc0 -- merge listed in batch #8), which handles all three of these scenarios.
Similarly, git-am(1) got its own --empty in 7c096b8 ("am: support --empty= to handle empty patches", 2021-12-09, Git v2.35.0-rc0 -- merge listed in batch #7).

git-cherry-pick(1), on the other hand, only supports two of the three possiblities: Keep the redundant commits via --keep-redundant-commits, or have the cherry-pick fail by not specifying that option.
There is no way to automatically drop redundant commits.

In order to bring git-cherry-pick(1) more in-line with git-rebase(1) and git-am(1), this commit adds an --empty option to git-cherry-pick(1).
It has the same three options (keep, drop, and stop), and largely behaves the same.
The notable difference is that for git-cherry-pick(1), the default will be stop, which maintains the current behavior when the option is not specified.

Like the existing --keep-redundant-commits, --empty=keep will imply --allow-empty.

The --keep-redundant-commits option will be documented as a deprecated synonym of --empty=keep, and will be supported for backwards compatibility for the time being.

git cherry-pick now includes in its man page:

previous commit will cause the cherry-pick to fail. To force the inclusion of those commits, use --empty=keep.

git cherry-pick now includes in its man page:

--empty=(drop|keep|stop)

How to handle commits being cherry-picked that are redundant with changes already in the current history.

-- drop;; The commit will be dropped. keep;; The commit will be kept. Implies --allow-empty. stop;; The cherry-pick will stop when the commit is applied, allowing you to examine the commit. This is the default behavior.

Note that --empty=drop and --empty=stop only specify how to handle a commit that was not initially empty, but rather became empty due to a previous commit. Commits that were initially empty will still cause the cherry-pick to fail unless one of --empty=keep or --allow-empty are specified.

Upvotes: 1

TTT
TTT

Reputation: 28944

This is happening because you aren't doing what you think you're doing:

but when I try running and then quitting vim without any changes(:q!)...

When you quit without modifying that file, you are actually still doing the rebase. If you want to exit without doing the rebase, you should delete all the lines in the file (or at least every line that contains a commit on it), and then save and exit. This will display an error and abort the rebase.

The reason just exiting usually works, and appears to do nothing, is because when your history is linear, by default Git won't rewrite a commit if nothing at all about the commit has changed, so it keeps the original commit ID and moves on. This is why you still see "rebasing 1/X..." as it iterates through all the commits and doesn't actually re-write them.

If you history is not linear (meaning you have some merge commits included in the rebase), the merge commits are not included in the to-do list. So this time rebasing will actually rewrite at least some of the commits, because you are missing the merge commits in this rewrite so the graph isn't identical. During the rebase, if it encounters a commit with no changes in it, you will get the message you saw. It stops here because this is considered unusual and it gives you the opportunity to decide what to do. The reason it mentions cherry-pick is because behind the scenes, rewriting commits during a rebase is essentially doing a cherry-pick of each commit for you.

Side Note: the most likely reason that you would have empty commits in this situation is when you have a similar commit on both sides of a merge commit (which is missing from the rebase to-do list).

Upvotes: 6

Related Questions