我有以下继承权:
BigProductName/
code/
.gitignore suitable for Linux C++ development
Project1/
Makefile; all .cpp, .h, etc. for this project
Project2/
Makefile; all .cpp, .h, etc. for this project
Project3/
Makefile; all .cpp, .h, etc. for this project
vs2022/
.gitignore suitable for Visual Studio
FirmName.sln
various Visual Studio files
distribution/
Distribution1.0/
Distribution1.0.zip
所有git控制的文件都在代码下。分发文件是我的输出,不受控制。*
问题:我是在FirmName
下运行git init
,然后运行add code
,还是在code
内运行git init
?如果是,我是在运行git add *
还是git add .
?
*与问题无关但可能有助于回答的额外细节:在代码目录中运行make会自动生成distribution
继承:复制文档、标头、示例代码以及make生成的二进制文件和库。在BigProduct.sln
的vs2022
下进行构建同样会填充正在分发的Windows子目录。周期性地,通过简单地将distribution
重命名为Distribution1.0
并将其压缩来创建发布。这就是为什么我们有一个由Git控制的代码目录,与其他目录和文件并排:它们是构建的输出。它们不受源代码控制,因为它们不是源代码。然而,它们在逻辑上与生成它们的代码树分组,因此与之紧密分组
;正确的";源文件和存储库的组织在很大程度上是一个意见问题,因此不能对StackOverflow负责。
运行git init
的地方(文件夹或目录,无论您喜欢什么术语)是Git将创建隐藏的.git
文件夹的地方,该文件夹将存储存储库。这将成为工作树的顶层。因此,给定上面的图像,如果你在FirmName
目录(文件夹)中并在那里运行git init
,你会得到:
FirmName/
.git/
code/
.gitignore suitable for Linux C++ development
Project1/
Makefile; all .cpp, .h, etc. for this project
Project2/
Makefile; all .cpp, .h, etc. for this project
Project3/
Makefile; all .cpp, .h, etc. for this project
vs2022/
.gitignore suitable for Visual Studio
FirmName.sln
various Visual Studio files
distribution
Distribution1.0
Distribution1.1
(我不知道distribution
是一个文件还是目录;我在这里去掉了将其标记为目录的尾部斜杠。)请注意,Git根本不存储任何目录(文件夹):它只存储文件,所以这个.git
将存储名为code/Project1/.gitignore
和code/Project2/.gitignore
的文件。
使用这种结构,签出特定的提交将填充整个工作树——code/
中的所有内容和所有distribution*
文件,除非这些文件也通过与code/
目录相同级别的.gitignore
被忽略,或者以其他方式未被跟踪1
另一方面,如果您更改到code
目录并在那里运行git init
,则会得到:
FirmName/
code/
.git/
.gitignore suitable for Linux C++ development
Project1/
Makefile; all .cpp, .h, etc. for this project
Project2/
Makefile; all .cpp, .h, etc. for this project
Project3/
Makefile; all .cpp, .h, etc. for this project
vs2022/
.gitignore suitable for Visual Studio
FirmName.sln
various Visual Studio files
distribution
Distribution1.0
Distribution1.1
请注意,工作树的顶层现在是code/
目录本身,Git存储库将包含文件.gitignore
和各种Project1/*
文件。它将不包含名为code/Project1/*
的文件,而是名为Project1/*
的文件:相同的内容,但使用不同的名称。
这意味着您可以在distribution/
下创建一个单独的.git
目录(如果是子目录的话)。您也可以在FirmName/
下创建一个.git
,但由于Git存储库不能容纳另一个Git存储池,2任何将code/.git
存储到更高级别Git存储区的尝试最终都会存储gitlink:这是子模块的一半,没有另一半就没用了,所以您必须调查子模块,或者很多人称之为子模块,sob-模块(它们让用户哭泣)。
关于git add .
与git add *
:
git add .
告诉Git:读取当前目录(根据需要递归)并添加您找到的所有文件,模块跳过也被忽略的未跟踪文件。git add *
告诉Git:读取命名的文件和/或目录,并添加这些。未跟踪的文件现在会引起投诉,并且默认情况下不会添加。不过这里有一个复杂的问题。如果您使用的是类似Unix的shell(bash、zsh或许多类似shell中的任何一个),shell会将
*
扩展为各种名称,而shell通常会跳过";点文件";例如CCD_ 42。这通常不是你想要的。如果您在Windows上使用旧的
CMD.EXE
,则不会扩展*
,因此Git会看到文本*
并进行自己的扩展。默认情况下,此包含点文件。
有关此方面的更多信息,请参阅之间的差异。(点)和*(星号)通配符。(PowerShell做什么,我不知道。)
所有这些的结果是,git add .
或git add --all
可能在大多数时候都是你想要的,因为它在任何地方都有效。
1文件的跟踪/未跟踪状态不是由文件是否列在.gitignore
中决定的,而是由文件是否在Git的索引中决定的。然而,在.gitignore
中列出一个文件往往会阻止文件进入Git的索引,因此往往会导致保持未跟踪,如果它已经未跟踪的话。这里的问题是,无论被跟踪的文件是否列在.gitignore
中,都会对其进行跟踪,因此如果被跟踪,它往往会保持跟踪状态。
2这是一个管理限制,不是内部Git数据结构固有的东西,但它仍然是真的。