I'm currently in the process of trying to switch our version control to Git (from CVSNT). Surprisingly, it wasn't the distributedness or the concept of a staging area that I had problems with. But I am having quite a bit of trouble wrapping my head around the fact that AFAICT operations like branching, merging and tagging always are applied at the repository level rather than the file or directory level...
We reuse a lot of our code across different projects. My working area currently looks like this:
/Dev
/Libs
/LibA
/LibB
/LibC
/Project1
/Project2
/Project3
/WebDev
Now, let's say Project1 depends on LibA and LibB, Project2 depends on LibB and LibC and Project3 has no lib dependencies. Some of these libs are later compiled into DLLs (or BPLs - our primary development environment is Delphi), others are mere collections of reusable code that gets included on a file-by-file-basis into the main projects.
WebDev contains the code for our (mostly static) company web site which also contains information about Project1,2,3 and thus might have to be tagged together with them.
As I switch between projects quite a lot I usually have all of this checked out at the same time, updating the lib directories on-the-fly to the appropriate project branches where necessary.
How would I model this in Git and would it even make sense to stick to this way of working? I have read about git submodules but so far I fail to see how I would apply that here for several reasons:
As far as I have understood, submodules would always be checked out inside their respective "superproject". However, we found managing multiple copies of (designtime) library code with Delphi to be a royal PITA, which is one of the reasons why we keep all the libs under a common directory outside the individual project trees. Additional copies are only ever checked out by build automation, never for doing any actual work on.
I don't really want the libs to be "independent" from the projects: If I tag or branch one of the projects I always want to tag or branch the respective libs as well. When I want to go back to a specific tagged revision of the main project I want the libs to be reverted to that state as well. If possible tagging/branching/checking-out should always happen in a single step for a project and its dependencies.
I already made one attempt to put everything in a single Git repository with the library code primarily managed on the master branch, and the "projects" each on its own branch but whenever I try to merge lib changes between master and the project branches it pulls in all the files from the unrelated libs as well which is not what I want at all...
Do you guys have any ideas how best to resolve all this? I'm open to pretty much all suggestions, including a new layout for my working tree.
If anyone could point me to a real hands-on tutorial about submodules (or whatever other technique I'll need to accomplish this), that would be great, too.