简体   繁体   中英

How do I set up my git repositories to easily be able to reuse projects in Visual Studio

My problem may be best described with an example.

Assume I have a project "A".

I also have a project "B" which depends on "A".

Another project "C" also depends on "A".

My "main" project depends on "B" and "C". It may also be that it also depends directly on "A".

Looks a bit like the "dreaded diamond of inheritance" when "main" == "D"

可怕的继承钻石

These are my requirements:

  • I'd like to be able to edit the content of projects "A", "B" and "C" in the solution for "main " and submit changes (ie I don't want just to include the DLL but also the code). But since "B" and "C" both depend on "A", it should be enforced that they reference the same commit.

  • The projects "A", "B" and "C" will most likely also be referenced by other projects, so I cannot assume ownership of the working directory for project "main".

  • Also it should be possible to sync the repositories for each project with external repositories.

  • The projects "A", "B", "C" and "main" should be

How do I need to set up my repositories to accomplish this?

Do not (ab)use git or any version control system for this.

Use NuGet .

You don't want to directly include other projects. Instead, pack every dependency into a .nuget package and use that for dependency handling. While submodules seems a solution to the problem, in practice, you are much better off using a proper dependency management instead of just including other projects.

TeamCity and other CI systems, even TFS, allow you to automatically build new nuget packages, and TeamCity can also act as a nuget server.

And if you do not want to use a 'real' NuGet server, you can also just use a shared drive somewhere on your intranet.

Using the submodules approach , I would recommend a model which includes a list of dependencies, instead of a hierarchy of dependencies:

Create a " parent " repo, in which you " git submodule add " the submodules for D , C , B and A :

parent
  D
  C
  B
  A

Add any symlink ( even in Windows ) you need for each project to compile (meaning to find the sources for their dependencies right from within there own structure).

The " parent " repo will reference the exact list of SHA1 representing each dependencies at their exact version needed for the project to compile/run at a specific time in the history of the parent repo.

And, as I explain in " true nature of submodules ", you can make any modification you want in A , B , C or D , and push to their respective upstream repo .
But you must not forget to go back to the parent repo, add and commit the SHA1 modifications representing the new state of the dependent repos A , B , C , and D .

This is a component approach , which has the advantage of resolving any overlapping dependency: if B and C need a different version of A , the parent repo will have to chose one (and only one) version of A .

To add to the OP Onur's answer:

Dependencies must be relative

Not necessarily: you can add symlink within a submodule, if it needs to see another with a fixed path.

Create the " user " repository

How do I automatically check out the correct set of libraries, eg A and B in the setup above

Once you have determined valid starting version for A and B, you can create and push a branch dedicated for their usage in a "parent" context.
Then you make those submodule follow that branch , meaning any git submodule update --remote will checkout the latest SHA1 of that dedicated branch for submodules A and B .

Just to make sure I understand your approach:

Things I need to do to set up the library repository:

  1. Create the "parent" repository
  2. Create a submodule for each library
  3. Dependencies must be relative, ie if D depends on B the path should look like ../../B/some folder
  4. Each commit in the parent repository represents a valid combination of libraries

Things I need to do to include a chosen set of libraries into a new project:

  1. Create the "user" repository
  2. Create a branch in the required libraries respective repositories (eg A and B) like "for_user" and track this for the submodules in the "user" project.
  3. Create a "from_user" branch in the "parent" repository that tracks changes from the used libraries ( is it possible to track repository branches on a per-branch base? ).
  4. Include the chosen set of libraries, eg A and B from the "for_user" branch.
  5. Changes made in A and/or B go to this branch and may be merged into the "parent" master branch if suitable and/or merged into other "from_..." branches from other projects using these libraries. The "parent" project is used to create consistent sets of libraries.

Effectively this means every "user" project that uses these libraries is represented by a branch "from_..." in the "parent" repository and a branch "for_..." in each used libraries repository.

The setup should now look like this

A
   branch "for_user"
   branch "master" (== for_parent)
   <other branches for each project using this library>

B,C,D
   <like A>


parent
   submodule A - tracks branch dependent on the current branch
   submodule B - tracks branch dependent on the current branch
   <other submodules>
   branch "master" (== from_parent)
   branch "from_user"
   <other branches for each project using one of the libraries>

user
   <own stuff>
   submodule A - tracks branch "for_user"
   submodule B - tracks branch "for_user"

Open questions:

  • How do I automatically check out the correct set of libraries, eg A and B in the setup above? I could check out all available libraries, but that would somehow eliminate the need for separate sub-modules for each libraries

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM