Skip to contentSkip to conversation

gitattributes.txt: mention exceptions to gitignore rules

PATCH In review Nguyễn Thái Ngọc Duy 4 participants 5 messages Jun 15, 2016 1 message not in the archive Documentation

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw

PATCH 1/1 gitattributes.txt: mention exceptions to gitignore rules

gitattr and .gitignore are supposed to use the same rules for matching patterns. Unfortunately it's not exactly the same in reality. Mention the differences so users won't be surprised, until gitattr gets updates.

---
2011/1/4 Marcin Wiśnicki <[email protected]>:

Quoted 2 lines

I think that for the time being at least the manual page must change to reflect reality.

Looks like changes will be more than just a few lines because path_matches() needs to learn about directories (iow less likely to get fixed right away). So, yes, good idea.

I skimmed through excluded_from_list() (gitignore) and path_matches (gitattr). Seems no other differences.

 Documentation/gitattributes.txt |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
Documentation/gitattributes.txt +1 -0
index 5a7f936..cfaf107 100644
@@ -56,6 +56,7 @@ When more than one pattern matches the path, a later line
 overrides an earlier line.  This overriding is done per
 attribute.  The rules how the pattern matches paths are the
 same as in `.gitignore` files; see linkgit:gitignore[5].
+However patterns that end with a slash is not supported.
 
 When deciding what attributes are assigned to a path, git
 consults `$GIT_DIR/info/attributes` file (which has the highest
Signature · 1 line
1.7.3.4.878.g439c7
#2 lore raw

Nguyễn Thái Ngọc Duy venit, vidit, dixit 04.01.2011 14:31:

Quoted 26 lines

gitattr and .gitignore are supposed to use the same rules for matching patterns. Unfortunately it's not exactly the same in reality. Mention the differences so users won't be surprised, until gitattr gets updates.

---
2011/1/4 Marcin Wiśnicki <[email protected]>:

Quoted 2 lines

I think that for the time being at least the manual page must change to reflect reality.

Looks like changes will be more than just a few lines because path_matches() needs to learn about directories (iow less likely to get fixed right away). So, yes, good idea.

I skimmed through excluded_from_list() (gitignore) and path_matches (gitattr). Seems no other differences.

 Documentation/gitattributes.txt |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
Documentation/gitattributes.txt +0 -0
index 5a7f936..cfaf107 100644

Documentation/gitattributes.txt When more than one pattern matches the path, a later line · line 59

Quoted 4 lines
Documentation/gitattributes.txt +1 -0
@@ -56,6 +56,7 @@ When more than one pattern matches the path, a later line
 overrides an earlier line.  This overriding is done per
 attribute.  The rules how the pattern matches paths are the
 same as in `.gitignore` files; see linkgit:gitignore[5].
+However patterns that end with a slash is not supported.

+However, patterns terminated by a slash are not supported.

Documentation/gitattributes.txt When more than one pattern matches the path, a later line · line 62

Quoted 3 lines
Documentation/gitattributes.txt +0 -0
 When deciding what attributes are assigned to a path, git
 consults `$GIT_DIR/info/attributes` file (which has the highest

Cheers,
Michael

#3 lore raw
In reply to Nguyễn Thái Ngọc Duy
Quoted 7 lines · Nguyễn Thái Ngọc Duy

2011/1/4 Marcin Wiśnicki <[email protected]>:

Quoted 2 lines

I think that for the time being at least the manual page must change to reflect reality.

Looks like changes will be more than just a few lines because path_matches() needs to learn about directories (iow less likely to get fixed right away). So, yes, good idea.

Not really. I'd rather see a handful of test cases added to t0003 to help interested parties to see what is broken and what is not.

Quoting from Marcin's other message, assuming that "Patterns" are stored in either .gitattributes at the top level or .git/info/attributes:

Quoted 4 lines

Example for file: d1/d2/f1.c

Patterns that match:
*.c

No slashes, so it should match anywhere (correct).

Quoted 1 line

d1/d2/*

With slashes, so this is anchored at the toplevel of the working tree, and the path should match (correct).

Quoted 1 line

/d1/d2/*

The same as above;, the leading '/' is only to make it explicit that it is anchored at the level

Quoted 1 line

*/d2/*

Should match.

Quoted 1 line

*/*/*

Should match.

Quoted 2 lines

Patterns that do not match but should:
d2/*

This shouldn't match unless it appears in d1/.gitattributes.

The presense of '/' makes the pattern anchored to the directory it appear in, and .git/info/attributes is taken as being at the top level.

Quoted 2 lines

d2/
d2

These shouldn't for the same reason.

Quoted 2 lines

d1/d2
/d1/d2

We somehow don't do leading path match like we do for gitignore, but I do not think this was intended. My gut feeling is that these should match.

The thinking back, when we wrote the code, could have been that, unlike gitignore that maintains only one bit (either "ignored" or "not"), attributes are richer and giving the same attribute (say "whitespace checking criteria") to files inside a directory and the containing directory itself was nonsensical. But if that was the reason, it is faulty, as we do not track directories anyway.

Wouldn't it be sufficient to teach attr.c:path_matches() that a pattern could also match with leading path? That would automatically cover the case where a pattern is terminated with a slash, as pattern "d/e/" would never match path "d/e" but does match "d/e/f"?

#4 lore raw
Quoted 8 lines · Junio C Hamano
Quoted 2 lines

Patterns that do not match but should:
d2/*

This shouldn't match unless it appears in d1/.gitattributes.

The presense of '/' makes the pattern anchored to the directory it appear in, and .git/info/attributes is taken as being at the top level.

After more carefully re-reading gitignore(5) I think that now I get it.

I presume that is is not possible to match certain pattern occurring *anywhere* in the path.

Would it be possible to extend pattern format to include double-star wildcard that matches anything including slashes ?

Like: **/whatever/**

Many tools (in java at least) and libraries support such extension to globs. Unfortunately standard fnmatch(3) that's used by git is not one of them, but glibc's implementation looks portable and self-contained so it could be included and modified.

Quoted 23 lines
Quoted 2 lines

d2/
d2

These shouldn't for the same reason.

Quoted 2 lines

d1/d2
/d1/d2

We somehow don't do leading path match like we do for gitignore, but I do not think this was intended. My gut feeling is that these should match.

The thinking back, when we wrote the code, could have been that, unlike gitignore that maintains only one bit (either "ignored" or "not"), attributes are richer and giving the same attribute (say "whitespace checking criteria") to files inside a directory and the containing directory itself was nonsensical. But if that was the reason, it is faulty, as we do not track directories anyway.

Wouldn't it be sufficient to teach attr.c:path_matches() that a pattern could also match with leading path? That would automatically cover the case where a pattern is terminated with a slash, as pattern "d/e/" would never match path "d/e" but does match "d/e/f"?

#5 lore raw
In reply to Nguyễn Thái Ngọc Duy
Quoted 6 lines · Nguyễn Thái Ngọc Duy

gitattr and .gitignore are supposed to use the same rules for matching patterns. Unfortunately it's not exactly the same in reality. Mention the differences so users won't be surprised, until gitattr gets updates.

(quoted diff) +0 -0
Quoted 9 lines

b/Documentation/gitattributes.txt index 5a7f936..cfaf107 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -56,6 +56,7 @@ When more than one pattern matches the path, a later line
overrides an earlier line. This overriding is done per attribute. The rules how the pattern matches paths are the same as in .gitignore files; see linkgit:gitignore[5].
+However patterns that end with a slash is not supported.

I'm afraid that is not all. The rules I've inferred:

1. No pattern will match directory tree.
2. It is only possible to match on path components.
3. If pattern contains slash it is treated as absolute.

Example for file: d1/d2/f1.c

Patterns that match:
*.c
d1/d2/*
/d1/d2/*
*/d2/*
*/*/*

Patterns that do not match but should:
d2/*
d2/
d2
d1/d2
/d1/d2