git archive : export-ignore, ignoring directories
Asked Answered
H

2

13

I have a git repository with this .gitattributes:

my_script.py export-subst
Makefile export-ignore
README.md export-ignore
.gitattributes export-ignore
.gitignore export-ignore
hooks/ export-ignore
tests/ export-ignore
*.pyc export-ignore

but when I make:

git archive HEAD | tar -x -C ../archive_dir

in the archive_dir directory, I get the directories hooks and tests:

 ls ../archive_dir/
 hooks/  my_script.py tests/

Why?

My git version is 1.7.9.

Hoopoe answered 17/2, 2014 at 14:51 Comment(2)
@twalberg git version : 1.7.9Hoopoe
@twalberg , git export-ignore other files, only have problems with the directoriesHoopoe
H
17

I removed the / in the directories, this fixed the problem

my_script.py export-subst
Makefile export-ignore
README.md export-ignore
.gitattributes export-ignore
.gitignore export-ignore
hooks export-ignore
tests export-ignore
*.pyc export-ignore

I find the solution in a answer to a similar question: git ignoring .gitattributes pattern

Hoopoe answered 17/2, 2014 at 15:12 Comment(1)
Please note that you exclude all hooks folder down the tree. To exclude only the one in the root, prepend it with slash: /hooks.Malena
T
2

Another approach, possible since Git 2.2+ (November 2014) is to filter the path you want to include in the archive.

See commit ed22b41 by Nguyễn Thái Ngọc Duy (pclouds):

archive: support filtering paths with glob

This patch fixes two problems with using :(glob) (or even "*.c" without ":(glob)").

The first one is we forgot to turn on the 'recursive' flag in struct pathspec. Without that, tree_entry_interesting() will not mark potential directories "interesting" so that it can confirm whether those directories have anything matching the pathspec.

The marking directories interesting has a side effect that we need to walk inside a directory to realize that there's nothing interested in there. By that time, 'archive' code has already written the (empty) directory down.
That means lots of empty directories in the result archive.

This problem is fixed by lazily writing directories down when we know they are actually needed. There is a theoretical bug in this implementation: we can't write empty trees/directories that match that pathspec.

path_exists() is also made stricter in order to detect non-matching pathspec because when this 'recursive' flag is on, we most likely match some directories. The easiest way is not consider any directories "matched".

Examples:

git archive -v HEAD -- ":(glob)**/sh"

git archive -o docs.zip v2.2.0 'Documentation/*.html'

Note (7 years later), this same command is being refactored with Git 2.32 (Q2 2021) See commit 4795748, commit 6c9fc42, commit 7367d88, commit 9614ad3, commit fcc7c12, commit eefadd1, commit 8de7821, commit dcc0a86 (20 Mar 2021) by Ævar Arnfjörð Bjarmason (avar).
(Merged by Junio C Hamano -- gitster -- in commit ad16f74, 30 Mar 2021)

For example, referencing the commit mentioned above:

archive: stop passing "stage" through read_tree_recursive()

Signed-off-by: Ævar Arnfjörð Bjarmason

The "stage" variable being passed around in the archive code has only ever been an elaborate way to hardcode the value "0".

This code was added in its original form in e4fbbfe ("Add git-zip-tree", 2006-08-26, Git v1.4.3-rc1 -- merge), at which point a hardcoded "0" would be passed down through read_tree_recursive() to write_zip_entry().

It was then diligently added to the "struct directory" in ed22b41 ("archive: support filtering paths with glob", 2014-09-21, Git v2.2.0-rc0 -- merge), but we were still not doing anything except passing it around as-is.

Let's stop doing that in the code internal to archive.c, we'll still feed "0" to read_tree_recursive() itself, but won't use it.

Ten answered 2/12, 2014 at 13:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.