如何从 git 存档中排除文件?
How do I exclude files from 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
在我的真实存储库中,使用特定文件存档的选项对我来说不是一个选项,因为它超过了最大命令行参数长度。
我知道我可以通过 export-ignore
属性将要排除的文件列表存储在 .gitattributes
中,但该列表是动态生成的。我可以自动更改文件,但直到另一次提交后更改才会被拾取。
是否有其他一些不需要再次提交即可运行的调用?
您可以创建一个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 参数长度以下
我认为您几乎做到了:可以从多个位置读取属性,.gitattributes
只是其中最常见的位置。第二个——被认为是每个存储库的配置——是 $GIT_DIR/info/attributes
.
引用手册:
Note that attributes are by default taken from the .gitattributes
files in the
tree that is being archived. If you want to tweak the way the output is
generated after the fact (e.g. you committed without adding an appropriate
export-ignore
in its .gitattributes
), adjust the checked out .gitattributes
file
as necessary and use --worktree-attributes
option. Alternatively you can keep
necessary attributes that should apply while archiving any tree in your
$GIT_DIR/info/attributes
file.
因此,如果可能的话,将您的列表粘贴到该文件,然后执行 git archive
。
另一种方法是不使用 git archive
而是仅 tar
工作树传递 tar
接受文件的 --exclude-from
命令行选项。这不适用于裸存储库,但如果您可以在归档之前检查内容,则可以通过 git read-tree
和 git checkout-index
提供正确的 $GIT_INDEX_FILE
来完成和 $GIT_WORK_TREE
环境。变量。
另一种可能的解决方法是反转方法:tar
(至少 GNU tar)支持一个鲜为人知的选项,即能够 删除 东西来自管道中的存档。
基本上可以做到
$ tar -C a_path -c -f - . \
| tar -f - --wildcards --delete '*.pdf' >result.tar
以便管道中的第一个 tar
归档所有内容,而第二个则传递所有内容,除了匹配 *.pdf
shell glob patten 的文件。
因此,如果使用 shell globs 指定要删除的文件可以满足命令行限制,只需将 git archive
的输出通过管道传输到 tar
进程,从而删除这些内容不需要。
除了将 export-ignore
放入(已提交).gitattributes
,您还可以将其放入(未提交)$GIT_DIR/info/attributes
文件。或者保留 .gitattributes
未提交并使用 --worktree-attributes
选项,这也可能不太好,因为它会使您的工作树变脏。
使用 Git 版本 2.20 (Windows) 和 Gitolite 服务器(未知版本)这对我来说可以排除名为 "b" 的文件和文件夹:
git archive HEAD . ":!b" | tar tf -
这也有效:
git archive HEAD . ":(exclude)b" | tar tf -
请注意,我在Windows平台上必须使用双引号,其他平台不确定。
一个可能的解决方案是git archive
想要一个树状的归档。
您正在通过它 HEAD
(可能是最常见的选择)。为了让它按照你的意思去做,这个 ref 会自动解析为它指向的对象——显然这将是一个提交。并且提交对象被解析为附加到它的树对象。所以你得到了当前提交的内容。到目前为止,很明显。
但是你可以传递任何你想要的树对象!这有什么帮助?好吧,您始终可以使用 git write-tree
从索引的当前状态创建一个树对象 - returns 它刚刚在 stdout 上创建的树对象的 SHA1。您不必创建提交或类似的东西。
因此,您可以 git rm --cached
在 tarball 中添加任何您不想要的内容,然后创建一个树对象以传递给 git archive
。因为你不关心树对象,所以你可以把它组合到 git archive
命令中:
git archive $( git write-tree )
之后您可以 git reset --hard
继续上路。
总计:
git rm --cached foo bar baz
git archive $( git write-tree )
git reset --all
给定一个简单的测试存储库,其中一次提交包含两个文件 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
属性将要排除的文件列表存储在 .gitattributes
中,但该列表是动态生成的。我可以自动更改文件,但直到另一次提交后更改才会被拾取。
是否有其他一些不需要再次提交即可运行的调用?
您可以创建一个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 参数长度以下
我认为您几乎做到了:可以从多个位置读取属性,.gitattributes
只是其中最常见的位置。第二个——被认为是每个存储库的配置——是 $GIT_DIR/info/attributes
.
引用手册:
Note that attributes are by default taken from the
.gitattributes
files in the tree that is being archived. If you want to tweak the way the output is generated after the fact (e.g. you committed without adding an appropriateexport-ignore
in its.gitattributes
), adjust the checked out.gitattributes
file as necessary and use--worktree-attributes
option. Alternatively you can keep necessary attributes that should apply while archiving any tree in your$GIT_DIR/info/attributes
file.
因此,如果可能的话,将您的列表粘贴到该文件,然后执行 git archive
。
另一种方法是不使用 git archive
而是仅 tar
工作树传递 tar
接受文件的 --exclude-from
命令行选项。这不适用于裸存储库,但如果您可以在归档之前检查内容,则可以通过 git read-tree
和 git checkout-index
提供正确的 $GIT_INDEX_FILE
来完成和 $GIT_WORK_TREE
环境。变量。
另一种可能的解决方法是反转方法:tar
(至少 GNU tar)支持一个鲜为人知的选项,即能够 删除 东西来自管道中的存档。
基本上可以做到
$ tar -C a_path -c -f - . \
| tar -f - --wildcards --delete '*.pdf' >result.tar
以便管道中的第一个 tar
归档所有内容,而第二个则传递所有内容,除了匹配 *.pdf
shell glob patten 的文件。
因此,如果使用 shell globs 指定要删除的文件可以满足命令行限制,只需将 git archive
的输出通过管道传输到 tar
进程,从而删除这些内容不需要。
除了将 export-ignore
放入(已提交).gitattributes
,您还可以将其放入(未提交)$GIT_DIR/info/attributes
文件。或者保留 .gitattributes
未提交并使用 --worktree-attributes
选项,这也可能不太好,因为它会使您的工作树变脏。
使用 Git 版本 2.20 (Windows) 和 Gitolite 服务器(未知版本)这对我来说可以排除名为 "b" 的文件和文件夹:
git archive HEAD . ":!b" | tar tf -
这也有效:
git archive HEAD . ":(exclude)b" | tar tf -
请注意,我在Windows平台上必须使用双引号,其他平台不确定。
一个可能的解决方案是git archive
想要一个树状的归档。
您正在通过它 HEAD
(可能是最常见的选择)。为了让它按照你的意思去做,这个 ref 会自动解析为它指向的对象——显然这将是一个提交。并且提交对象被解析为附加到它的树对象。所以你得到了当前提交的内容。到目前为止,很明显。
但是你可以传递任何你想要的树对象!这有什么帮助?好吧,您始终可以使用 git write-tree
从索引的当前状态创建一个树对象 - returns 它刚刚在 stdout 上创建的树对象的 SHA1。您不必创建提交或类似的东西。
因此,您可以 git rm --cached
在 tarball 中添加任何您不想要的内容,然后创建一个树对象以传递给 git archive
。因为你不关心树对象,所以你可以把它组合到 git archive
命令中:
git archive $( git write-tree )
之后您可以 git reset --hard
继续上路。
总计:
git rm --cached foo bar baz
git archive $( git write-tree )
git reset --all