繁体   English   中英

Git没有获取被忽略的跟踪文件

[英]Git not fetching ignored tracked files

这个问题几乎与FAQ(关于如何阻止Git跟踪被忽略的文件)相反。 在这种情况下, 我想跟踪它们,而不是忽略它们。

我有一个.gitignore文件,其中包含以下行:

**/*.exe

在大多数情况下, .exe文件是构建的产物,并且将被忽略(此项目托管在MinGW和Cygwin的组合上,因此二进制文件在Windows上运行。)

但是,此忽略规则也有例外。 我已经在源代码树中添加了一些.exe文件。 据我了解, .gitignore不适用于跟踪的文件(索引中的文件)。

但是,当我克隆我的存储库时,不会提取.exe文件。

如果我在添加了原始存储库的文件对该文件执行git status则会得到:

$ git status program.exe On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working tree clean

该文件也存在于工作树中:

$ ls -l program.exe -rwxrwx---+ 1 abc xyz 23040 Mar 20 15:35 program.exe

$ git log program.exe

commit 412fd58b5a11bf6a40f661109e71f2c0026c1643 Author: abc <abc@xyz.com> Date: Sat Apr 1 02:21:40 2017 -0700

cleanup

commit b0a2efd4dc17b70d046c1e7d78e3142cf29410ba Author: abc <abc@xyz.com> Date: Mon Mar 20 18:41:00 2017 -0700

Initial version

我已将提交推送到另一台服务器上的裸存储库中。 我可以在裸仓库中找到与最新签入相对应的blob:

MyProject.git/objects/41/2fd58b5a11bf6a40f661109e71f2c0026c1643

因此很明显,它正在被跟踪。 但是,当我克隆存储库时,它不会出现在工作树中。 在克隆的存储库上

$ git status program.exe On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working tree clean

$ ls -l program.exe ls: cannot access 'program.exe': No such file or directory

我没有使用assume-unchanged的东西。

  1. 在其他存储库中提取时,是否被忽略但跟踪的文件仍然被忽略?

  2. 即使它们匹配.gitignore您如何强制它们被获取?

  3. 您是否需要从匹配的.gitignore中排除它们才能获取它们?

$ git --version git version 2.12.0.windows.1

编辑:记住,将跟踪文件添加到.gitignore之后,我不是想忽略它们; 我正在尝试获取跟踪和提交的文件,尽管它们匹配.gitignore

TL; DR:我认为这里有一个关于被跟踪的含义的关键见解

在最初的答案和下面的大量讨论之间,我意识到我认为不是很明显的事情。 当我第一次使用Git时,这当然对我来说并不明显(可能长达数月甚至数年)。 这里有两个部分:

  • 在Git中, tracked表示索引

  • 但是,每次签出某些特定的提交(例如git checkout otherbranch ,索引(您将进行的下一次提交)都会更改

这意味着是否跟踪文件是相对的,而不是绝对的。 可以在git checkout branch1之后跟踪文件F ,然后在git checkout branch2之后取消跟踪文件F。 它可能在分支master上的先前提交中已被跟踪,而现在在分支master上未被跟踪。 如果该文件是既未经跟踪忽略,但在过去跟踪和目前在工作树,它可以是相当难以弄清楚发生了什么事情。 该文件即使在历史记录中也不会出现在新的克隆中。

(原始,请在此处填写完整的答案。)


但是,当我克隆我的存储库时,不会提取.exe文件。

git clone操作不会获取任何文件。 相反,它将获取提交。 现在,提交包含文件确实是事实,所以这看起来似乎毫无意义,但它对于您的问题(实际上对几乎所有Git都至关重要)至关重要,因此确实很重要。 Git不在乎文件; Git就是关于提交的。

提交本身形成了历史。 每个提交都包含一些文件集,但是还具有指向先前提交的后向指针:“这就是我们现在拥有的。这是我们之前提交的哈希ID。” 我们称其为提交的父级 该父提交也有其自己的父。 该向后链存储库中的历史记录。

master这样的分支名称是Git记录该分支的当前哈希ID的方式。 Git在最近一次提交时从此处开始,使用分支名称; 然后,如果需要,Git会向后工作,获取较早的(父)提交,并按要求转到较旧的(祖父母,曾祖父母等)提交。

运行git clone复制分支名称,分支提交,该提交的父级以及父级的父级,依此类推; 这样您就可以获取所有历史记录。 每个提交都带有与该提交一起存储的文件,因此一旦拥有所有提交,就不仅拥有所有当前文件,而且还拥有所有先前的当前父提交文件,以及所有早先的文件。到第一次提交。 但是所有这些文件都以仅Git的秘密格式隐藏起来,除了Git以外对其他任何东西都没有好处。 仍然是git clone复制的内容。

当然,为了使Git实际有用,我们需要使用一些实际有用的形式的文件。 因此,Git在此提交历史记录中添加了一些内容,但这并不是被克隆的内容。 这就是您的问题所在。

存储库中的内容

在一个有用的(即非--bare )存储库中,我们不仅需要所有提交和各种分支名称来记住其最近的哈希ID,还需要一个工作树 工作树是我们可以处理实际文件的地方。 这些文件以树状结构排列,其中包含顶级文件和目录,并根据需要在目录中包含更多文件和子目录。 (因此,名称为“工作树”:这是工作表单文件的树。)

Git还会抛出Git称为索引的另一件事。 索引的简短描述是它是您构建下一个提交的地方。 如果您从不对自己的存储库进行任何更改,则该索引会为您带来麻烦,但是Git仍然会迫使您了解它。 如果你做的修改,该指数是至关重要的,因为进行更改的方法是修改在工作树的事情,然后使用git add到这些修改复制回索引,使他们上演 ,明年提交。 然后,当您运行git commit进行提交时,Git 现在将索引中的内容(即以前存在的所有旧内容,除了您用git add新内容替换的内容)复制到新提交中。

要知道这一点确实非常重要: 索引会跟踪工作树中的内容。 实际上,这就是“被跟踪”的含义:被跟踪 在索引中的含义 但是索引也是下一次提交中的索引,因此它开始与当前提交中的匹配。

您可以(通常这样做 )在工作树中包含故意未被跟踪的文件。 例如,您的*.exe文件被无意跟踪。 未被跟踪意味着它们不在索引中。 这意味着它们也不在当前提交中, 1 ,现在我们可以看到会有问题。


1也就是说, 除非索引为“ dirty”, 否则它们不在当前提交中,因此需要将其写出到新提交中。 再次,这是您首先进行新提交的方式:您修改工作树中的内容,例如修改文件,添加全新文件或删除现有文件,然后复制这些“脏”的工作,树文件进入索引,“使索引变脏”。 然后,您使用git commit进行新的提交。 新提交的父级是当前提交的父级,而其文件就是索引中的内容。 然后,Git将新提交的哈希ID写入分支名称,并且新提交现在是历史记录的一部分,将被永久保存。


异议:“我可以找到问题”

您提到:

我可以在裸仓库中找到与最新签入相对应的blob: MyProject.git/objects/41/2fd58b5a11bf6a40f661109e71f2c0026c1643

这意味着该文件在某些时候提交。 这是历史的承诺。 这并不意味着该文件位于像master这样的分支上的最新提交中。 该存储库具有仅Git内部(压缩对象)格式,曾经提交过的每个文件的每个版本。 并且,您可以而且经常在工作树中拥有不在索引中且不在当前提交中的文件。 该文件很可能与您过去提交的文件匹配。

因此,文件在存储库中的存在并不意味着它在某个特定分支上的最新提交中 这确实意味着您可以提取历史文件。 例如,鉴于以上所述,您可以:

git show 412fd58b5a11bf6a40f661109e71f2c0026c1643 > foo.exe

随时将其提取到foo.exe 如果您知道提交哈希和路径,则也可以使用它:

git show 1234567:path/to/foo.exe > foo.exe

以及提交是否具有名称 (例如分支或标记名称):

git show name:path/to/foo.exe > foo.exe

可以使用此方法提取历史文件,但是显然有些痛苦。

git clone在获取所有提交后会做什么

如前所述, git clone首先复制提交和分支名称。 实际上,默认情况下,它将这些分支名称重命名为Git所谓的“远程跟踪分支”。 但是,在退出它并调用一切正常且准备就绪之前的最后一步, git clone 填充了您的工作树

它在你的工作树填充的方法git checkout一些分行的名称,通常是master 该分支名称会记住该分支的最新提交的哈希ID。 该提交是从索引进行的,并且该索引中没有.exe文件。 因此,最新的master提交中没有.exe文件。

由于此工作树是全新的,并且检出的提交中没有.exe文件,因此新工作树中也没有.exe文件。 这就是为什么他们失踪的原因。

如果这些.exe文件确实存在于存储库中的其他提交中,则它们位于存储库中,您可以将其取出。 您只是没有简单地将它们弄出来:

git checkout master

因为这只会将为master上的最新提交保存的文件提取到索引中,然后提取到工作树中。

所以, 在哪里得到你.exe文件?

好吧,这部分取决于您。 Git在这里没有为您提供预包装的解决方案。 它们可能位于您要克隆的另一个Git存储库的工作树中,但是克隆协议中没有任何内容可以采用另一个Git的工作树

处理这个的一个方法是有一个承诺,它包含什么,但最新.exe文件。 然后您可以告诉Git:

    将提交中哈希值为feede3e所有文件提取到我的工作树中,而不提取到索引中

例如,假设该提交具有该哈希ID。 事实证明,这非常困难,因为Git 确实想将提交中的文件提取到索引中,然后再将它们复制到工作树中。 将它们放入索引会使它们被跟踪 ,这不是您想要的。 当然,首先要将那些.exe文件提交到提交中,那么,还有什么呢:等待它……您猜对了吗? 是的,这需要将那些.exe文件放入索引中!

Git不会让您同时拥有它。 要么跟踪文件,要么它们都在索引中,所以它们确实进入了提交; 否则它们将无法跟踪,因此它们不在索引中,因此它们不会进入提交。 选择一个并坚持下去。 如果你喜欢,使用git worktree add ,或者这个仓库,或者完全独立的存储设备的单独的克隆,创建使用不同的分支, 确实有第二个库或worktree .exe跟踪和提交的文件。 实际上,您可能希望此分支或其他存储库跟踪和保存.exe文件。 然后,您可以从那里简单地复制.exe文件。

或者,当然,您可以从确实有它们的地方获得它们,但是可以使用git clone其他方法。

(它实际上有可能做到这一切,没有一个单独的工作树,使用各种Git的管道命令和临时索引的,但它是相当棘手的,而不是Git的是如何构建的工作。在任何情况下,请注意,你会希望有一个名称(例如分支名称),您可以轻松记住,以获取具有最新 .exe文件的最新提交;具有分支名称的想法可以为您记住哈希ID,提交对象可以保存文件,还可以记得上一次提交的对象...好,这是一个分支 ,是混帐什么它使能记住承诺,能记住已保存列的索引文件的哈希分支的名称,以便你真的想要一个独立的工作树和独立。索引,用于更新和提交文件。毕竟,您真的不想在Git模型之外工作。)

.gitignore文件是一个红色鲱鱼

.gitignore中的条目所做的主要两件事:

  • 它可以抑制有关未跟踪文件的投诉 如果foo.exe存在于工作树中但不存在于索引中,因此不会保存在下一个git commit ,那么Git 会对发牢骚 它不断地告诉您:“嘿, foo.exe不会被提交!记住将foo.exe添加到索引中!不要忘记foo.exe ,否则它将不会被提交!” 这得到讨厌,和你看到的,你真的忘记文件投诉的方式获得。 因此,将foo.exe*.exe添加到.gitignore关闭此投诉。

  • 它禁止foo.exegit add -a 自动添加。 您可以通过提及目录名称或使用--all或使用git add *类的shell全局功能,整体上添加肮脏的工作树文件,而不必一次手动git add向索引中git add一个文件。 如果foo.exe当前未被跟踪并且.gitignore列出,则它们实际上不会将foo.exe复制到索引中。 甚至git add *都会跳过它,并有抱怨; git add . git add -a会跳过它而不会产生任何投诉。

请注意,如果跟踪文件, .gitignore中列出文件名无效。 .gitignore中的条目主要是关于防止文件跟踪,而不是停止已经生效的任何操作。

您的构建文件位于bin文件夹中。 因此您必须将.gitignore添加到:

bin/*.exe or bin/* 

并且您应该从gitignore文件中删除此行:

**/*.exe

编辑:如果要忽略除某些文件以外的所有exe文件,可以使用“!”将其排除。 在行模式的开头,请查看此https://stackoverflow.com/a/987162/5410373

暂无
暂无

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

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