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 /DTOs
and /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 /dtos
and /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 /dtos
or /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 rebase
or merge
from 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)
git pull --rebase origin develop
done.