Reputation: 28463
I have a common library that I want to share between a few solutions, that stored in different github repositories. We put the shared library in separate GitHub repository and created nuget package, that can be installed in each required projects/solution. The disadvantage is that changing code in a library involves a few steps ( change code, push to library repository, creating nuget package, installing package) which is annoying.
I wanted to use git subtree
to create sub directory with library project and use it as local project in my solution with easy code changing/testing/debugging.
Developers of "Main" solutions will have a choice- include library as a binary nuget package or as a source project in subdirectory.
PROBLEM: When I tried git subtree
, I found one issue: csproj files have relative references to packages folder, that are located on different levels, when included in standalone library solution and when included in a main solution.
When in MyLib.sln the path is "..\Packages" , but in Main.sln the path should be "..\..\Packages" .
The structure of Main GitHub Repository ( and OtherUserOfMyLib GitHub Repository(is)) :
Main.sln
LibSubfolder
-----------------| MyLib.sln
-----------------| MyLibSource
--------------------------| myLib.csproj
--------------------------| myLib code
-----------------| (expected Packages from lib solution)
Packages. (From main solution)
The structure of MyLib GitHub Repository:
MyLib.sln
MyLibSource
--------------| myLib.csproj
--------------| myLib code
Packages. (From lib solution)
I tried git subtree
to copy only MyLibSource subdirectory from Lib repository (That will allow to have relative position of packages folder the same). Unfortunately I didn't find a way to to copy subdirectory from another repo, that support later PUSH the changes back to original repo. The answer
Add subdirectory of remote repo with git-subtree has a few options, but all of them seems only discussed one-way (pull) syncronization.
From what I looked, git submodule and git subrepo do not support copying subfolder from source repository.
Am I missing something? Can anyone suggest, how to copy to subfolder of my repository folder from library repository, that will allow later two-way (pull/push) syncronization?
Other option I considered is to change the location of packages folder. But I am not sure, which path to choose to be consistent for both main.sln and MyLib.sln.
The third approach is do not use MyLib.sln in MyLib repository ; use the repository only as a master storage for library source code. Instead create MyLib.sln in the Main repository and use it to build NuGet package. I will be able to use git subtree pull/push content of MyLibSource project. OtherUserOfMyLib repositories will just refer to the project in subfolder and also call git subtree pull/push when required
Main.sln
MyLib.sln ( locate in Main repository instead of MyLib repository)
LibSubfolder
-----------------| MyLibSource
--------------------------| myLib.csproj
--------------------------| myLib code
Packages
My question is which approach to try:
I've looked at similar questions like Best practice to share common libraries between solutions in .NET and How do you share code between projects/solutions in Visual Studio? but didn't find satisfactory solutions.
Upvotes: 4
Views: 3187
Reputation: 28463
I was able to use git subtree to share the common repository (e.g. source code library) as subfolder of different client solutions(repositories) and allow to push the changes back to the shared repository.
We are using similar approach for c# libraries, folder of Powershell psm modules, consider to use for collection of React jsx components. For c# library one of the client repositories builds NuGet package, that can be used by any solution which prefer to refer NuGet package instead of source code.
The same approach we are using if we need to include source code of some open source github library ( e.g. if we want the changes before a new release is available).
In each application repository we need to customise two batch files (for each common repository): subtreePull and subtreePush.
Examples of batch files (based on option 4 of Add subdirectory of remote repo with git-subtree answer) :
MyCommonLib-SubtreePull.cmd
@rem Template Pull and Push are located in SubTreeCommands folder
@Rem from https://developer.atlassian.com/blog/2015/05/the-power-of-git-subtree
@set remoteBranch=master
@set RelativeTarget=src/MyApplicationProject/LibSource/MyCommonLib
@echo If you have errors "Working tree has modifications. Cannot add." uncomment stash before command and stash apply after command
@REM git stash
@rem run this command from the toplevel of the working tree
@for /f %%i in ('git rev-parse --show-toplevel ') do set GitRoot=%%i
CD %GitRoot%
IF EXIST %RelativeTarget% (
set gitCmd=pull
) ELSE (
set gitCmd=add
)
@rem if you want to have full history, do not include --squash
git subtree %gitCmd% --prefix %RelativeTarget% https://github.com/MyCompany/MyCommonLib.git %remoteBranch% --squash
@REM git stash apply
@pause
MyCommonLib-SubtreePush.cmd
@Rem from https://medium.com/@v/git-subtrees-a-tutorial-6ff568381844#.a2ne9vlve
set remoteBranch=master
@rem run this command from the toplevel of the working tree
@for /f %%i in ('git rev-parse --show-toplevel ') do set GitRoot=%%i
CD %GitRoot%
git subtree push --prefix=src/MyApplicationProject/LibSource/MyCommonLib https://github.com/MyCompany/MyCommonLib.git %remoteBranch%
@pause
During the work you are doing normal git commit/git push for the changes in your Application repository, including changes within LibSource common library subfolder.
To synchronise your common library changes run subtreePush/subtreePull commands.
Note that subtreePush is recommended to run after major change in the library (e.g. at the end of each relevant project).
subtreePull may be done by different persons in different repositories , it is recommended to run before major work with the repository(e.g. at the start of a project).
Both subtree pull and push batches take some time to run, but you can start them and do anything else.
Upvotes: 3