简体   繁体   English

我可以创建一个带有本地存储库的远程 git 存储库吗?

[英]Can I create a remote git repository with a local repository inside?

I am required for a university course to handle a git folder of a local repo for every assignment I do, but I would like to have the folder containing all the projects as a remote repository.大学课程要求我为我所做的每项作业处理本地存储库的 git 文件夹,但我希望将包含所有项目的文件夹作为远程存储库。 Is that possible?那可能吗? Because I tried and gitlab says the data inside the folder with the local repo is inaccesible.因为我试过 gitlab 说本地存储库文件夹中的数据不可访问。 I am thinking of using a.gitignore file, but I don't know if that would do the job or only waste more time.我正在考虑使用 .gitignore 文件,但我不知道这是否可以完成工作或只会浪费更多时间。

You can get close, but not quite there.你可以靠近,但不完全在那里。 Specifically, a repository cannot contain a repository.具体来说,存储库不能包含存储库。 (A work-tree can, but a repository cannot.) 工作树可以,但存储库不能。)

In normal use, a Git repository is stored within a subdirectory named .git .在正常使用中,Git 存储库存储在名为.git的子目录中。 Let's define these terms:让我们定义这些术语:

  • Work-tree: the place in the file system where you do your work.工作树:文件系统中你做工作的地方。
  • Top level: the path to this work-tree, without any additional subdirectories.顶级:此工作树的路径,没有任何其他子目录。
  • Path component: see below.路径组件:见下文。
  • Nested repository: a repository and work-tree that is contained underneath another repository's work-tree.嵌套存储库:存储库和工作树包含在另一个存储库的工作树之下。

For instance if /home/users/fred/projects/proj1 is the top level, it will contain a directory named .git .例如,如果/home/users/fred/projects/proj1是顶层,它将包含一个名为.git的目录。 This is where the repository itself is.这是存储库本身所在的位置。 The rest of the stuff in /home/users/fred/projects/proj1 is the work-tree for this repository. /home/users/fred/projects/proj1中的 rest 是这个存储库的工作树 If there is a /home/users/fred/projects/proj1/subproj/.git , this .git is a nested repository within the work-tree for the proj1 repository.如果有/home/users/fred/projects/proj1/subproj/.git ,则此.gitproj1存储库工作树中的嵌套存储库。

Commits inside the repository contain files.存储库中的提交包含文件。 The files inside the commits have path names.提交中的文件具有路径名。 These path names never start with slash, but may contain slashes (always forward slashes, even on Windows), so a file might be named, eg, path/to/file.ext .这些路径名从不以斜杠开头,但可能包含斜杠(始终是正斜杠,即使在 Windows 上也是如此),因此可以命名文件,例如path/to/file.ext When Git extracts this file into the work-tree, it makes the path/ and path/to sub-directories on demand so that path/to/file.ext can exist in the way the OS itself requires (as a file named file.ext in a dir/folder named to that is in a dir/folder named path ).当 Git 将此文件提取到工作树中时,它会根据需要创建path/path/to子目录,以便path/to/file.ext可以按照操作系统本身要求的方式存在(作为名为 file.txt 的file.ext在名为path to目录/文件夹中。 The various parts separated by slashes are path components .由斜杠分隔的各个部分是路径组件

What Git won't do is store a file or directory with a component named .git . Git不会用名为.git的组件存储文件或目录。 1 No commit should ever contain a file that has this as any of its path component. 1任何提交都不应包含将此作为其任何路径组件的文件。 2 2个

What this means is that cloning a repository, then extracting some commit, never creates any sub-directory within the work-tree that is named .git .这意味着克隆存储库,然后提取一些提交,永远不会在名为.git的工作树中创建任何子目录。 To contain an actual repository, you'd have to have a Git extract a subdirectory (not at the top level) named .git , which would then contain all the files that go in the .git of a fresh clone—and, except for security holes that are now fixed, Git just won't allow this.要包含一个实际的存储库,你必须有一个 Git 提取一个名为.git的子目录(不在顶层),然后它将包含 go 在新克隆的.git中的所有文件 - 并且,除了现在已修复的安全漏洞,Git 不允许这样做。

You can , however, create new Git repositories within the work-tree of an existing Git repository.但是,您可以在现有 Git 存储库的工作树中创建新的 Git 存储库。 What you can't do is add and commit those, because adding one of those requires adding its .git directory, and a component name that includes .git is forbidden.您不能做的是添加和提交它们,因为添加其中一个需要添加其.git目录,并且禁止包含.git的组件名称。 Git will (in modern times anyway) cleverly detect that there is a .git , so this must be some kind of sub-project, and will automatically attempt to submodule-ize things, to some extent. Git 会(无论如何在现代)巧妙地检测到有一个.git ,所以这一定是某种子项目,并且会在某种程度上自动尝试对事物进行子模块化。 (See below.) (见下文。)


1 In a security hole type bug, very-old versions of Git did not check for uppercase variants, which caused problems on case-insensitive file systems such as the default ones on Windows and MacOS. 1在一个安全漏洞类型的错误中,Git 的非常旧版本没有检查大写变体,这导致不区分大小写的文件系统出现问题,例如 Windows 和 MacOS 上的默认文件系统。 That is, you could store a .Git or .GIT or .gIt or some such.也就是说,您可以存储.Git.GIT.gIt等。 All modern Git versions forbid these as well.所有现代 Git 版本也禁止这些。

2 Since existing commits cannot be changed, all modern Gits check for this in existing commits, and refuse to extract such files, too. 2由于无法更改现有提交,因此所有现代 Git 都会在现有提交中检查这一点,并拒绝提取此类文件。


What you can do能做什么

There are two things you could do here, other than using a third-party add-on like Google's repo .您可以在这里做两件事,而不是使用像 Google 的repo这样的第三方插件。 3 One is more sensible than the other, and also more automatic. 3一个比另一个更明智,也更自动。

You could:可以:

  • make your nested repositories manually, ie, create a repository with a work-tree and in that work-tree make a sub-repository手动创建嵌套存储库,即创建一个带有工作树的存储库,并在该工作树中创建一个子存储库
  • then just before git add -ing and git commit -ing in the top level work-tree, that contains nested repositories, rename the .git directory in the sub-repository:然后就在git addgit commit之前,在包含嵌套存储库的顶级工作树中,重命名子存储库中的.git目录:

     (cd sub; mv.git XGIT); git add.; git commit -m 'add nested fake repo'
  • then when you extract this commit, manually go in and rename XGIT to .git然后当您提取此提交时,手动 go 并将XGIT重命名为.git

and now you have a standard nested repository within a repository.现在您在存储库中有一个标准的嵌套存储库。

This is not the right way to do it and is just for illustration.这不是正确的方法,只是为了说明。

Or, you can:或者,您可以:

  • use submodules使用子模块

This is the right way to do it but it means that you have to have more than one GitHub or GitLab repository: you need one per project, in fact, plus one more "superproject" repository that simply exists to name all the sub-projects.这是正确的方法,但这意味着您必须拥有多个 GitHub 或 GitLab 存储库:事实上,每个项目都需要一个,再加上一个仅用于命名所有子项目的“超级项目”存储库.

A submodule is simply a way to have one Git repository refer to another Git repository.子模块只是一种让一个 Git 存储库引用另一个 Git 存储库的方法。 The superproject—the containing repository—has a file named .gitmodules that lists the subproject info for git clone , and contains a series of commits.超级项目(包含存储库)有一个名为.gitmodules的文件,其中列出了git clone的子项目信息,并包含一系列提交。 Each commit in the superproject lists:超级项目列表的每个提交:

  • the path name of the submodule Git, and子模块 Git 的路径名,以及
  • the commit hash ID that the superproject will git checkout in the submodule.超级项目将git checkout的提交 hash ID。

The superproject therefore directs a Git to clone and git checkout any number of additional Git repositories, all automatically.因此,超级项目指示 Git 克隆和git checkout任意数量的额外 Git 存储库,所有这些都是自动的。 There are a number of drawbacks to submodules, but they do work right out of the box.子模块有很多缺点,但它们开箱即用。

To use a submodule, after creating a sub-project .git within a superproject work-tree, use git submodule add in the superproject.要使用子模块,在超级项目工作树中创建子项目.git后,在超级项目中使用git submodule add This sets up the .gitmodules file correctly for you.这会为您正确设置.gitmodules文件。 If you let Git auto-detect the existence of the nested repository, Git creates the right part in the commit but the data needed to clone the submodule is missing.如果您让 Git 自动检测嵌套存储库的存在,Git 会在提交中创建正确的部分,但缺少克隆子模块所需的数据。


3 Google's repo exists mainly because submodules were much more dysfunctional back in the 2005-2012 or so era. 3 Google 的repo之所以存在,主要是因为子模块在 2005-2012 年左右的时代功能失调得多。 Submodules work a lot better today.子模块今天工作得更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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