如何从git归档中排除文件?

如何从git归档中排除文件?,git,git-archive,Git,Git Archive,给定一个简单的测试存储库,其中包含两个文件,a和b,我可以获得特定文件的列表: $ git ls-files a a $ git ls-files . ':!b' a $ git archive HEAD a | tar tf - a $ git archive HEAD . ':!b' | tar tf - a b 或不包括特定文件的所有文件的列表: $ git ls-files a a $ git ls-files . ':!b' a $ git archive HEAD a |

给定一个简单的测试存储库,其中包含两个文件,
a
b
,我可以获得特定文件的列表:

$ git ls-files a
a
$ git ls-files . ':!b'
a
$ git archive HEAD a | tar tf -
a
$ git archive HEAD . ':!b' | tar tf -
a
b
或不包括特定文件的所有文件的列表:

$ git ls-files a
a
$ git ls-files . ':!b'
a
$ git archive HEAD a | tar tf -
a
$ git archive HEAD . ':!b' | tar tf -
a
b
我可以创建特定文件的存档:

$ git ls-files a
a
$ git ls-files . ':!b'
a
$ git archive HEAD a | tar tf -
a
$ git archive HEAD . ':!b' | tar tf -
a
b
但我无法创建除特定文件之外的所有文件的存档:

$ git ls-files a
a
$ git ls-files . ':!b'
a
$ git archive HEAD a | tar tf -
a
$ git archive HEAD . ':!b' | tar tf -
a
b
在我的真实存储库中,使用特定文件的存档不是我的选项,因为它超过了最大命令行参数长度

我知道我可以通过
export ignore
属性将要排除的文件列表存储在
.gittributes
中,但该列表是动态生成的。我可以自动更改文件,但在再次提交之前,不会拾取更改


是否有其他调用可以在不需要再次提交的情况下工作?

您可以创建一个tar,然后删除不需要在其中的文件夹和文件

git archive HEAD -o archive.tar
tar -f archive.tar --delete listoffiles1
tar -f archive.tar --delete listoffiles2
tar -f archive.tar --delete listoffiles..
tar -f archive.tar --delete listoffilesN

通过这种方式,您可以拆分命令行,使其保持在最大cli参数长度以下。我认为您几乎可以做到这一点:属性可以从多个位置读取,其中,
.gittributes
是最常见的属性。第二个被认为是每个存储库配置的是
$GIT\u DIR/info/attributes

引用手册:

请注意,默认情况下,属性取自 正在存档的树。如果要调整输出的方式 在事实发生后生成(例如,您未添加适当的
export ignore
在其
.gittributes
中,调整签出的
.gittributes
文件 根据需要,使用
--worktree attributes
选项。或者你可以保留 归档数据库中的任何树时应应用的必要属性
$GIT\u DIR/info/attributes
文件

因此,如果可能的话,将您的列表粘贴到该文件,然后执行
git archive

另一种方法是不使用
git archive
,而只使用
tar
工作树传递
tar
接受文件的
--exclude from
命令行选项。这对于裸存储库不起作用,但是如果您在归档之前能够签出内容,那么可以通过执行
git read tree
git checkout index
来完成,并提供正确的
$git_index_文件
$git_work_tree
env。变量

另一种可能的解决方法是逆转这种方法:
tar
(至少是GNU tar)支持一种鲜为人知的选项,即能够从管道中的存档中删除内容

基本上,你能做到

 $ tar -C a_path -c -f - . \
   | tar -f - --wildcards --delete '*.pdf' >result.tar
因此,管道中的第一个
tar
会归档所有内容,而第二个会传递所有内容,但与
*.pdf
shell全局模式匹配的文件除外


因此,如果使用shell globs指定要删除的文件可以符合命令行限制,只需将
git archive
的输出通过管道传输到
tar
prcoess,它将删除不需要的内容。

除了将
export ignore
放入(提交的)
.gittributes
之外,还可以将其放入(未提交)
$GIT_DIR/info/attributes
文件。或者将
.gittributes
保持为未提交状态,并使用
--worktree attributes
选项,这也可能不太好,因为它会使工作树变脏。

使用GIT 2.20版(Windows)和Gitolite服务器(未知版本)这适用于排除名为“b”的文件和文件夹:

这也适用于:

git archive HEAD . ":(exclude)b" | tar tf -

请注意,我必须在Windows平台上使用双引号,不能确定其他平台。

感谢您提供的详细答案。我认为对我来说,
。git/info/attributes
不一定是最符合逻辑的方法,但它最适合我现有的方法,如果我将来需要更多的方法,我可以将其更改为
tar--delete