Git rebase fails because: Commit xxxx is a merge but no -m option was given
Asked Answered
M

2

6

I had a feature branch:

feature

with lets say 10 commits

then some time ago I started doing experiments on it, but wanted to preserve the current functionality just in case, so I started a new branch:

feature-experiment

and then did another 10 commits

today I decided to merge feature-experiment into feature and then I deleted feature-experiment. There were some merge conflicts which I resolved.

then, my 20 commits which were all using the same name and ending in WIP (work in progress), were very ugly, so I decided to

git rebase -p -i HEAD~22

I changed pick to s to squash them all into the oldest commit for this feature, but I had some merge conflicts (the same as before). I resolved them and then

git add -A && git commit

git rebase --continue

but now I get the following error:

error: Commit asd123qsd is a merge but no -m     option was given.
fatal: cherry-pick failed
Could not pick asd123qsd 

This is the last commit (the merge one)

I tried again, but this time I didnt change this particular commit's pick to s, but got the same error.

How can I carry out this dreadful rebase?

I was thinking, as a possible solution, I could I modify the last commit to add -m to it, but how do I do that and what do I do with this -m command? Are there any other options

Mccammon answered 20/6, 2016 at 14:33 Comment(4)
This is strange, because normally merge commits should be excluded by a rebase unless you explicitly pass the --preserve-merges flag...Hux
I did pass it, actually (-p)Mccammon
should I try without it?Mccammon
I tried without it but now a conflict comes up from much before the feature branch was creatd and I don't know how to resolve itMccammon
H
3

The problem is likely here:

git rebase -p -i HEAD~22

The -p option is described in the git documentation as the short version of --preserve-merges:

-p

--preserve-merges

Recreate merge commits instead of flattening the history by replaying commits a merge commit introduces. Merge conflict resolutions or manual amendments to merge commits are not preserved.

This uses the --interactive machinery internally, but combining it with the --interactive option explicitly is generally not a good idea unless you know what you are doing (see BUGS below).

Since you're trying to squash commits here, preserving merge commits is almost certainly not what you want. Additionally, the warning about combining the --preserve-merges flag with the --interactive (-i) flag is likely relevant here.

Honestly though, using a rebase to do a squash like this may be introducing a lot more complexity than what you need here. If all you want is to squash all of the changes from this branch into a single commit, you can do that like this:

git checkout feature
git reset --soft <base of feature branch>

At this point all the changes from your feature branch should be staged, and the feature branch should be at the base commit. Now you can simply run git commit to create a new commit containing all the changes from your feature branch, which is basically equivalent to a squash.

Hux answered 20/6, 2016 at 15:13 Comment(7)
Thank you I will try that! What should I put in the placeholder you used <base of feature branch>? the commit that I want to start with?Mccammon
That would be the commit your branch is based off of. For example, if you branched off of master, then git merge-base master feature should print the hash of the commit to use for that step. (It should be the parent of the first commit on the feature branch.)Hux
I did this and then pushed. Was rejected, because the other branch had advanced, so I pulled, then pushed. Went to GitHub but all 20 commits are still there and this new one is there as well. What did I do wrong?Mccammon
@J.K. That's a general problem with all git operations that rewrite history. (Rebase, squash, --amend, etc.) The other branch likely didn't "advance", it just still contained the unsquashed commits that were no longer in your local branch. So when you ran git pull it merged all those commits back into your local branch. (Because that's what pull is for.) You have to push with --force whenever you want to delete commits (i.e. rewrite history) on a remote branch. Assuming that is what you intended, reset --hard back to the squashed commit and push again with --force.Hux
by the squashed commit you mean <base of feature branch> or the one that I just uploaded? after that commit, there is some merge commit added as well, so which of those 3 should I reset hard to? I am really sorry for asking so many questionsMccammon
I would have tried all 3 variants but I dont want to mess up even more @HuxMccammon
@J.K. I mean the squashed commit you just committed.Hux
A
1

I get the following error...

The error message will be clearer (since you were preserving merge commits):

'pick' does not take a merge commit.
If you wanted to replay the merge, use 'merge -C' on the commit.

With Git 2.46 (Q3 2024), batch 15, when the user adds to "git rebase -i"(man) instruction to pick a merge commit, the error experience is not pleasant.
Such an error is now caught earlier in the process that parses the todo list.

See commit 4c063c8, commit 0c26738 (30 May 2024) by Phillip Wood (phillipwood).
(Merged by Junio C Hamano -- gitster -- in commit 83ac567, 20 Jun 2024)

rebase -i: improve error message when picking merge

Reported-by: Stefan Haller
Signed-off-by: Phillip Wood

The only todo commands that accept a merge commit are "merge" and "reset".
All the other commands like "pick" or "reword" fail when they try to pick a a merge commit and print the message

error: commit abc123 is a merge but no -m option was given.

followed by a hint about the command being rescheduled.
This message is designed to help the user when they cherry-pick a merge and forget to pass "-m".
For users who are rebasing the message is confusing as there is no way for rebase to cherry-pick the merge.

Improve the user experience by detecting the error and printing some advice on how to fix it when the todo list is parsed rather than waiting for the "pick" command to fail.
The advice recommends "merge" rather than exec git cherry-pick -m ...(man) on the assumption that cherry-picking merges is relatively rare and it is more likely that the user chose pick by a mistake.

It would be possible to support cherry-picking merges by allowing the user to pass "-m" to "pick" commands but that adds complexity to do something that can already be achieved with

exec git cherry-pick -m1 abc123
Auliffe answered 4/8 at 16:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.