我正在使用一个遗留应用程序,它在每次新用户登录时都会在源目录中创建一个新的子目录。到目前为止,它还没有受到源代码管理,所以我将它添加到Git并推送到我们公司的存储库--源代码加上几百个子目录。现在,每次我对代码进行更改并部署到生产环境时,我必须先git add自上次提交以来创建的所有子目录,然后在我可以下拉之前提交这些子目录。所以,我的问题是,我如何命令.gitignore对 * 任何 * 子目录(旧的或新的)视而不见,除了那些与代码相关的子目录?
git add
cs7cruho1#
假设您的项目目录(我假设它也是您的存储库根目录)中有以下结构:
./ ├── foo/ │ └── foo ├── bar/ │ └── baz ├── docs/ │ └── release/ │ └── 0.0.1 ├── README.md └── src/ └── code
其中目录foo/和bar/是生成结果的示例(您不想跟踪的),名称不可预测(或者难以单独地或以某种足够窄的模式显式地在.gitignore中列出),而docs/和src/包含(仅)要跟踪的文件(和子目录),并且您还希望直接跟踪存储库根目录中的任何文件(例如当前的README.md)。这可以通过存储库根目录中的以下.gitignore来实现:
foo/
bar/
.gitignore
docs/
src/
README.md
# Ignore all subirectories (but not files in the repo root dir): */ # ... except for the actual project sub dirs: !src/ !docs/
请参阅the documentation(也可以通过git help gitignore获得)了解.gitignore中的模式如何工作以及它们如何相互作用。下面是上面解决方案中使用的模式(大部分直接复制或部分稍微修改自上述文档):*匹配除斜杠以外的任何内容(/,它被用作目录分隔符)以及任何级别的任何目录名或文件名。这有点太宽泛了,因为我们不想忽略根目录中的文件。附加/使模式只匹配目录,因此*/匹配任何目录(在任何级别)。(忽略目录中的文件也会被忽略,因为Git不会跟踪目录本身。所以对于*/,我们忽略了整个文件树,除了直接在根目录中的文件。但这还是太多了,所以我们需要有选择地撤销一些忽略,我们可以通过其他模式来做到这一点:前缀! "否定"模式;由先前模式排除的任何匹配文件(此处,按*/)将再次被包括。但是,因为如果文件的父目录被排除,则不可能重新包括该文件(出于性能原因,Git不会列出被排除的目录,因此所包含文件上的任何模式都不会起作用,无论它们是在哪里定义的。docs/和src/将只匹配顶级目录docs和src,而不是foo/src(如果存在的话)。
git help gitignore
*
/
*/
!
docs
src
foo/src
上面描述的交互虽然有很好的文档记录,但对我来说似乎有些模糊,因此您可能更愿意通过预先添加/:
# Ignore all subirectories (but not files in the repo root dir): */ # ... except for the actual source dirs: !/src/ !/docs/
也可以用这种方式锚定第一个模式(不改变结果行为):
# Ignore all subirectories (but not files in the repo root dir): /*/ # ... except for the actual source dirs: !/src/ !/docs/
e5nszbig2#
要忽略从给定点开始的所有子目录,只需在通配符的末尾加一个斜杠:
但是,对于其他目录,这不应该阻止您进行下拉操作,除非这些目录在提交后被应用程序修改。请注意,即使.gitignore忽略了一个文件,也可以显式地将其添加到索引中,然后提交它。在这种情况下,它将像所有其他常规文件一样被跟踪。如果你仍然需要它们,你可能想使用git rm --cached在Git的历史记录中“从现在开始”将它们标记为已删除,而不是将它们从工作目录中删除。
git rm --cached
2条答案
按热度按时间cs7cruho1#
假设您的项目目录(我假设它也是您的存储库根目录)中有以下结构:
其中目录
foo/
和bar/
是生成结果的示例(您不想跟踪的),名称不可预测(或者难以单独地或以某种足够窄的模式显式地在.gitignore
中列出),而docs/
和src/
包含(仅)要跟踪的文件(和子目录),并且您还希望直接跟踪存储库根目录中的任何文件(例如当前的README.md
)。这可以通过存储库根目录中的以下
.gitignore
来实现:解释
请参阅the documentation(也可以通过
git help gitignore
获得)了解.gitignore
中的模式如何工作以及它们如何相互作用。下面是上面解决方案中使用的模式(大部分直接复制或部分稍微修改自上述文档):*
匹配除斜杠以外的任何内容(/
,它被用作目录分隔符)以及任何级别的任何目录名或文件名。这有点太宽泛了,因为我们不想忽略根目录中的文件。附加/
使模式只匹配目录,因此*/
匹配任何目录(在任何级别)。(忽略目录中的文件也会被忽略,因为Git不会跟踪目录本身。所以对于
*/
,我们忽略了整个文件树,除了直接在根目录中的文件。但这还是太多了,所以我们需要有选择地撤销一些忽略,我们可以通过其他模式来做到这一点:前缀
!
"否定"模式;由先前模式排除的任何匹配文件(此处,按*/
)将再次被包括。但是,因为如果文件的父目录被排除,则不可能重新包括该文件(出于性能原因,Git不会列出被排除的目录,因此所包含文件上的任何模式都不会起作用,无论它们是在哪里定义的。docs/
和src/
将只匹配顶级目录docs
和src
,而不是foo/src
(如果存在的话)。(等效)解决方案稍长,但更易于推理
上面描述的交互虽然有很好的文档记录,但对我来说似乎有些模糊,因此您可能更愿意通过预先添加
/
:也可以用这种方式锚定第一个模式(不改变结果行为):
e5nszbig2#
要忽略从给定点开始的所有子目录,只需在通配符的末尾加一个斜杠:
但是,对于其他目录,这不应该阻止您进行下拉操作,除非这些目录在提交后被应用程序修改。
请注意,即使
.gitignore
忽略了一个文件,也可以显式地将其添加到索引中,然后提交它。在这种情况下,它将像所有其他常规文件一样被跟踪。如果你仍然需要它们,你可能想使用
git rm --cached
在Git的历史记录中“从现在开始”将它们标记为已删除,而不是将它们从工作目录中删除。