1

我真的很难理解 .gitignore 文件是如何工作的......

这是我的文件的样子:

custom/history
cache
*.log
custom/modules/*/Ext
upload
sugar-cron*
custom/application/Ext
custom/Extenstion/modules/*/Ext/Language
!custom/modules/*/Language/cs_CZ.*
!custom/modules/*/Language/en_us.*
custom/Extenstion/application/Ext/Language
!custom/Extenstion/application/Ext/Language/cs_CZ.*
!custom/Extenstion/application/Ext/Language/en_US.*
.htaccess
config.php
config_override.php
files.md5

这就是我的 git status 的样子:

apache@cb772759c68a sugarcrm$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#    LOG.txt
#    deploy_backup/
nothing added to commit but untracked files present (use "git add" to track)

所以现在我想删除这两个未跟踪的文件,但令我惊讶的是,一大堆其他文件也被删除了。

apache@cb772759c68a sugarcrm$ git clean -fd
Removing Disabled/upload:/
Removing LOG.txt
Removing custom/Extension/modules/Bugs/Ext/Language/
Removing custom/Extension/modules/Cases/Ext/Language/
Removing custom/Extension/modules/EmailAddresses/
Removing custom/Extension/modules/EmailParticipants/
Removing custom/Extension/modules/ForecastManagerWorksheets/
Removing custom/Extension/modules/ForecastWorksheets/
Removing custom/Extension/modules/Forecasts/
Removing custom/Extension/modules/Meetings/Ext/Layoutdefs/
Removing custom/Extension/modules/Meetings/Ext/WirelessLayoutdefs/
Removing custom/Extension/modules/Meetings/Ext/clients/
Removing custom/Extension/modules/ModuleBuilder/
Removing custom/Extension/modules/OutboundEmail/
Removing custom/Extension/modules/PdfManager/
Removing custom/Extension/modules/ProjectTask/Ext/Language/
Removing custom/Extension/modules/Quotas/
Removing custom/Extension/modules/Quotes/Ext/Dependencies/
Removing custom/Extension/modules/Targets/
Removing custom/Extension/modules/Tasks/Ext/Language/
Removing custom/Extension/modules/TimePeriods/
Removing custom/application/
Removing custom/install/
Removing custom/modules/Administration/
Removing custom/modules/Bugs/
Removing custom/modules/Cases/
Removing custom/modules/Contracts/
Removing custom/modules/Emails/
Removing custom/modules/HHP_Products/
Removing custom/modules/KBContents/
Removing custom/modules/Project/
Removing custom/modules/ProjectTask/
Removing custom/modules/ProspectLists/
Removing custom/modules/Prospects/
Removing custom/modules/Quotas/
Removing custom/modules/Reports/
Removing custom/modules/RevenueLineItems/
Removing custom/modules/Schedulers/
Removing custom/modules/Tags/
Removing custom/modules/Teams/
Removing custom/modules/hhp_assignment_zip/
Removing custom/modules/hhp_zipcode/
Removing custom/working/modules/Calls/
Removing custom/working/modules/Leads/clients/
Removing deploy_backup/
Removing deploy_log/
Removing dist/identity-provider/tests/docker/saml-test/config/simplesamlphp/config/
Removing vendor/sugarcrm/identity-provider/tests/docker/saml-test/config/simplesamlphp/config/

第一点 - 删除的文件git status显然是 gitignore“掩码”的一部分后没有显示......谁能解释一下,这些文件中的任何一个如何匹配 gitignore 中的任何模式?就像vendor/sugarcrm/identity-provider/tests/docker/saml-test/config/simplesamlphp/config/......任何人都可以帮助我建立一个propper gitignore吗?

第二点 - 我认为 .gitignore 从 .gitignore “保护”这些未版本化的文件git clean,git 实际上不会对它们采取任何行动。所以很明显它确实删除了它们......我怎么能在使用时不删除未版本控制的文件git clean

编辑:我将 git clean 与 git rm 混淆了,我一直在谈论 git clean

编辑 2:事实证明,与 .gitignore 不匹配的已删除目录毕竟是“空的”。(他们有子目录,但目录树没有任何文件......)

4

2 回答 2

4

TL;博士

您误解git clean了默认删除的内容和使用-d. (注意:我不是我自己的忠实粉丝git clean;让它删除珍贵文件太容易了。)

正如phd 所指出的那样,在默认情况下,将文件列在.gitignore特定位置会禁用将git clean其清除。然而,git clean(明显)比这更复杂。我们稍后会讨论这个。

不过,首先,让我们解决.gitignore条目的一个特点。如果您已经知道所有这些(但似乎没有人知道:-)),您可以跳到下面的git clean特定部分。

  1. 被跟踪的文件(现在在索引中)永远不会被忽略,因此匹配.gitignore或等效(例如,.git/info/exclude)模式是无关紧要的。

    这句话现在在索引中就是这个意思。当您使用git addgit rm --cached添加或删除文件时,会更改其跟踪性。您还可以使用git ls-files --stage转储索引中每个文件的完整列表及其暂存数据(模式、哈希和阶段插槽编号),或者--stage仅获取名称。

  2. Git 找到的文件(不是目录)现在不在索引中,是untracked。Git 不存储目录,因此目录永远不会出现在索引中。1 跟踪或未跟踪纯粹是文件的属性。

  3. 未跟踪的文件也可以是被忽略的文件。如果是这样git add,即使您在命令行上显式命名它也不会添加它(尽管您既可以显式命名它也可以使用--force来添加它)。

    这意味着文件(但不是目录)属于以下三个类别之一:已跟踪、未跟踪(仅)或未跟踪和忽略。 这对 来说很重要git status,它只抱怨未跟踪的文件(不是未跟踪和忽略的),但也有一段时间git clean

  4. 最后,当 Git 进行完整的目录树搜索/扫描时——git add .例如——并遇到一个它可能能够跳过的目录(其中没有跟踪的文件),Git 将检查目录本身是否匹配.gitignore模式,如果是这样,不要往里面看。 这会加快git statusgit add -A/git add .在此类目录上的速度(有时,如果您可以忽略整个供应商树或 SDK,则速度会非常快)。

规则 4 是为什么,如果您不想忽略位于某个目录路径下的特定文件路径,您必须指示 Git 明确地不忽略该目录。如果忽略目录,Git 可能永远不会查看目录内部。这尤其会影响这三行:

custom/Extenstion/application/Ext/Language
!custom/Extenstion/application/Ext/Language/cs_CZ.*
!custom/Extenstion/application/Ext/Language/en_US.*

如果您忽略了整个目录custom/Extenstion/application/Ext/Language,Git 将不会查看它,也永远不会找到任何匹配的文件custom/Extenstion/application/Ext/Language/cs_CZ.*来取消忽略它。因此,有必要将目录本身从忽略状态中排除:您应该将第一行更改为 read custom/Extenstion/application/Ext/Language/*,以便 Git 必须查看目录内部。cs_CZ.*以and结尾的后续en_US.*行将覆盖捷克语和美国英语文件的忽略状态。


1事实上,它们可以出现在索引中,但只是为了作为特殊情况处理。 git ls-files,它可以显示索引内容,直接跳过它们。


使用git clean -d明确修改规则 4

Git 只能删除的目录。这是操作系统强制执行的一般规则:如果一个目录d包含一些文件d/f1d/f2等,并且您要在d没有先删除文件的情况下删除这些文件,那么这些文件就会有问题。系统会强制您首先删除目录中的文件。这也适用于子目录:d如果d/sub存在,即使d/sub它本身是一个空目录,也不能删除。 只能删除空目录。

git clean不运行-d不仅会安装 Rule 4,而且实际上扩展了它。例如,在我们开始的示例中,Git 注意到 (1)custom/Extenstion/application/Ext/Language是一个目录;(2) 目录匹配忽略模式;所以 (3)如果其中没有已跟踪的文件custom/Extenstion/application/Ext/Language Git 可以并且将跳过整个目录(当然不会删除它,因为git clean运行时没有-d)。

假设有另一个名为的目录xyzzy/在索引中没有列出任何文件。此目录可能完全为空。在这种情况下,根据定义,其中没有未跟踪的文件;所以git clean没有-d应该对它做任何事情。或者它可能有文件;根据定义,这些文件是未跟踪的(因此可能是未跟踪和忽略的),但是您说不要删除目录,所以git clean 仍然懒得看里面。这是一个有点奇怪的情况:Git 通常不会费心去查看未知目录。2 (您也可以看到git status:您必须使用它git status -uall来查找神秘目录中的文件git add -A。但是orgit add .必须查看内部,除非该目录被忽略,这就是为什么规则 4 在一般情况下有点复杂。)

但是,与 一起运行-d显然完全抛弃了规则 4。同样,为了删除目录,Git 必须首先删除目录中的所有文件。为此,Git 还必须枚举内容。因此,如果您告诉git clean使用-d,完全禁用规则 4 似乎是合适的。路径名的目录性将强制 Git 扫描目录的内容。要么我们已经需要查看内部,因为有跟踪的文件,要么我们需要查看内部以删除文件以删除目录。


2请注意,“未知”与“未跟踪”不同。它甚至不是一个 Git 术语。我在这里编好了。然而,正如我们将看到的,如果 Git确实定义了“未跟踪目录”这个短语可能会很好。


什么git clean删除

运行git clean -n会告诉你它会删除什么。该显示使用了一些简写:删除目录意味着删除该目录中的所有文件,包括(递归地)带有子文件的子目录。这比使用-f而不是运行更安全-n,因为-f它向您展示了它确实删除了什么,同样的方式-n向您展示了它将删除什么。

默认情况下,git clean删除未跟踪的文件,但不删除未跟踪和忽略的文件。也就是回到上面第3点,看文件的三分类:git clean去掉中间的分类(只)。添加-X(大写 X)告诉 Git:不要删除未跟踪的文件;相反,删除未跟踪和忽略的文件。

添加-x告诉 Git:不要读取通常的忽略指令文件,例如.gitignore. 此时,不会忽略任何文件,因此(无论跟踪哪些文件)都不能不跟踪和忽略任何文件。将其与3-X结合起来毫无意义,因此禁止您同时使用and 。git clean-x-X

运行git clean添加-d空目录删除。不过,在这里,事情变得特别古怪。似乎 Git 的跟踪、未跟踪和未跟踪和忽略的分类有点崩溃了。 文档说这-d将:

除了未跟踪的文件之外,还删除未跟踪的目录。

但是 Git 没有定义未跟踪的目录。“跟踪性”完全是files的属性。我们确实在脚注中看到目录作为不可见的实体潜入索引中(为了加速各种 Git 操作),但这并不意味着目录被跟踪

我们可以组成一个:“未跟踪目录”可能是一个不包含跟踪文件的目录。我认为(但还没有证明我自己满意)这个定义有效并解释了git clean的行为。不过,如果 Git 文档确实正确地定义了这一点,将会有很大帮助。


3组合-x-Xwith-e可能有一些实际用途,但 Git 仍然禁止这样做,至少在今天如此。

于 2018-01-28T21:17:27.127 回答
1
  1. .gitignore忽略文件被添加和提交。它不能保护它们不被清洁,恰恰相反。

  2. 那些清理过的文件与.gitignore以下方式有关:

    自定义/扩展/模块/错误/扩展/语言/自定义/扩展/模块/案例/扩展/语言/

匹配custom/modules/*/Ext规则。

LOG.txt
vendor/sugarcrm/identity-provider/tests/docker/saml-test/config/simplesamlphp/config/

文件未添加到索引中,因此它们有资格进行清理。

  1. 为避免清理未版本控制的文件,请不要运行git clean. 手动删除不必要的文件。
于 2018-01-28T14:11:55.410 回答