推送时如何忽略对特定文件的所有更改

时间:2018-11-28 20:45:58

标签: git

我从存储库中将项目克隆到PC上,并出现错误,因为一些文件的文件名中带有星号,而这些文件在Windows系统上显然不存在。现在,我的git status表明我正在删除这些文件,因为它们没有复制到我的项目中。我不需要对这些文件(它们都是图像)进行任何更改,所以有没有办法告诉git不要对这些特定文件进行任何更改(在这种情况下为删除)?

我尝试对其中之一进行git update-index --assume-unchanged的操作,但似乎没有用,因为我的git status仍将文件显示为排队等待删除(相关图片)。

enter image description here

3 个答案:

答案 0 :(得分:2)

简单地:git update-index --skip-worktree [<file>...]

使用skip-worktree,即使git知道文件已被修改(或需要通过reset --hard等修改),它仍会假装未使用该文件中的版本索引代替。这一直持续到索引被丢弃为止。 explanation.

See How do Iconfigure git to ignore some files locally : git update-index --skip-worktree

答案 1 :(得分:1)

TL; DR

为索引中的那些特定路径设置--skip-worktree位:

git ls-files -dz | xargs -0 git update-index --skip-worktree

(我假设您的Windows-bash具有xargs -0;如果没有,您可能需要对此进行一些摆弄。)

长(ish)

您的git update-index命令未产生任何错误,因此它不会影响这些文件,这意味着您在错误的位置查找。

这里的一个基本问题是git push不会推送文件。而是推送 commits 。确实提交了 contain 文件,因此您可能会争辩说这是无用的区别,但这是Git做出的关键区别,它是问题和解决方案的核心。 >

  

...一些文件名中带有星号的文件在Windows系统上显然不存在

这似乎是正确的(What characters are forbidden in Windows and Linux directory names?)。从某种意义上说,它不会影响或困扰 Git ,因为Git处理提交而不是文件。它会影响。 :-)

Git将提交存储在其存储库数据库中。 Git还将每个文件的每个版本存储在此数据库中。每个存储的项目在内部都称为 object ,具有特殊的,压缩的,仅Git的形式。只要提交存在(通常是永久保存),提交中的文件就会另外冻结(通常是永久保存)。 1

冻结(只读),仅Git的文件对您和计算机上的其余程序都没有用。因此,Git需要一种将它们提取为可读写的有用形式的方法。它分两个阶段执行此操作:首先,它通过在文件的 index (实际上只是一个名为.git/index的文件)中列出文件来有效地解冻文件。索引跟踪工作树中的内容,或者至少应该是内容。然后,将其解压缩,并为它们提供有用的名称(即真实文件系统中的真实文件名),并将其放入您的工作树中。

这是最后一步,将解冻但仍仅限Git的索引条目转换为foo*bar之类的文件名,由于名称被禁止,该文件失败。因此,解冻后的条目位于,但不在工作树中。

Git始终根据索引中的内容进行 new 提交。甚至git commit -a之类的命令实际上只是更新索引,然后根据索引构建提交(尽管有些命令仅在提交期间使用临时辅助索引,然后修复实际索引)。因此,直到您更改 index 中文件的副本,您对工作树所做的任何事情(包括删除文件,或Git认为由于从未创建该文件而删除的文件)都只是以git status而言,未上演提交的更改。

不过,我们希望避免git status抱怨,并且避免git add 删除文件的索引副本。也就是说,如果有一个文件foo*bar,但它没有进入我们的工作树中,那可以,只要我们不想做任何事情该文件。我们可以将文件保留在索引中,而不是工作树中的文件,并让每个新的git commit重新冻结索引副本。我们只是不得不<脚,因为工作树中没有foo*bar

两个索引标志--assume-unchanged--skip-worktree让我们解决这个问题。 --skip-worktree是用于 meant 的标志:Git伙计们将其添加为“稀疏签出”,这是稀疏签出的一种特殊情况。因此,我们只能找到git status会认为已从工作树中删除的文件列表,即,索引中列出的文件,实际工作树中缺少的文件,并且没有特殊的标志设置在索引中,并设置--skip-worktree标志。

git ls-files -d打印此类文件名的列表。使用-z,它将以ASCII NUL(\0)字符而不是换行符结尾的字符打印出来。 xargs -0命令读取这些以NUL结尾的字符串,并对它们运行git update-index --skip-worktree,因此现在所有这些索引条目都设置了标志。新的提交将包含文件(因为索引列出了它们),但是工作树不会(因为它不能);同时git add不会尝试删除它们,并且git status不会抱怨它们。


1 这实际上是一条通用规则的一部分:Git的内部对象生活在键值存储中,该键值存储是由哈希ID组成的键,而任何对象的哈希ID都是唯一的,加密的对象内容的校验和。内容无法更改,因为如果更改,则校验和将更改,此后旧键仍将检索旧对象,只有新键/哈希ID才能检索新对象

答案 2 :(得分:0)

正如几天前有关类似问题的说法,这可能是一个shell问题,而不是git问题。

您是否尝试过git bash而不是Windows Shell?

在拉动之后,您是否尝试过使用星号的转义字符来重命名这些文件?