tags:

views:

1589

answers:

4

I have a project that relies upon another 2 subprojects that have been merged using the subtree merge strategy (as described here and there)?

After a while, I have noticed that one of the subprojects is having his own lifecycle inside the current project, so I'd like to decouple it from the original, but I have no idea how to achieve this.

Basically, I have noticed that the subprojects are listed in the .git/config file so I'm wondering if it is enough to remove it from there.

Following Jakub's answer/question, I'll try to add more details to my question. The project I'm working on ProjectA depends on a library LibraryB which has his own git repository and its own lifecycle. While setting up ProjectA, I have used the subtree merge technique to add the dependency of LibraryB (the steps are exactly the ones described in the links thankfully added by VonC). Now, ProjectA needs some custom changes to LibraryB which are not generic enough to be pushed back to LibraryB repository. So, I'd like to decouple the LibraryB in ProjectA from its master repository (by decoupling I mean that LibraryB in ProjectA will not be able to update from its master repository and will have its own history tracked only inside ProjectA).

More details: after checking my ProjectA repository I have figured out that the only reference to LibraryB repository lives in ProjectA/.git/config file in the form:

[remote "gaelib"]
    url = ../libraries/gaelib
    fetch = +refs/heads/*:refs/remotes/gaelib/*

and there is not additional git related information in the directory LibraryB was included in ProjectA (../libraries/gaelib)

A: 

If you want to maintain your own version of LibraryB you have a few options:

  • You can make LibraryB inherent part of your project: just remove or comment out [remote "LibraryB"] section in the config file, and make changes to LibraryB inside your project.

    The disadvantage is that it would be harder to send patches for canonical (third-party) version of LibraryB

  • You can continue using 'subtree' merge, but not from the canonical version of LibraryB, but from your own clone (fork) of this library. You would change remote.LibraryB.url to point to your local version, and your local version would be clone of original LibraryB. Note that you should merge your own branch, and not remote-tracking branch of canonical LibraryB.

    The disadvantage is that you have to maintain separate clone, and to remember that your own changes (well, at least those generic) to LibraryB have to be made in the fork of LibraryB, and not directly inside ProjectA.

  • You might want to move from 'subtree' merge which interweaves history of ProjectA and LibraryB, to having more separation that can be achieved using submodule (tutorial). In this case you would have separate repository (fork) of LibraryB, but it would be inside working area of ProjectA; the commit in ProjectA would have instead of having tree of LibraryB as subtree, pointer to commit in LibraryB repository. Then if you do not want to follow LibraryB development, it would be enough to simply not use 'git submodule update' (and perhaps just in case comment out or remove link to canonical version of LibraryB).

    This has the advantage of making it easy to send your improvements to canonical LibraryB, and the advantage that you make changes inside working area of ProjectA. It has disadvantage of having to learn slightly different workflow.

    Additionally there is also an issue of how to go from 'subtree' merge to submodules. You can either:

    • Move from subtree merge to submodule by creating git repository in the subproject subtree in superproject working repository (i.e. "git init" inside appropriate subdirectory + appropriate "git submodule init" etc.). This means that you would have 'subtree' up to some point of history, and submodule later.
    • Rewrite history using git filter-branch to replace subtree merge by submodule. This has the disadvantage of rewriting history (big no if somebody based his/her work on current history), and advantage of 'clean start'. Or you can wait a bit for "git submodule split" (thread on git mailing list) to make it into git...
      Unfortunately Splitting a git repository blog posts returns "host not found"

I hope that this version solve your problem.

Disclaimer: I have used neither subtree merge, nor submodules, nor git-filter-branch personally.

Jakub Narębski
I have tried to provide as much details as I could figure out. Thanks for trying to address my question.
alexpopescu
Does expanded answer address you problem better?
Jakub Narębski
+3  A: 

I don't get it. If you've included libraryB in projectA repository using subtree merge method, you don't have to do any decoupling. You already have exactly what you need:

  • You can pull updates to libraryB from libraryB repository. Which, I'd guess, is a good thing.

  • You can commit changes to libraryB inside the repository of projectA. This changes will remain local to this repository unless you decide to push/pull them to another repository. They will be part of projectA history only and won't automatically propagate to libraryB repository.

That's the whole point of subtree merge method as opposed to submodule method.

Tomek Szpakowicz
+2  A: 

Yes, remove that remote pointing to libraryB from the config file. That will prevent anyone using your repo from inadvertently updating your local code from the remote.

There's nothing else you have to do -- you simply don't pull from or push to the LibraryB repo any more.

Paul
I'll clone the repo and try it out just to make sure I'm not screwing it. I'll post back.
alexpopescu
+2  A: 

It sounds like you want to "undo" a subtree merge and submit it back upstream. The git subtree split command should do this.

apenwarr