有没有办法告诉git只包含某些文件而不是忽略某些文件?

220

我的程序通常会生成巨大的输出文件(约1 GB),我不希望将它们备份到 Git 存储库中。因此,我不能使用以下命令:

git add .

我需要做类似这样的事情

git add *.c *.cc *.f *.F *.C *.h *.cu

这有点繁琐...

我相信我可以编写一个快速的perl脚本,将目录内容列入.gitignore文件中,再根据一个名为.gitinclude(或类似名称)的文件删除文件,但这似乎有点hackish。 有更好的方法吗?

7个回答

306

我自己没有尝试过这个,但是根据我阅读的TFM,似乎否定模式可以实现你想要的效果。 你可以使用后面的否定项覆盖.gitignore中的条目。 因此,你可以这样做:

*.c
!frob_*.c
!custom.c
忽略所有的.c文件,但是除了custom.c和任何以"frob_"开头的文件。

27
谢谢,T.E.D.。这个方法很有效。我只需要在 .gitignore 文件中以 * 开始,然后列出所有包含的文件模式,前面加上一个感叹号即可。 - Daisy Sophia Hollman
11
文件夹怎么样?我找不到一种方法来通过否定规则来包含文件夹和文件。 - Marcio Cruz
5
关于文件夹,请查看 https://dev59.com/aGcs5IYBdhLWcg3wgkIQ。 - uzsolt
2
非常好。我正在使用这个在我的主文件夹中建立一个存储库,用于存放像vimrc和bashrc之类的东西。 - Martin Capodici
1
@uzsolt 不适用于包含一个特定文件夹的情况。请参见https://dev59.com/rHNA5IYBdhLWcg3wX8rk#29932318 - DiCaprio
显示剩余6条评论

94

在您的代码库中创建.gitignore文件,并且只想跟踪c文件并忽略所有其他文件,则将以下行添加到该文件中...

*
!*.c

'*' 将忽略所有文件

而!将排除需要被忽略的文件....所以这里我们要求git不要忽略c文件....


3
* 是一个通配符,即使对于 . 也是如此,因此隐藏文件也被忽略,但是以 .c 结尾的所有隐藏文件都会被包括。 - tim-phillips
2
使用这种方法,我认为子文件夹中的文件也会被忽略。请查看此链接以获取更多详细信息:https://dev59.com/d2ct5IYBdhLWcg3wvf_K#11853075 - Stelian
1
我在我的主目录中使用此方法仅跟踪我的 .bashrc 和 .bash_history,例如在 .gitignore 文件中添加以下内容:* 后跟 !.bash* - user5359531
2
你可能需要在Windows上使用 *.* - 参见@Smaranjit Maiti的答案 - Martin Capodici
如果你在子目录中有 *.c 文件,而第一个目录是 ,那么它会有效地忽略所有的子目录。因此,即使你在 * 之后包含 !.c,子目录中的文件也不会被包括在内。 - alpha_989
显示剩余4条评论

22

最好的解决方案是

在仓库根目录中创建.gitignore文件,如果你只想包含.c文件,则需要将以下行添加到.gitignore文件中。

*.*
!*.c
这将递归地包括目录和子目录中的所有.c文件。 使用
*
!*.c

不是所有版本的git都适用。

已测试通过

git版本为2.12.2.windows.2


4
我也遇到了和*相关的问题,只能使用*.*解决。这是在Windows上使用gitbash和git版本2.9.0.windows.1时发生的。 - Martin Capodici

15
如果您需要忽略某些文件但不是目录中的特定文件,这是我如何做到的:
# Ignore everything under "directory"
directory/*
# But don't ignore "another_directory"
!directory/another_directory
# But ignore everything under "another_directory"
directory/another_directory/*
# But don't ignore "file_to_be_staged.txt"
!directory/another_directory/file_to_be_staged.txt

6
我看到了许多关于最初的“忽略一切”规则的建议,无论是在SO网站上还是其他网站上,但我发现大部分都有其自己烦人的使用问题。这引发了一些项目,比如可分发的.gitinclude.NET托管在GH Pages上的git-do-not-ignore,它们只是简单地帮助使这个过程更加容易维护。
每一个这样的建议(以及许多其他博客文章)都建议从一个简单的*开始,以字面意义上忽略当前根目录中的所有文件和文件夹。
此后,包含一个文件“就像”在路径前加上!那样简单,例如!.gitignore,以确保我们的仓库不会忽略自己的.gitignore规则文件。
这样做的缺点是,当Git遇到一个被忽略的文件夹时,出于性能原因,它不会检查它的内容。在嵌套路径中尝试“不要”忽略一个文件变得非常麻烦:
# ...when ignoring all files and folders in the current root
*

!custom_path                       # allow Git to look inside this folder
custom_path/*                      # but ignore everything it contains
!custom_path/extras                # allow Git to look inside this folder
custom_path/extras/*               # but ignore everything it contains
!custom_path/extras/path_to_keep   # allow Git to see the file or folder you want to commit

因此,为了提供一个替代性的想法,我刚刚在我的Windows用户个人资料文件夹的根目录中配置了一个.gitignore文件,以** / *开头,而不是通常看到的**.*
此后,我想要明确包含的每个路径只需要一个条目每个树级别。稍微简化上一个示例如下:
# ...when ignoring all files recursively from the current root
**/*

!custom_path                       # allow Git to look inside this folder
!custom_path/extras                # allow Git to look inside this folder
!custom_path/extras/path_to_keep   # allow Git to see the file or folder you want to commit

这并不是一个非常巨大的区别,但足以使文件更易于阅读和维护,特别是在尝试取消忽略嵌套约5层深度的文件时...

这种方法的问题在于你不能取消忽略目录,只能取消忽略单个文件(除非我漏掉了什么)。 - undefined

1
如果你只想包含点文件,这个方法对我有效...
!.*

0
虽然来晚了,但我的解决方案是为源文件创建一个目录,为可执行文件和程序输出创建另一个目录,就像这样:
+ .git
|    (...)
+ bin
|    my_exe.exe
|    my_output.txt
+ src
     some_file.c
     some_file.h 

...然后只将src/中的内容添加到我的代码库中,完全忽略bin/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接