Let's say you have an iOS project, and you want to use some external library, like AFNetworking. How do you integrate it?
Add the project to your repo:
git submodule add [email protected]:AFNetworking/AFNetworking.git Vendor/AFNetworking
or something to that effect.
Well, what happens if you find a bug in AFNetworking that you want to fix? With submodules, I'd usually
- Fork AFNetworking
- Go through the pain of changing my project's submodules to point to my new fork
- Make my change and commit it to my fork
- Submit a pull request to AFNetworking repo
- Wait to see if the pull request is accepted, but keep my fork up-to-date in the meantime
- If it is accepted, do the whole dance to switch my submodule back to the official AFNetworking repo
- Continue as usual
Okay, that sucks. If you've ever done it, you know how painful it is and how finicky submodules can be.
Add the project to your repo:
git subtree add --prefix=Vendor/AFNetworking --squash [email protected]:AFNetworking/AFNetworking.git master
This is pretty similar so far except the other members of your team won't have to remember to run git submodule update because subtrees actually store the source in your repo. Nice.
Now, let's say we have the same bug. What do I do differently now that I'm using subtrees?
I make my change and commit it to my project's repository. Technically, I could stop now if I wanted to since the bug fixed code is in my repository. But, I want to be a good open source citizen, so what do I do?
- I'll fork AFNetworking into my account on Github.
- Back in my local repo:
git subtree split --prefix=Vendor/AFNetworking/ --branch AFNetworking
to set up being able to push changes to my fork. 3. I'll push my change to my fork, but on a branch to make the pull request more awesome.
git push [email protected]:kvnsmth/AFNetworking.git AFNetworking:critical-bug-fix
- I would issue a pull request and hope it gets accepted, but a big difference is that the acceptance of my change doesn't keep me from being able to easily stay in sync with the official AFNetworking repo.
I can still do:
git subtree pull --prefix=Vendor/AFNetworking --squash [email protected]:AFNetworking/AFNetworking.git master
to stay up-to-date with the latest in the official repository.
Now, I think that is much better than using submodules and a lot less invasive to my repo.
@funkytaco I'm curious as well.
The thing that I find offputting about subtrees is exactly what people praise about them: they hide the existence of other repos a little too well for my taste.
If I clone a repo that contains subtrees, I will not really notice. Whatever changes I make may not find their way back out to the original repo that created the subtree. I'm surprised that nobody else seems to mind this at all.
I fear that while it is robust on my own repo (it will not break, as easily happens with submodules), the cohesion between the linked repos weakens. This is bad if you're developing e.g. a library in one repo and an application that uses your library in a separate repo (which would make a lot of sense to me).
You have to manually split out your changes and apply them to the remote repo.
OTOH submodules are very brittle, so I'm reluctant to use them as well.
I have no good answer right now.