我了解 .gitignore
文件掩盖了 Git 版本控制中的指定文件。我有一个项目 (LaTeX) 在运行时会生成大量额外文件(.auth
、.dvi
、.pdf
、日志等),但我不希望跟踪这些文件。
我知道我可以(也许应该)将所有这些文件放在项目中的一个单独的子文件夹中,因为我可以忽略该文件夹。
但是,是否有任何可行的方法将输出文件保留在项目树的根目录中并使用 .gitignore
忽略除我使用 Git 跟踪的文件之外的所有内容?就像是
# Ignore everything
*
# But not these files...
script.pl
template.latex
# etc...
一个可选的前缀!这否定了模式;任何被先前模式排除的匹配文件都将再次包含在内。如果否定模式匹配,这将覆盖较低优先级的模式源。
# Ignore everything
*
# But not these files...
!.gitignore
!script.pl
!template.latex
# etc...
# ...even if they are in subdirectories
!*/
# if the files to be tracked are in subdirectories
!*/a/b/file1.txt
!*/a/b/c/*
如果你想忽略一个目录的全部内容,除了其中的一个文件,你可以为文件路径中的每个目录编写一对规则。例如 .gitignore
忽略 pippo/pluto/paperino.xml
以外的 pippo
文件夹
pippo/*
!pippo/pluto
pippo/pluto/*
!pippo/pluto/paperino.xml
请注意,如果您只是在上面写了:
pippo/*
!pippo/pluto/paperino.xml
它不起作用,因为中间的 pluto
文件夹对 Git 不存在,所以 paperino.xml
找不到存在的地方。
foo
和 foo/*
不相同。为此,您需要使用 foo/*
作为基本文件夹
!.gitignore
否则这将不起作用。 .gitignore
文件也不会被 git 跟踪
在大多数情况下,您希望使用 /*
而不是 *
或 */
使用 *
是有效的,但它以递归方式工作。从那时起,它不会查看目录。人们建议再次使用 !*/
来包含目录,但实际上最好使用 /*
将最高级别的文件夹列入黑名单
# Blocklist files/folders in same directory as the .gitignore file
/*
# Includelist some files
!.gitignore
!README.md
# Ignore all files named .DS_Store or ending with .log
**/.DS_Store
**.log
# Includelist folder/a/b1/ and folder/a/b2/
# trailing "/" is optional for folders, may match file though.
# "/" is NOT optional when followed by a *
!folder/
folder/*
!folder/a/
folder/a/*
!folder/a/b1/
!folder/a/b2/
!folder/a/file.txt
# Adding to the above, this also works...
!/folder/a/deeply
/folder/a/deeply/*
!/folder/a/deeply/nested
/folder/a/deeply/nested/*
!/folder/a/deeply/nested/subfolder
上面的代码将忽略除 .gitignore
、README.md
、folder/a/file.txt
、folder/a/b1/
和 folder/a/b2/
以及最后两个文件夹中包含的所有文件之外的所有文件。 (并且这些文件夹中的 .DS_Store
和 *.log
文件将被忽略。)
显然我也可以这样做,例如 !/folder
或 !/.gitignore
。
更多信息:http://git-scm.com/docs/gitignore
.DS_Store
文件不会被忽略,但通过命令行这不是问题。为了解决这个问题,我不得不将 **/.DS_Store
移到所有其他规则之下。
!/nested/
或 !/nested
,您将无法执行 /*
然后 !/nested/folder/*
(或等效的 !/nested/folder
) ! (可能介于 /nested/*
之间)。要记住的一个技巧是,如果您将深度嵌套的子文件夹列入白名单,则需要将每个子文件夹中的子文件夹一直涂黑,而这些黑名单将以“斜线星”结尾...
更具体一点:
示例:忽略 webroot/cache
中的所有内容 - 但保留 webroot/cache/.htaccess
。
注意 cache
文件夹后面的斜杠 (/):
失败
webroot/cache*
!webroot/cache/.htaccess
作品
webroot/cache/*
!webroot/cache/.htaccess
# ignore these
*
# except foo
!foo
让我们工具化!
正如@Joakim 所说,要忽略文件,您可以使用如下所示的内容。
# Ignore everything
*
# But not these files...
!.gitignore
!someFile.txt
但如果文件位于嵌套目录中,则编写这些规则有点困难。
例如,如果我们要跳过所有文件,但不跳过位于 aDir/anotherDir/someOtherDir/aDir/bDir/cDir
中的 a.txt
。然后,我们的 .gitignore
将是这样的
# Skip all files
*
# But not `aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt`
!aDir/
aDir/*
!aDir/anotherDir/
aDir/anotherDir/*
!aDir/anotherDir/someOtherDir/
aDir/anotherDir/someOtherDir/*
!aDir/anotherDir/someOtherDir/aDir/
aDir/anotherDir/someOtherDir/aDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/
aDir/anotherDir/someOtherDir/aDir/bDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/
aDir/anotherDir/someOtherDir/aDir/bDir/cDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt
这很难手写。
为了解决这个障碍,我创建了一个名为 git-do-not-ignore 的 Web 应用程序,它将为您生成规则。
工具
https://theapache64.github.io/git-do-not-ignore/
演示
样本输入
aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt
样本输出
!aDir/
aDir/*
!aDir/anotherDir/
aDir/anotherDir/*
!aDir/anotherDir/someOtherDir/
aDir/anotherDir/someOtherDir/*
!aDir/anotherDir/someOtherDir/aDir/
aDir/anotherDir/someOtherDir/aDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/
aDir/anotherDir/someOtherDir/aDir/bDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/
aDir/anotherDir/someOtherDir/aDir/bDir/cDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt
要忽略目录中的某些文件,您必须按正确的顺序执行此操作:
例如,忽略文件夹“application”中除 index.php 和文件夹“config”之外的所有内容,注意顺序。
你必须首先否定你想要的。
失败
application/*
!application/config/*
!application/index.php
作品
!application/config/*
!application/index.php
application/*
git status
愚弄,检查您对 .gitignore
的更改是否按预期工作
git status
不会告诉您它正在查看什么以及忽略了什么,那么您如何知道这是否有效?
有与 OP 类似的问题,但前 10 名赞成的答案都没有真正起作用。我终于发现了以下内容
错误的语法:
*
!bin/script.sh
正确的语法:
*
!bin
!bin/script.sh
来自 gitignore man page 的解释:
可选前缀“!”这否定了模式;任何被先前模式排除的匹配文件都将再次包含在内。如果排除了该文件的父目录,则无法重新包含该文件。出于性能原因,Git 不会列出排除的目录,因此包含文件的任何模式都无效,无论它们是在哪里定义的。
这意味着上面的“错误语法”是错误的,因为 bin/script.sh
不能被重新包含,因为 bin/
被忽略了。就这样。
扩展示例:
$树。
.
├── .gitignore
└── bin
├── ignore.txt
└── sub
└── folder
└── path
├── other.sh
└── script.sh
$ 猫 .gitignore
*
!.gitignore
!bin
!bin/sub
!bin/sub/folder
!bin/sub/folder/path
!bin/sub/folder/path/script.sh
$ git status --untracked-files --ignored
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitignore
bin/sub/folder/path/script.sh
Ignored files:
(use "git add -f <file>..." to include in what will be committed)
bin/ignore.txt
bin/sub/folder/path/other.sh
nothing added to commit but untracked files present (use "git add" to track)
这就是我在忽略其他所有内容的同时保留文件夹结构的方式。您必须在每个目录(或 .gitkeep)中有一个 README.md 文件。
/data/*
!/data/README.md
!/data/input/
/data/input/*
!/data/input/README.md
!/data/output/
/data/output/*
!/data/output/README.md
您可以使用 git config status.showUntrackedFiles no
,所有未跟踪的文件将对您隐藏。详见man git-config
。
要从 .gitignore 中排除文件夹,可以执行以下操作。
!app/
app/*
!app/bower_components/
app/bower_components/*
!app/bower_components/highcharts/
这将忽略 bower_components
中除 /highcharts
之外的所有文件/子文件夹。
有很多类似的问题,所以我将发布我之前写的内容:
我让它在我的机器上工作的唯一方法就是这样做:
# Ignore all directories, and all sub-directories, and it's contents:
*/*
#Now ignore all files in the current directory
#(This fails to ignore files without a ".", for example
#'file.txt' works, but
#'file' doesn't):
*.*
#Only Include these specific directories and subdirectories and files if you wish:
!wordpress/somefile.jpg
!wordpress/
!wordpress/*/
!wordpress/*/wp-content/
!wordpress/*/wp-content/themes/
!wordpress/*/wp-content/themes/*
!wordpress/*/wp-content/themes/*/*
!wordpress/*/wp-content/themes/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*/*
请注意,您必须如何明确允许要包含的每个级别的内容。所以如果我在主题下有 5 个子目录,我仍然需要把它拼出来。
这是来自@Yarin 的评论:https://stackoverflow.com/a/5250314/1696153
这些是有用的主题:
.gitignore 中的否定模式如何工作?
gitignore 排除规则实际上是如何工作的?
我也试过
*
*/*
**/**
和**/wp-content/themes/**
或/wp-content/themes/**/*
这些都不适合我。很多线索和错误!
我是这样做的:
# Ignore everything
*
# Whitelist anything that's a directory
!*/
# Whitelist some files
!.gitignore
# Whitelist this folder and everything inside of it
!wordpress/wp-content/themes/my-theme/**
# Ignore this folder inside that folder
wordpress/wp-content/themes/my-theme/node_modules
# Ignore this file recursively
**/.DS_Store
使用 gig status -u
以递归方式查看未跟踪目录中的单个文件 - 使用 git status
您只会看到文件夹,这可能会让您误以为其中的所有内容都已被跟踪
我的子文件夹有问题。
不工作:
/custom/*
!/custom/config/foo.yml.dist
作品:
/custom/config/*
!/custom/config/foo.yml.dist
我尝试了上面给出的所有答案,但没有一个对我有用。阅读 gitignore 文档 (here) 后,我发现如果您首先排除文件夹,则子文件夹中的文件名不会被索引。因此,如果您之后使用感叹号来包含文件,则在索引中找不到它,因此不会包含在您的 git 客户端中。
这就是找到解决方案的方法。我开始为我的文件夹树中的所有子文件夹添加例外以使其正常工作,这是一项艰巨的工作。之后我能够将详细配置压缩为下面的配置,这与文档有点相反..
工作.gitignore:
# Ignore the 'Pro' folder, except for the '3rdparty' subfolder
/Pro/*
!Pro/3rdparty/
# Ignore the '3rdparty' folder, except for the 'domain' subfolder
/Pro/3rdparty/*
!Pro/3rdparty/domain/
# Ignore the 'domain' folder, except for the 'modulename' subfolder
Pro/3rdparty/domain/*
!Pro/3rdparty/domain/modulename/
结果,我在我的 git 客户端中看到,只有 Pro/3rdparty/domain/modulename/ 文件夹中的两个文件正在为下一次提交暂存,而这正是我正在寻找的。
如果您需要将同一文件夹的多个子文件夹列入白名单,则将感叹号行分组到 exclude 语句下方,如下所示:
# Ignore the 'Pro' folder, except for the '3rdparty' subfolder
/Pro/*
!Pro/3rdparty/
# Ignore the '3rdparty' folder, except for the 'domain' & 'hosting' subfolders
/Pro/3rdparty/*
!Pro/3rdparty/domain/
!Pro/3rdparty/hosting/
# Ignore the 'domain' folder, except for the 'modulename' subfolder
Pro/3rdparty/domain/*
!Pro/3rdparty/domain/modulename/
# Ignore the 'hosting' folder, except for the 'modulename' subfolder
Pro/3rdparty/hosting/*
!Pro/3rdparty/hosting/modulename/
否则它将无法按预期工作。
这对我有用,我只想向 repo 提交一个 Cordova 插件:
...
plugins/*
!plugins/cordova-plugin-app-customization
这里有很多复杂的答案......这是我在上面看不到的非常简单的东西,并且在许多情况下都能很好地工作:
# ignore all files that have an extension
**/*.*
# except for these extensions
!**/*.extension1
!**/*.extension2
这不会忽略任何无扩展名文件,但如果您有一堆名称相同或相似的文件,您可以为这些文件添加排除项
**/EXTENSIONLESSFILETOIGNORE
我有来自凉亭的 Jquery 和 Angular。 Bower 将它们安装在
/public_html/bower_components/jquery/dist/bunch-of-jquery-files
/public_html/bower_components/jquery/src/bunch-of-jquery-source-files
/public_html/bower_components/angular/angular-files
最小化的 jquery 位于 dist
目录中,而 angular 位于 angular
目录中。我只需要将最小化的文件提交到 github。对 .gitignore 进行了一些篡改,这就是我设法想到的……
/public_html/bower_components/jquery/*
!public_html/bower_components/jquery/dist
/public_html/bower_components/jquery/dist/*
!public_html/bower_components/jquery/dist/jquery.min.js
/public_html/bower_components/angular/*
!public_html/bower_components/angular/angular.min.js
希望有人能发现这很有用。
如果您需要忽略除少数文件和少数根文件夹之外的所有内容,则简单的解决方案:
/*
!.gitignore
!showMe.txt
!my_visible_dir
魔术在 /*
中(如上所述),它忽略(根)文件夹中的所有内容,但不递归。
!directory/*
不像之前的许多示例那样工作。它必须是 !directory
,最后没有斜杠或 *。
我解决这个问题的最简单方法是强制添加文件。即使它被掩埋或嵌套在 git 忽略的子目录树中,它也会在 git 中进行说明。
例如:
x64 文件夹不包含在 .gitignore 中:
x64/
但是您想包含位于 x64/Release/
目录中的文件 myFile.py
。然后你必须:
git add -f x64/Release/myFile.py
您可以对匹配模式的多个文件执行此操作,例如
git add -f x64/Release/myFile*.py
等等。
我得到了这个工作
# Vendor
/vendor/braintree/braintree_php/*
!/vendor/braintree/braintree_php/lib
到目前为止,没有什么对我有用,因为我试图从 lib 中添加一个 jar。
这没有用:
build/*
!build/libs/*
!build/libs/
!build/libs/myjarfile.jar
这有效:
build/*
!build/libs
我对单个文件的否定也有一些问题。我能够提交它们,但我的 IDE (IntelliJ) 总是抱怨被跟踪的被忽略的文件。
git ls-files -i --exclude-from .gitignore
显示了我以这种方式排除的两个文件:
public/
!public/typo3conf/LocalConfiguration.php
!public/typo3conf/PackageStates.php
最后,这对我有用:
public/*
!public/typo3conf/
public/typo3conf/*
!public/typo3conf/LocalConfiguration.php
!public/typo3conf/PackageStates.php
关键是首先文件夹的否定 typo3conf/
。
此外,似乎语句的顺序并不重要。相反,您需要明确否定所有子文件夹,然后才能否定其中的单个文件。
对于 .gitignore,文件夹 !public/typo3conf/
和文件夹内容 public/typo3conf/*
是两个不同的东西。
伟大的线程!这个问题困扰了我一段时间;)
我似乎找到了其他人没有提到的对我有用的东西。
# Ignore everything
*
# But not these files...
!.gitignore
!script.pl
!template.latex
# etc...
# And if you want to include a sub-directory and all sub-directory and files under it, but not all sub-directories
!subdir/
!subdir/**/*
基本上,它似乎否定了一个子目录被忽略,你必须有两个条目,一个用于子目录本身 !subdir/
,另一个用于扩展它下的所有文件和文件夹 !subdir/**/*
这是一场灾难,在使用 git
16 年(2005 年)之后,当位于目录层次结构的深处时,没有简单而明显的方法来排除 一个文件,即否则应被忽略。相反,我们需要诉诸疯狂的事情,例如反复挖掘结构并以正确的顺序排除和包含目录。一年 4 次你需要做的事情是不可能记住的。
唯一聪明但非常奇怪的替代方法是使用 git add --force
。当您不单独处理 gitted repo 时,某些时候肯定会失败。
所以我写了一个小 bash 函数来为你解决这个问题,以便于复制粘贴。让我先解释一下单线:
f=0; y='';for x in $(echo "uploads/rubbish/stuff/KEEP_ME/a.py" | tr '\/' '\n'); do y="$y/$x"; if [ $(($f)) -eq 0 ]; then y="$x"; f=1; fi; echo -e '!'"$y/\n$y/*"; done | sed '$d' |sed -z 's/..$//'; echo;
# output:
!uploads/
uploads/*
!uploads/rubbish/
uploads/rubbish/*
!uploads/rubbish/stuff/
uploads/rubbish/stuff/*
!uploads/rubbish/stuff/KEEP_ME/
uploads/rubbish/stuff/KEEP_ME/*
!uploads/rubbish/stuff/KEEP_ME/a.py
描述
有一个 if 语句来调整第一个项目没有得到 /。
tr '\/' '\n' - 将标准 POSIX 路径中的 / 转换为 \n(以获取列表)
y="$y/$x" - 在前一个目录之后添加下一个子目录(在列表中)。
echo -e '!'"$y/\n$y/*" - 打印 2 行子目录项,第一行带有 !前缀,第二个带有 /* 后缀。
sed '$d' - 删除最后一行
sed -z 's/..$//' - 从最后一行删除最后 2 个字符 /*
然后我们创建函数:
function gitkeep () { f=0; y='';for x in $(echo "$1" | tr '\/' '\n'); do y="$y/$x"; if [[ f -eq 0 ]]; then y="$x"; f=1; fi; echo -e '!'"$y/\n$y/*"; done | sed '$d' |sed -z 's/..$//'; echo; }
# gitkeep "uploads/rubbish/stuff/KEEP_ME/a"
!uploads/
uploads/*
!uploads/rubbish/
uploads/rubbish/*
!uploads/rubbish/stuff/
uploads/rubbish/stuff/*
!uploads/rubbish/stuff/KEEP_ME/
uploads/rubbish/stuff/KEEP_ME/*
!uploads/rubbish/stuff/KEEP_ME/a
这里我将算术 if
语句简化为 if [[ f -eq 0 ]];
。
享受!
KEEP_ME1/
和 KEEP_ME2/
无需重复这些子文件夹可能共有的行,因为它们共享相同的父文件夹。我怀疑,在您提供的方法中,必须分别列出每个文件夹 KEEP_ME1/
和 KEEP_ME2/
要旨
# Ignore everything
*
# But not these files...
!script.pl
!template.latex
可能包括:
!.gitignore
参考
从 https://git-scm.com/docs/gitignore:
可选前缀“!”这否定了模式;任何被先前模式排除的匹配文件都将再次包含在内。如果排除了该文件的父目录,则无法重新包含该文件。出于性能原因,Git 不会列出排除的目录,因此包含文件的任何模式都无效,无论它们是在哪里定义的。在第一个“!”前面放一个反斜杠(“\”)对于以文字“!”开头的模式,例如,“\!important!.txt”。 ... 排除除特定目录 foo/bar 之外的所有内容的示例(注意 /* - 没有斜杠,通配符也将排除 foo/bar 中的所有内容): $ cat .gitignore # 排除除目录 foo/bar 之外的所有内容 /* !/foo /foo/* !/foo/bar
通过 github.com/gitinclude,您可以下载一个命令行工具(适用于 windows、linux 和 osx),用于包含深度嵌套的文件集。
在 .gitinclude
中定义文件集并执行工具(通过双击或命令行)。您的 .gitignore
现已更新。
wp/
),但我不想忽略该文件夹深处的一些文件(例如wp/path/to/some/location/*
)。我可以让它工作的唯一方法是做git add -f wp/path/to/some/location/*
!*/
异常!*/
使我徒劳地尝试使.gitignore
文件正常工作。非常感谢。