简体   繁体   中英

Decoupling a Visual Studio solution into multiple (interdependent) git repositories

I am working on a game and its engine and have been working on both of them simultaneously and thus have one solution file that references all projects from the following (simplified) directory structure:

Root
├───Engine
│   ├───Library1
│   ├───Library2
│   └───Library3
├───Game
│   ├───Game
│   ├───Tool1
│   └───Tool2
└───GlobalSolution.sln

The build process compiles all engine libraries and links them into one static library while the game is an executable that is being linked against the resulting static library, similiar to some of the tools.

Unfortunately I have everything in the same git repository whereas I want to have one repository for the engine and one for the current game since the engine itself isn't really useful (although it can be compiled on its own) but I might want to create another game which I should be able to host in its own repository.

The only structure I could come up with is the following:

Root
├───Engine
│   ├───Library1
│   ├───Library2
│   ├───Library3
│   └───EngineSpecificSolution.sln
├───GameA
│   ├───GameASpecifics
│   ├───ToolA1
│   ├───ToolA2
│   └───GameASpecificSolution.sln
└───GameB
    ├───GameBSpecifics
    ├───ToolB1
    └───GameBSpecificSolution.sln

In that case I would just need to reference the engine libraries by adding $(SolutionDir)\\..\\Engine\\Build\\ to the library path of the game solutions. Unfortunately though, I am losing the convenience of having everything (engine and game) in one VS window and would need to code in separate windows, wouldn't I? And of course, every time I make a change to the engine I would have to manually compile the game solution instead of letting VS handle all projects in one go.

Are there any suggestions on how to properly decouple the projects into multiple repositories and keeping the work with those as convenient as possible?

This is what git submodules were created for.

Many feel it's not easy to learn how git submodules work so there will likely be some pain at the beginning but one you master it, it's a very useful tool.

I will show one way to do it and won't go into the specifics of git-submodule but don't hesitate to search for git-submodule question, ask new questions and to ping me in the comments if you need clarification on certain points.

First, you create a solution with your Engine projects in a specific git repository (the .git directory is just there to show you what is a git repo and what is not):

Root
├───Engine
    ├───.git/
    ├───Library1
    ├───Library2
    ├───Library3
    └───EngineSpecificSolution.sln

With git:

$ mkdir Engine && cd Engine
$ git init
** Create the Engine solution **
$ git commit -a -m "First commit for Engine"
$ git remote add origin https://github.com/user/engine.git
$ git push -u origin master

Then you create you game directories with the Engine repository added as a submodule:

Root
├───Engine
│   ├───.git/
│   [...]
├───GameA
│   ├───.git/
│   ├───Engine
│   │   ├───.git/
│   │   ├───Library1
│   │   ├───Library2
│   │   ├───Library3
│   │   └───EngineSpecificSolution.sln
│   ├───GameASpecifics
│   ├───ToolA1
│   ├───ToolA2
│   └───GameASpecificSolution.sln
└───GameB
    ├───.git/
    ├───Engine
    │   ├───.git/
    │   ├───Library1
    │   ├───Library2
    │   ├───Library3
    │   └───EngineSpecificSolution.sln
    ├───GameBSpecifics
    ├───ToolB1
    └───GameBSpecificSolution.sln

Create the solution for GameA with git:

$ mkdir GameA && cd GameA 
$ git init

# The following command creates a link to the Engine submodule
$ git submodule add https://github.com/user/engine.git Engine

# The following command will clone the submodule's repository in place of Engine directory
$ git submodule update

** Create the GameA solution and add Engine projects to solution **
$ git commit -a -m "First commit for GameA"
$ git remote add origin https://github.com/user/gamea.git
$ git push -u origin master

You now have GameA that contains everything but the Engine code, and that references the Engine repository at a specific commit. When you make changes to GameA only, you only need to create a commit in GameA. When you make changes in both GameA and Engine, you will need to create a commit in Engine first, and then in GameA. The commit in GameA will include a change to the reference to Engine because the referenced commit will have changed.

When you make changes to Engine, you will be able to do in either in Root/Engine or in Root/GameA/Engine or in Root/GameB/Engine and synchronize your changes using git push and git push .

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