This is probably a very common scenario but to the best of my efforts I couldn't find any proper answer on it using Google search or use of an LLM chatbot.
This is a team project, I was developing on my sub branch called "devel". I did 6 commits, finally reached a stage where I can push to production so I pushed my changes. On the main branch, using Gitlab's GUI, I created a squashed merge request.
I continued developing on the same branch locally, did a fix, pushed it, created another merge request but Gitlab blocked the merge with this:
So I pulled origin main, tried ff which fails, then tried rebase, merge and finally cherry pick but the all of them want to do 6 stages of rebase/merge/cherry-pick!!! This is totally unexpected. How do I make it understand to not apply those squashed merges from main to my devel branch? Do I have to delete the devel branch at this point and create a new branch to continue with my development? I'd like to have my commit history though.
So my question is how to resolve the Gitlab error and simply make a proper merge request to apply the last commit on devel branch to main branch.
Avoid squash merging if possible. As you found out, it mostly causes headaches. But all is not lost.
Let's say you start with the following history graph, 2 commits only reachable from main
and 4 commits on your devel
branch:
A-B-C-D < main
\
E-F-G-H < devel
Next you create a merge request and squash merge. This gives you a new commit, that I call S
(short for "squash"). It contains all changes from commits E
, F
, G
, and H
.
A-B-C-D-S < main
\
E-F-G-H < devel
Then you keep working on your branch and add a few more commits:
A-B-C-D-S < main
\
E-F-G-H-I-J-K < devel
You cannot (squash) merge that again, because the changes have already been partially applied to main. Attempting a simple rebase will also fail because S
contains the changes of E
(and F
and G
and H
), so E
cannot be applied again – that would be like applying E
on top of H
.
But you can help Git by telling it what the old upstream was:
git rebase --onto main H devel
This command will take the commit range H..devel
(i.e. I
, J
, K
) and apply them on top of main
. This should give fewer conflicts and avoids re-applying patches that already exist upstream. History after the rebase:
A-B-C-D-S < main
\ \
\ I'-J'-K' < devel
\
E-F-G-H-I-J-K