Given a simple test repository with a single commit with two files,
$ git ls-files a
$ git ls-files . ':!b'
$ git archive HEAD a | tar tf -
$ git archive HEAD . ':!b' | tar tf -
I think you almost nailed it: attributes can be read from several places, with
.gitattributes being only the most common of them. The second one—considered a per-repository configuration—is
To cite the manual:
Note that attributes are by default taken from the
.gitattributesfiles 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
.gitattributes), adjust the checked out
.gitattributesfile as necessary and use
--worktree-attributesoption. Alternatively you can keep necessary attributes that should apply while archiving any tree in your
So, if possible, stick your list to that file and then do
Another approach is to not use
git archive but instead merely
tar the work tree passing
--exclude-from command-line option which accepts a file. This wouldn't work for a bare repository, but if you're OK with checking out stuff before archiving it, this can be done by doing
git read-tree and
git checkout-index supplied with the correct
$GIT_WORK_TREE env. variables.
Another possible workaround is reversing the approach:
tar (at least GNU tar) supports a lesser-known option of being able to delete stuff from an archive in a pipeline.
Basically, you can do
$ tar -C a_path -c -f - . \ | tar -f - --wildcards --delete '*.pdf' >result.tar
so that the first
tar in the pipeline archives everything while the second one passes everything through except for files matching the
So if specifying files to delete using shell globs can be fitted to the command-line limit, just pipe the output of
git archive to a
tar prcocess which removes the stuff not needed.