I currently have a single pre-existing Git repo for a client/server solution that contains three subdirectories for 3 sub-projects:
/client - An Angular2 SPA application (client-side TypeScript) /dtos - Language-agnostic web-service DTO (data contract) definitions written in T4 /client - T4-generated TypeScript typings *.d.ts files /server - T4-generated C# DTO classes /server - The web-service
So far this is all in a single
master branch, with appropriate temporary
dev/ branches that are merged when their work is complete:
o--o--o--o - master \ / o-o - dev/foo
We need to do some A/B (or rather, A/B/C/D) testing on radically different UX options in the Angular2 project - I would like to branch-off for each UX option, to generate different builds we can test, then after our UX research is done we merge that specific branch back into
master for the remainder of the project:
o - master \ o--o--o---o - ux/red-background \ o--o----o - ux/new-sidebar \ o--o - ux/new-sidebar-and-banner
However I only want to branch the
/Client directory off - so the
/Server directories always contain the latest code.
In SVN and TFS this is easily doable because branches can be made from subdirectories, not just the entire repository (as they are with git), so if this were an SVN project then I would do something like this:
cd trunk # this is the solution root with the client, dtos and server directories svn copy ^/trunk/client ^/branches/red-background svn copy ^/branches/red-background ^/branches/new-sidebar # then after some commits to 'new-sidebar'... svn copy ^/branches/new-sidebar ^/branches/new-sidebar-and-banner
Then to build the solution with each different branch of
/client we modify the symlink:
cd trunk # to 'checkout' the red-background version prior to building: ln -s branches/red-background client # or the new-sidebar version: ln -s branches/new-sidebar client
The main advantage of this approach is that commits can continue to be made to the
/server directories without affecting
client at all - regardless of whatever branch of
client is being worked-in.
Whereas with git, a branch is a separate timeline entirely, so this scenario becomes impossible.
I understand that to get the result I want, I would still need to create different branches for each version to test or build, but changes to
/server would still need to happen in
master (just like in
trunk in SVN) but after every commit everyone working on the different
client branches would need to
master, and that has the potential to get really ugly (especially if individual people
rebase from multiple commits to
/server choosing their own rebase points - they might end up with identical codebases but different commit hashes).
What's the solution?
(Another solution is to move
client to its own git repo - then merging it back into the solution repo when it's all done - I'm not opposed to this but let's pretend that we've hit our maximum repo count in our organizational GitHub account)