有没有一种方法可以将多个项目放在一个Git仓库中?

255

由于某些原因,我只有一个仓库可用。
但我有包括Java项目、PHP脚本Android应用程序项目在内的多个项目

现在我的问题是,我必须将它们放到存储库的不同子文件夹中。
我使用不同的IDE,你知道,每个IDE都可以有自己的工作区。

是否有一种简单的方法(比如通过设计而非看法),来解决这个问题?


1
可能的解决方案可以是 https://dev59.com/02035IYBdhLWcg3wSN4G?rq=1 或者 https://dev59.com/klzUa4cB1Zd3GeqP5q8-#7931825。 - Ragnarokkr
3
你并不孤单。我有一个类似的情况,我的代码仓库是用于学习目的(例如:https://github.com/hopbit/java-sandbox)。我不想为每本新书或教程尝试示例而创建新的代码仓库... - Łukasz Siwiński
1
你想这样做的一个原因是,如果你有一个项目是产品代码,你会将其部署到测试或生产等运行时环境中。第二个项目是一个应用程序,它对第一个项目进行系统测试(例如BDD)。这两个项目之间存在密切的关系,现在你可以使用一个存储库URL来维护/引用整个项目。 - Lance Kind
Git 不知道这些是同一个项目还是不同的项目。 - Ahmed Nabil
3个回答

245

虽然大多数人会建议您只使用多个仓库,但我认为值得一提的是还有其他解决方案。

解决方案1

一个单独的仓库可以包含多个 独立的 分支,称为 孤立分支。孤立分支彼此完全独立,它们不共享历史记录。

git checkout --orphan BRANCHNAME

这将创建一个新的分支,与当前分支无关。每个项目应该在自己的孤立分支中。

现在由于某些原因,在孤立检出之后,git 需要进行一些清理工作。

rm .git/index
rm -r *

删除之前确保所有内容都已提交

一旦孤立分支干净,就可以像平常一样使用它。

解决方案2

避免孤立分支的所有麻烦。创建两个独立的存储库,并将它们推送到相同的远程存储库。只需为每个存储库使用不同的分支名称即可。

# repo 1
git push origin master:master-1

# repo 2
git push origin master:master-2

3
非常感谢,这应该能够解决我的问题。实际上,这两个解决方案都使用分支来保存不同的项目。 - Stony
8
我不确定我理解解决方案2的意思。您是否意味着将所有.git文件提交到主git存储库中?使用多个孤立分支与使用多个分支有什么区别? - Nate
24
他的意思是:创建两个独立的本地代码仓库,然后将它们都推送到GitHub上同一个远程仓库中。请注意,这里的“local”指的是本地代码仓库,“remote”指的是GitHub上的远程仓库。 - The Guy with The Hat
2
感谢 @TheGuywithTheElfHat。现在看来(9个月之后),这对我来说已经很清楚了。虽然解决方法2仍然会创建孤立的分支,但我可以看出这种方法更容易处理。 - Nate
34
解决方案2需要更多的解释。 - eC Droid
显示剩余8条评论

26

解决方案3

这是为了在单个目录中使用多个项目而设计的技巧。我在某些密切相关的项目中使用此技术,常常需要从一个项目中拉取更改并应用到另一个项目中。这与孤立分支的想法类似,但这些分支不需要被孤立。只需从同一个空目录状态开始所有项目。

从一个已提交的空目录开始所有项目

不要对此解决方案抱有太高期望。我认为,你总会遇到一些未跟踪文件带来的烦恼。Git 对它们真的不知道该怎么办,所以如果编译器生成了一些中间文件,并被你的 .gitignore 文件忽略掉,那么当你尝试快速地在软件项目和博士论文项目之间进行切换时,它们很可能会被遗忘。

然而,这里是计划。按照您应该开始任何 Git 项目的方式开始,通过提交空仓库,然后从相同的空目录状态开始所有项目。这样,您可以确信两组文件基本上是相互独立的。此外,请给您的分支命名,并不要懒惰地只使用“主分支”。您的项目需要是相互独立的,因此请给它们适当的名称。

Git 提交(因此也包括标签和分支)基本上存储了目录及其子目录的状态,并且Git 不知道这些是否是同一项目的一部分还是不同项目,因此将不同项目存储在同一个仓库中实际上没有问题。问题在于使用另一个项目时你需要清理掉其中一个项目的未跟踪文件,或者以后分离这些项目。

创建一个空的仓库

cd some_empty_directory
git init
touch .gitignore
git add .gitignore
git commit -m empty
git tag EMPTY

从零开始开始你的项目。

只专注于一个项目。

git branch software EMPTY
git checkout software
echo "array board[8,8] of piece" > chess.prog

git add chess.prog 
git commit -m "chess program"

开始另一个项目

随时喜欢。

git branch thesis EMPTY
git checkout thesis
echo "the meaning of meaning" > philosophy_doctorate.txt
git add philosophy_doctorate.txt 
git commit -m "Ph.D"

来回切换

您可以随时在项目之间自由切换。此示例返回到国际象棋软件项目。

git checkout software
echo "while not end_of_game do make_move()" >> chess.prog
git add chess.prog 
git commit -m "improved chess program"

未跟踪的文件很烦人

然而,当在不同项目/分支之间切换时,未跟踪的文件会让你感到烦恼。

touch untracked_software_file.prog
git checkout thesis 
ls
    philosophy_doctorate.txt  untracked_software_file.prog

这不是无法克服的问题

从定义上来看,Git并不知道如何处理未跟踪的文件,因此需要你自己来处理它们。你可以按照以下方法阻止未跟踪的文件从一个分支传递到另一个分支。

git checkout EMPTY 
ls
    untracked_software_file.prog
rm -r *
    (directory is now really empty, apart from the repository stuff!)
git checkout thesis
ls
    philosophy_doctorate.txt

确保在检出新项目之前该目录是空的,我们就能够确保没有任何悬而未决的未跟踪文件来自其他项目。

一种改进

$ GIT_AUTHOR_DATE='2001-01-01:T01:01:01' GIT_COMMITTER_DATE='2001-01-01T01:01:01' git commit -m empty

如果在提交一个空仓库时总是指定相同的日期,则独立创建的空仓库提交可以具有相同的SHA1代码。 这使得两个仓库可以独立创建,然后稍后合并到一个具有共同根的单一树中。

示例

# Create thesis repository. 
# Merge existing chess repository branch into it

mkdir single_repo_for_thesis_and_chess
cd single_repo_for_thesis_and_chess
git init
touch .gitignore
git add .gitignore
GIT_AUTHOR_DATE='2001-01-01:T01:01:01' GIT_COMMITTER_DATE='2001-01-01:T01:01:01' git commit -m empty
git tag EMPTY
echo "the meaning of meaning" > thesis.txt
git add thesis.txt
git commit -m "Wrote my PH.D"
git branch -m master thesis

# It's as simple as this ...
git remote add chess ../chessrepository/.git
git fetch chess chess:chess

结果

合并存储库的图表

每个项目使用子目录?

如果可能的话,将您的项目保存在子目录中也可能会有所帮助,例如,不要将文件放在一个大的共享目录中。

chess.prog
philosophy_doctorate.txt 
chess/chess.prog
thesis/philosophy_doctorate.txt 
在这种情况下,您的未跟踪软件文件将是chess/untracked_software_file.prog。在thesis目录中工作时,您不应受到未跟踪的国际象棋程序文件的干扰,并且您可能会发现在不删除其他项目中的未跟踪文件的情况下可以愉快地工作。
此外,如果您想从其他项目中删除未跟踪的文件,将不需要的目录转储比通过选择每个文件来删除不需要的文件更快(并且更少出错)。

分支名称可以包括'/'字符

因此,您可能希望像这样命名您的分支:
project1/master
project1/featureABC
project2/master
project2/featureXYZ

我认为这里的关键是使用“/”字符在文件夹中为分支命名。然后要有不同的分支,你可以做两件事:1)使用git commit --allow-empty创建一个实际上为空的共同根提交——方案3的改进——。2)使用git checkout --orphan $project/$branch创建多个根提交。 - DuniC
我有两个文件夹,分别用于两个不同的项目,但是它们仍然混合在一起未被跟踪。我在根目录下有一个.git文件夹,在它的下面有BE和FE文件夹,每个文件夹都包含自己的.gitignore文件,我应该怎么做才能忽略相反的文件呢?非常感谢。 - Adir D

18

7
我只有一个可用的仓库。您能否解释一下如何将多个子模块存储在同一个仓库中? - Ivan
6
git submodule add [url to git repo] 的意思是向当前的Git仓库中添加一个子模块,并将其连接到指定的git仓库的URL。更多详细信息可以参考 https://git-scm.com/book/en/v2/Git-Tools-Submodules 。 - prasanthv
6
能否解释一下为什么要使用“单体代码库”(Monorepos)呢? - sophievda
5
仅仅提及“Monorepos”而没有解释为什么建议使用它,我认为这不太适合作为一个回答。 - Mohammed Noureldin
Git子模块很好,如果你有单独的存储库。 - DuniC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接