In short, I want to "fork" a subdirectory of another project (not under my control) to the top-level of a new repository and make enhancements to the code in that subdirectory while preserving the ability to merge in changes from the subdirectory in the upstream project.
I've been reading up on this topic for a while now but can't find a sure answer for my situation. Most of the uses of git subtree
break down into these cases:
git subtree add
These use cases don't apply to me: I'm not forking-and-forgetting, and I don't own both sides of this fork, so the git subtree add
flow isn't applicable.
So let's say the original module lives in contrib/foo
in the main project. My current idea is to:
git subtree split -P contrib/foo -b upstream_vx.y
to create a new history that "hoists" the subdirectory up to the top-level of a repositorymaster
branch from my project with enhancements from this pointupstream_vx.y
by running git subtree split
occasionallyupstream_vx.y
into my master
This doesn't feel "git-like" to me. Specifically, I'm basically creating a parallel history of the upstream project's subdirectory and maintaining my own "hoisted" branch for each major upstream branch (to say nothing of being able to reference upstream tags).
Is there a better way to go about this?
Splitting the Original Repository The subtree commands effectively take a folder and split to another repository. Everything you want in the subtree repo will need to be in the same folder.
git subtree split lets you specify a rev other than HEAD. ' git push '(man) lets you specify a mapping between a local thing and a remot ref. So smash those together, and have git subtree push let you specify which local thing to run split on and push the result of that split to the remote ref.
I think I have been maintaining a similar situation to you. I have a primary project (ProjA) which has modules, and I am adding a subtree of a second project (ProjB) into the primary's modules. In order to accomplish this, I maintain a copy ProjB.
Split ProjB:
cd ProjB
git checkout -b split-maint
git subtree split --prefix=important/dir --branch=module-for-A
Add the subtree to ProjA:
cd ProjA
git remote add ProjB_remote /path/to/ProjB
git fetch ProjB_remote
git subtree add --prefix=modules/projB_mod ProjB_remote/module-for-A --message="commit message"
Then to update/maintain, re-split the original (as above). The key here is git subtree split is repeatable, and the SHA of each revision that was previously split will be the same.
Update ProjA with the new details:
cd ProjA
git fetch ProjB_remote
git subtree merge --prefix=modules/projB_mod ProjB_remote/module-for-A --message="commit message"
Technically I do it slightly differently because my ProjB has a lot of commits and the split actually takes an hour to run. I can give you details on how to help with that too if you need it. (Just comment, and I will update this answer).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With