For the life of me I can't get git subtree merge
to work. Here's my situation:
I'm working on a built-in part of Moodle called Workshop. The code lives at mod/workshop
in the moodle
directory. I have to upgrade my local Moodle to 2.5 and get my Workshop changes to work in it. So, the obvious solution to me is:
MOODLE_25_STABLE
branch from the upstreamMOODLE_25_STABLE_workshop
based on that branchmod/workshop
from my MOODLE_23_STABLE_workshop
branch into MOODLE_25_STABLE_workshop
That would be easy if I wanted to merge every single file from MOODLE_23_STABLE_workshop
into MOODLE_25_STABLE_workshop
but I'm only interested in replaying my commits to the mod/workshop
directory. Is there an easier way than to cherry-pick
my way through six months of commits? Because I really, really don't want to do that.
Things I have already tried:
$ git subtree merge --prefix=mod/workshop/ MOODLE_23_STABLE_workshop:mod/workshop
error: 402c67f6fedc96a6fed76e663df4e5af9dfa094e: expected commit type, but the object dereferences to tree type
and
$ git merge -s ours --no-commit MOODLE_23_STABLE_workshop
$ git read-tree --prefix=mod/workshop/ -u MOODLE_23_STABLE_workshop:mod/workshop
error: Entry 'mod/workshop/aggregate.php' overlaps with 'mod/workshop/aggregate.php'. Cannot bind.
$ gormster:Documents/moodle$ git read-tree -m --prefix=mod/workshop/ -u MOODLE_23_STABLE_workshop:mod/workshop
fatal: Which one? -m, --reset, or --prefix?
Any guidance is appreciated.
Well, a merge (sans the recursive part of the strategy for dealing with criss-cross merge) is just patching the local tree with diff from most recent common ancestor to the remote one.
There is a command to get the merge base, git merge-base
, but git diff
is even able to call it on it's own if you use the ...
(3 instead of 2 dots) operator.
So the merge is:
git diff HEAD...MOODLE_23_STABLE_workshop -- mod/workshop/ | git apply -3
and than you commit it.
You probably shouldn't try recording MOODLE_23_STABLE_workshop
as base, because it really isn't. If you did, next merge would assume you merged all changes and explicitly reverted the ones outside mod/workshop/
. On the other hand if you don't record the parent, next merge will try to re-apply the changes, causing unnecessary conflicts if the same areas are modified again as git is smart enough to recognize already applied diff, but can't tell when the diff obsoletes other changes.