Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use `git subtree split` to maintain a "fork" of a project's subdirectory?

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:

  • A subdirectory of a project is being spun off as its own separate project. The parent project is removing the subdirectory entirely and the new project lives its own life.
  • A maintainer of a parent project wants to allow maintenance of a subdirectory on its own terms and spins it off into its own repository, which is added back to the main project using 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:

  • Use 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 repository
  • Create a master branch from my project with enhancements from this point
  • Keep updating upstream_vx.y by running git subtree split occasionally
  • When I need a bug fix or whatnot from upstream, merge upstream_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?

like image 888
jasonmp85 Avatar asked May 28 '14 22:05

jasonmp85


People also ask

What is git subtree split?

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.

What is git subtree push?

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.


1 Answers

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).

like image 176
Mike Avatar answered Oct 07 '22 02:10

Mike