跟踪多个存储库中的相同文件

时间:2016-11-12 20:44:27

标签: git version-control

假设我有repo1被跟踪(它包含.git)。

然后,在其中,我从github下载project1。这有它自己的.git文件夹(我可能会忽略它?)。

继续,我会将project1添加到repo1

此时,我会说多个存储库正在跟踪project1中的文件。

我在这里做了一些没有任何问题的测试,显然这种情况可以继续下去。我可以在两个存储库中提交。显然一切都还井井有条。

我忘了什么吗?这有点危险吗?

1 个答案:

答案 0 :(得分:2)

Git 不是问题。它可能会让你混淆你自己,和/或让你做你不想做的事情。

关键是要跟踪三件事:存储库本身工作树(通常每个存储库一个),以及索引(对于该存储库或工作树)。 1

Git将忽略任何 .git子目录中的所有文件。 2 您有一些顶级{{1}包含另一个目录repo1(即它自己的存储库)的目录(和存储库),因此我们可以确定project1存在,repo1/project1/.git/HEAD也可能存在;但Git 会自动忽略它们。但是,如您所见,Git 不会自动忽略其他文件。也就是说,从repo1/project1/.git/refs/heads/master开始,repo1中的文件(例如project1)被视为有效路径名repo1/project1/README,可以跟踪(在索引中) repo1)或未跟踪(不在该索引中)。

如果这些文件显示为未跟踪,并且您尝试使用project1/README来查看它们,则只会看到整个目录(即git status),除非您要求project1/(或-uall)。通常大多数人会使用--untracked-files=all隐藏整个目录,以便其文件既不会显示为未跟踪,也不会意外添加。

同时,每当你坐在这个嵌套层次结构的某个层次上进行操作时,Git“在那个级别”就会捕获它。例如,如果您将当前工作目录更改为.gitignore并运行repo1,则会检查git status的状态,但是如果您将其更改为repo1并运行project1,您将检查git status的状态。

如果project1有一个自己的子目录(project1repo1/project1/sub/目录,那么在该子目录中完成的操作是“在“.git

换句话说,除非你给它额外的指示,否则Git从你现在的位置开始并检查project1。如果这里没有,它会爬上一个目录并再次尝试。它会重复,直到它用完可能的地方(有一些特殊的案例代码可以避免爬出文件系统,因此“可能的地方”可能不会继续到.git;这是依赖于操作系统的)。一旦它找到/的“顶级”,它就会停止攀爬。要查看它停止的位置,请运行:

.git

无论它停在哪里,那就是工作树的位置。 3 这通常(但并不总是)存储库本身也是如此:

$ git rev-parse --show-toplevel

(可能显示相对或绝对路径)。

通过这种嵌套,您需要(痛苦地:-))了解您正在使用的存储库,因为每个存储库 - 或者更确切地说,是一些工作树存储库相关联,以及必要时的存储库和索引 - 将被各种Git命令触及。但这种“触动”不会以任何方式通知任何内部Git存储库。例如,如果运行$ git rev-parse --git-dir ,Git将通过切换分支来修改当前工作树中的文件,然后修改当前存储库中的HEAD提交。如果此工作树重叠某些其他存储库的工作树,并且您将自己移动到另一个存储库,则突然所有这些(已更改的)文件不再与您当前的文件匹配存储库的HEAD提交。

当工作树像这样重叠时,人们会犯错误。 Git 不会关心;它只是处理存储库,工作树和索引。

1 在旧版本的Git中,存储库只有一个工作树。如果使用新的git checkout otherbranch,则可以拥有多个工作树,每个工作树都有自己的索引。在具有 no 工作树(脚注3)的特殊情况下,仍然有一个索引。

2 在折叠案例的系统上曾经存在一些与安全相关的问题,因为您可能拥有包含名为git worktree add.GiT/hooks/pre-commit的文件的存储库,会覆盖你的顶级或子级存储库的钩子。 Modern Git会自动忽略somedir/.gIT/hooks/pre-commit.Git.giT等。

3 假设有一个工作树,那就是。如果存储库是“裸”(.GIt已设置,但未被覆盖),那么没有工作树,所有这些问题基本上都消失了。