* Change in .gitignore handling: intended or bug? @ 2016-03-04 2:11 Charles Strahan 2016-03-04 3:09 ` Duy Nguyen 2016-03-04 5:51 ` Kevin Daudt 0 siblings, 2 replies; 28+ messages in thread From: Charles Strahan @ 2016-03-04 2:11 UTC (permalink / raw) To: git Hello, I've found a change in the way .gitignore works, and I'm not sure if it's a bug or intended. Previously, one could use the following .gitignore: * !/foo !/foo/bar.txt !/baz !/baz/quux !/baz/quux/**/* And these files would be seen by git: foo/bar.txt baz/quux/grault.txt baz/quux/corge/wibble.txt And these files would be ignored: foo/garply.txt baz/waldo.txt At some point (between git 2.6.0 and 2.7.0, I think), the behavior changed such that _none_ of the files above would be ignored. Previously, git would treat !/foo as an indication that it should not prune /foo, but that _wouldn't_ be sufficient to un-ignore the contents thereof. Now, it seems the new scheme treats !/foo as functionally equivalent to !/foo followed by !/foo/**/* in the old scheme. I manage my home directory by making it a git repo, and using ~/.gitignore to selectively permit certain files or subdirectories to be seen by git. The recent change in behavior has resulted in sensitive directories like ~/.gpg being un-ignored. For reference, I've appended my .gitignore to the end of this email. So, is this behavior intended, or is this a bug? If the former, is there an announcement explaining this change? -Charles (.gitignore is as follows) * !/.Xdefaults !/.Xresources !/.ackrc !/.bash_profile !/.config !/.config/dunst !/.config/dunst/dunstrc !/.config/taffybar !/.config/taffybar/taffybar.hs !/.config/taffybar/taffybar.rc !/.ctags !/.gdb !/.gdb/**/* !/.gdbinit !/.gemrc !/.ghci !/.git_template !/.git_template/**/* !/.gitexcludes !/.gitignore !/.gnupg !/.gnupg/dirmngr.conf !/.gnupg/gpg.conf !/.goobook/ !/.goobook/decipher !/.goobook/decipher/goobookrc !/.inputrc !/.irbrc !/.irssi !/.irssi/**/* !/.mbsyncrc !/.msmtprc !/.mutt !/.mutt/accounts !/.mutt/accounts/* !/.mutt/gpg.rc !/.mutt/mailcap !/.mutt/muttrc !/.mutt/signature !/.mutt/theme/* !/.nixpkgs !/.nixpkgs/**/* !/.notmuch-config !/.pystartup !/.tmux !/.tmux.conf !/.tmux/**/* !/.vim !/.vim/**/* !/.vimrc !/.xmonad !/.xmonad/xmonad.hs !/.xsession !/.zlogin !/.zprofile !/.zsh !/.zsh/**/* !/.zshenv !/.zshrc !/osx ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-04 2:11 Change in .gitignore handling: intended or bug? Charles Strahan @ 2016-03-04 3:09 ` Duy Nguyen 2016-03-04 5:51 ` Kevin Daudt 1 sibling, 0 replies; 28+ messages in thread From: Duy Nguyen @ 2016-03-04 3:09 UTC (permalink / raw) To: Charles Strahan; +Cc: Git Mailing List On Fri, Mar 4, 2016 at 9:11 AM, Charles Strahan <charles@cstrahan.com> wrote: > Hello, > > I've found a change in the way .gitignore works, and I'm not sure if > it's a bug > or intended. Can't look into this just yet. Quick question, what's the git version you're currently running? -- Duy ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-04 2:11 Change in .gitignore handling: intended or bug? Charles Strahan 2016-03-04 3:09 ` Duy Nguyen @ 2016-03-04 5:51 ` Kevin Daudt 2016-03-04 6:12 ` Charles Strahan 1 sibling, 1 reply; 28+ messages in thread From: Kevin Daudt @ 2016-03-04 5:51 UTC (permalink / raw) To: Charles Strahan; +Cc: git On Thu, Mar 03, 2016 at 09:11:56PM -0500, Charles Strahan wrote: > Hello, > > I've found a change in the way .gitignore works, and I'm not sure if > it's a bug > or intended. > > Previously, one could use the following .gitignore: > > * > !/foo > !/foo/bar.txt > !/baz > !/baz/quux > !/baz/quux/**/* > > And these files would be seen by git: > > foo/bar.txt > baz/quux/grault.txt > baz/quux/corge/wibble.txt > > And these files would be ignored: > > foo/garply.txt > baz/waldo.txt > > At some point (between git 2.6.0 and 2.7.0, I think), the behavior > changed such > that _none_ of the files above would be ignored. Previously, git would > treat > !/foo as an indication that it should not prune /foo, but that > _wouldn't_ be > sufficient to un-ignore the contents thereof. Now, it seems the new > scheme > treats !/foo as functionally equivalent to !/foo followed by !/foo/**/* > in the > old scheme. > > I manage my home directory by making it a git repo, and using > ~/.gitignore to > selectively permit certain files or subdirectories to be seen by git. > The recent > change in behavior has resulted in sensitive directories like ~/.gpg > being > un-ignored. For reference, I've appended my .gitignore to the end of > this email. > > So, is this behavior intended, or is this a bug? If the former, is there > an > announcement explaining this change? > > -Charles > > [snip] > -- > To unsubscribe from this list: send the line "unsubscribe git" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html Works as intended for me: ├── baz │ ├── quux │ │ ├── corge │ │ │ └── wibble.txt │ │ └── grault.txt │ └── waldo.txt └── foo ├── bar.txt └── garply.txt $ git status -s -uall ?? baz/quux/corge/wibble.txt ?? baz/quux/grault.txt ?? foo/bar.txt garply.txt and waldo.txt are ignore, but the rest is still tracked. I'm on 2.7.2. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-04 5:51 ` Kevin Daudt @ 2016-03-04 6:12 ` Charles Strahan 2016-03-04 11:56 ` Kevin Daudt 0 siblings, 1 reply; 28+ messages in thread From: Charles Strahan @ 2016-03-04 6:12 UTC (permalink / raw) To: Kevin Daudt; +Cc: git I'm on 2.7.0. Here's a quick sanity check: ├── baz │ ├── quux │ │ ├── corge │ │ │ └── wibble.txt │ │ └── grault.txt │ └── waldo.txt └── foo ├── bar.txt └── garply.txt $ git --version git version 2.7.0 $ git status -sb -uall ## Initial commit on master ?? baz/quux/corge/wibble.txt ?? baz/quux/grault.txt ?? baz/waldo.txt ?? foo/bar.txt ?? foo/garply.txt For the lazy (such as myself), this will set up an identical tree: mkdir -p foo mkdir -p baz/quux/corge touch foo/bar.txt touch foo/garply.txt touch baz/waldo.txt touch baz/quux/grault.txt touch baz/quux/corge/wibble.txt cat <<"EOF" > .gitignore * !/foo !/foo/bar.txt !/baz !/baz/quux !/baz/quux/**/* EOF I just checked https://git-scm.com/docs/gitignore and the example at the bottom suggests that this behavior may be expected: $ cat .gitignore # exclude everything except directory foo/bar /* !/foo /foo/* !/foo/bar Note the /foo/*, explicitly ignoring the entries below /foo. This wasn't always the case, though, so I'd love to hear if it was intentional (or if I've lost my mind, which is quite possible). -Charles On Fri, Mar 4, 2016, at 12:51 AM, Kevin Daudt wrote: > On Thu, Mar 03, 2016 at 09:11:56PM -0500, Charles Strahan wrote: > > Hello, > > > > I've found a change in the way .gitignore works, and I'm not sure if > > it's a bug > > or intended. > > > > Previously, one could use the following .gitignore: > > > > * > > !/foo > > !/foo/bar.txt > > !/baz > > !/baz/quux > > !/baz/quux/**/* > > > > And these files would be seen by git: > > > > foo/bar.txt > > baz/quux/grault.txt > > baz/quux/corge/wibble.txt > > > > And these files would be ignored: > > > > foo/garply.txt > > baz/waldo.txt > > > > At some point (between git 2.6.0 and 2.7.0, I think), the behavior > > changed such > > that _none_ of the files above would be ignored. Previously, git would > > treat > > !/foo as an indication that it should not prune /foo, but that > > _wouldn't_ be > > sufficient to un-ignore the contents thereof. Now, it seems the new > > scheme > > treats !/foo as functionally equivalent to !/foo followed by !/foo/**/* > > in the > > old scheme. > > > > I manage my home directory by making it a git repo, and using > > ~/.gitignore to > > selectively permit certain files or subdirectories to be seen by git. > > The recent > > change in behavior has resulted in sensitive directories like ~/.gpg > > being > > un-ignored. For reference, I've appended my .gitignore to the end of > > this email. > > > > So, is this behavior intended, or is this a bug? If the former, is there > > an > > announcement explaining this change? > > > > -Charles > > > > [snip] > > -- > > To unsubscribe from this list: send the line "unsubscribe git" in > > the body of a message to majordomo@vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > Works as intended for me: > > ├── baz > │ ├── quux > │ │ ├── corge > │ │ │ └── wibble.txt > │ │ └── grault.txt > │ └── waldo.txt > └── foo > ├── bar.txt > └── garply.txt > > $ git status -s -uall > ?? baz/quux/corge/wibble.txt > ?? baz/quux/grault.txt > ?? foo/bar.txt > > garply.txt and waldo.txt are ignore, but the rest is still tracked. > > I'm on 2.7.2. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-04 6:12 ` Charles Strahan @ 2016-03-04 11:56 ` Kevin Daudt 2016-03-04 12:36 ` Duy Nguyen 0 siblings, 1 reply; 28+ messages in thread From: Kevin Daudt @ 2016-03-04 11:56 UTC (permalink / raw) To: Charles Strahan; +Cc: git On Fri, Mar 04, 2016 at 01:12:37AM -0500, Charles Strahan wrote: > I'm on 2.7.0. > > Here's a quick sanity check: > > ├── baz > │ ├── quux > │ │ ├── corge > │ │ │ └── wibble.txt > │ │ └── grault.txt > │ └── waldo.txt > └── foo > ├── bar.txt > └── garply.txt > > $ git --version > git version 2.7.0 > > $ git status -sb -uall > ## Initial commit on master > ?? baz/quux/corge/wibble.txt > ?? baz/quux/grault.txt > ?? baz/waldo.txt > ?? foo/bar.txt > ?? foo/garply.txt > > > For the lazy (such as myself), this will set up an identical tree: > > mkdir -p foo > mkdir -p baz/quux/corge > touch foo/bar.txt > touch foo/garply.txt > touch baz/waldo.txt > touch baz/quux/grault.txt > touch baz/quux/corge/wibble.txt > cat <<"EOF" > .gitignore > * > !/foo > !/foo/bar.txt > !/baz > !/baz/quux > !/baz/quux/**/* > EOF > > > I just checked https://git-scm.com/docs/gitignore and the example at the > bottom > suggests that this behavior may be expected: > > $ cat .gitignore > # exclude everything except directory foo/bar > /* > !/foo > /foo/* > !/foo/bar > > Note the /foo/*, explicitly ignoring the entries below /foo. > > This wasn't always the case, though, so I'd love to hear if it was > intentional > (or if I've lost my mind, which is quite possible). > > -Charles > > > > On Fri, Mar 4, 2016, at 12:51 AM, Kevin Daudt wrote: > > On Thu, Mar 03, 2016 at 09:11:56PM -0500, Charles Strahan wrote: > > > Hello, > > > > > > I've found a change in the way .gitignore works, and I'm not sure if > > > it's a bug > > > or intended. > > > > > > Previously, one could use the following .gitignore: > > > > > > * > > > !/foo > > > !/foo/bar.txt > > > !/baz > > > !/baz/quux > > > !/baz/quux/**/* > > > > > > And these files would be seen by git: > > > > > > foo/bar.txt > > > baz/quux/grault.txt > > > baz/quux/corge/wibble.txt > > > > > > And these files would be ignored: > > > > > > foo/garply.txt > > > baz/waldo.txt > > > > > > At some point (between git 2.6.0 and 2.7.0, I think), the behavior > > > changed such > > > that _none_ of the files above would be ignored. Previously, git would > > > treat > > > !/foo as an indication that it should not prune /foo, but that > > > _wouldn't_ be > > > sufficient to un-ignore the contents thereof. Now, it seems the new > > > scheme > > > treats !/foo as functionally equivalent to !/foo followed by !/foo/**/* > > > in the > > > old scheme. > > > > > > I manage my home directory by making it a git repo, and using > > > ~/.gitignore to > > > selectively permit certain files or subdirectories to be seen by git. > > > The recent > > > change in behavior has resulted in sensitive directories like ~/.gpg > > > being > > > un-ignored. For reference, I've appended my .gitignore to the end of > > > this email. > > > > > > So, is this behavior intended, or is this a bug? If the former, is there > > > an > > > announcement explaining this change? > > > > > > -Charles > > > > > > [snip] > > > -- > > > To unsubscribe from this list: send the line "unsubscribe git" in > > > the body of a message to majordomo@vger.kernel.org > > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > > > Works as intended for me: > > > > ├── baz > > │ ├── quux > > │ │ ├── corge > > │ │ │ └── wibble.txt > > │ │ └── grault.txt > > │ └── waldo.txt > > └── foo > > ├── bar.txt > > └── garply.txt > > > > $ git status -s -uall > > ?? baz/quux/corge/wibble.txt > > ?? baz/quux/grault.txt > > ?? foo/bar.txt > > > > garply.txt and waldo.txt are ignore, but the rest is still tracked. > > > > I'm on 2.7.2. > -- Verified that it's different in 2.7.0, but 2.7.2 gives expected output. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-04 11:56 ` Kevin Daudt @ 2016-03-04 12:36 ` Duy Nguyen 2016-03-04 17:28 ` Junio C Hamano 0 siblings, 1 reply; 28+ messages in thread From: Duy Nguyen @ 2016-03-04 12:36 UTC (permalink / raw) To: Kevin Daudt; +Cc: Charles Strahan, Git Mailing List On Fri, Mar 4, 2016 at 6:56 PM, Kevin Daudt <me@ikke.info> wrote: > Verified that it's different in 2.7.0, but 2.7.2 gives expected output. Thanks. 2.7.1 reverts the faulty commit from 2.7.0 that generated two other regression reports before this one. I guess it's all good then (except for the people still on 2.7.0) -- Duy ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-04 12:36 ` Duy Nguyen @ 2016-03-04 17:28 ` Junio C Hamano 2016-03-04 19:12 ` Junio C Hamano 2016-03-05 0:43 ` Duy Nguyen 0 siblings, 2 replies; 28+ messages in thread From: Junio C Hamano @ 2016-03-04 17:28 UTC (permalink / raw) To: Duy Nguyen; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List Duy Nguyen <pclouds@gmail.com> writes: > On Fri, Mar 4, 2016 at 6:56 PM, Kevin Daudt <me@ikke.info> wrote: >> Verified that it's different in 2.7.0, but 2.7.2 gives expected output. > > Thanks. 2.7.1 reverts the faulty commit from 2.7.0 that generated two > other regression reports before this one. I guess it's all good then > (except for the people still on 2.7.0) Are we good at 2.8.0-rc0, too? Somehow I had an impression that we queued "another attempt to do it differently" or something. ... goes and looks ... $ rungit maint status -suall ?? baz/quux/corge/wibble.txt ?? baz/quux/grault.txt ?? foo/bar.txt $ rungit master status -suall ?? baz/quux/corge/wibble.txt ?? baz/quux/grault.txt ?? baz/waldo.txt ?? foo/bar.txt ?? foo/garply.txt ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-04 17:28 ` Junio C Hamano @ 2016-03-04 19:12 ` Junio C Hamano 2016-03-05 0:43 ` Duy Nguyen 1 sibling, 0 replies; 28+ messages in thread From: Junio C Hamano @ 2016-03-04 19:12 UTC (permalink / raw) To: Duy Nguyen; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List Junio C Hamano <gitster@pobox.com> writes: > Duy Nguyen <pclouds@gmail.com> writes: > >> On Fri, Mar 4, 2016 at 6:56 PM, Kevin Daudt <me@ikke.info> wrote: >>> Verified that it's different in 2.7.0, but 2.7.2 gives expected output. >> >> Thanks. 2.7.1 reverts the faulty commit from 2.7.0 that generated two >> other regression reports before this one. I guess it's all good then >> (except for the people still on 2.7.0) > > Are we good at 2.8.0-rc0, too? Somehow I had an impression that we > queued "another attempt to do it differently" or something. > > ... goes and looks ... > > $ rungit maint status -suall > ?? baz/quux/corge/wibble.txt > ?? baz/quux/grault.txt > ?? foo/bar.txt > $ rungit master status -suall > ?? baz/quux/corge/wibble.txt > ?? baz/quux/grault.txt > ?? baz/waldo.txt > ?? foo/bar.txt > ?? foo/garply.txt It seems to bisect down to this one between maint..master: commit a60ea8fb66945a886ea53fd3f41e61cc5fb3201e Author: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Date: Mon Feb 15 16:03:36 2016 +0700 dir.c: fix match_pathname() Given the pattern "1/2/3/4" and the path "1/2/3/4/f", the pattern prefix is "1/2/3/4". We will compare and remove the prefix from both pattern and path and come to this code /* * If the whole pattern did not have a wildcard, * then our prefix match is all we need; we * do not need to call fnmatch at all. */ if (!patternlen && !namelen) return 1; where patternlen is zero (full pattern consumed) and the remaining path in "name" is "/f". We fail to realize it's matched in this case and fall back to fnmatch(), which also fails to catch it. Fix it. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> But I do not think this change alone is the culprit; the change itself does make sense in the context of the series. At this point, we have two choices. Either we revert the merge of the whole series: commit 5e57f9c3dfe7dd44a1b56bb5b3327d7a1356ec7c Merge: e79112d d589a67 Author: Junio C Hamano <gitster@pobox.com> Date: Wed Feb 24 13:25:59 2016 -0800 Merge branch 'nd/exclusion-regression-fix' Another try to add support to the ignore mechanism that lets you say "this is excluded" and then later say "oh, no, this part (that is a subset of the previous part) is not excluded". * nd/exclusion-regression-fix: dir.c: don't exclude whole dir prematurely dir.c: support marking some patterns already matched dir.c: support tracing exclude dir.c: fix match_pathname() to go back to the 2.7.2 behaviour, or add a follow-on change to the nd/exclusion-regression-fix topic to fix what it wanted to fix without breaking Charles's use case. I am inclined to go for the former (unless the follow-on fix is really trivial), but I haven't dug into the codebase myself yet, so... ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-04 17:28 ` Junio C Hamano 2016-03-04 19:12 ` Junio C Hamano @ 2016-03-05 0:43 ` Duy Nguyen 2016-03-05 0:50 ` Duy Nguyen 2016-03-07 21:11 ` Junio C Hamano 1 sibling, 2 replies; 28+ messages in thread From: Duy Nguyen @ 2016-03-05 0:43 UTC (permalink / raw) To: Junio C Hamano; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List On Sat, Mar 5, 2016 at 12:28 AM, Junio C Hamano <gitster@pobox.com> wrote: > Duy Nguyen <pclouds@gmail.com> writes: > >> On Fri, Mar 4, 2016 at 6:56 PM, Kevin Daudt <me@ikke.info> wrote: >>> Verified that it's different in 2.7.0, but 2.7.2 gives expected output. >> >> Thanks. 2.7.1 reverts the faulty commit from 2.7.0 that generated two >> other regression reports before this one. I guess it's all good then >> (except for the people still on 2.7.0) > > Are we good at 2.8.0-rc0, too? Somehow I had an impression that we > queued "another attempt to do it differently" or something. > > ... goes and looks ... > > $ rungit maint status -suall > ?? baz/quux/corge/wibble.txt > ?? baz/quux/grault.txt > ?? foo/bar.txt > $ rungit master status -suall > ?? baz/quux/corge/wibble.txt > ?? baz/quux/grault.txt > ?? baz/waldo.txt > ?? foo/bar.txt > ?? foo/garply.txt If you swap a60ea8f and bac65a2 so that we can have tracing even without the problematic commit a60ea8f (dir.c: fix match_pathname() - 2016-02-15). Without a60ea8f I got GIT_TRACE_EXCLUDE=1 ~/w/git/temp/git status -suall 2>&1 >/dev/null |grep waldo 07:25:05.639445 dir.c:952 exclude: baz/waldo.txt vs * at line 1 => yes (meaning, baz/waldo.txt matches "*" rule and is decided to be excluded) with a60ea8f > /tmp/abc $ GIT_TRACE_EXCLUDE=1 ~/w/git/temp/git status -suall 2>&1 >/dev/null |grep waldo 07:25:24.425125 dir.c:952 exclude: baz/waldo.txt vs /baz at line 4 => no the decision is not taken earlier from line "!/baz" and it's decided to be re-included. Which I would argue is the correct thing because you ask to re-include the whole directory "baz". It should behave this way because exclude rules without '!' behave this way. Because positive any negative rules can be nested, by adding a rule to reinclude what's inside baz.. * !/foo !/foo/bar.txt !/baz /baz/* !/baz/quux !/baz/quux/**/* you'll get baz/waldo.txt excluded. Yes it's a behavior change. I think the old behavior is unintended. But it's probably out there long enough that many .gitignore files may rely on it and by making it right, I break them. Whether to revert the series is up to you. Let me know if I should send the revert patch. -- Duy ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-05 0:43 ` Duy Nguyen @ 2016-03-05 0:50 ` Duy Nguyen 2016-03-05 1:00 ` Charles Strahan 2016-03-07 21:11 ` Junio C Hamano 1 sibling, 1 reply; 28+ messages in thread From: Duy Nguyen @ 2016-03-05 0:50 UTC (permalink / raw) To: Junio C Hamano; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List typo fixes On Sat, Mar 5, 2016 at 7:43 AM, Duy Nguyen <pclouds@gmail.com> wrote: > On Sat, Mar 5, 2016 at 12:28 AM, Junio C Hamano <gitster@pobox.com> wrote: >> Duy Nguyen <pclouds@gmail.com> writes: >> >>> On Fri, Mar 4, 2016 at 6:56 PM, Kevin Daudt <me@ikke.info> wrote: >>>> Verified that it's different in 2.7.0, but 2.7.2 gives expected output. >>> >>> Thanks. 2.7.1 reverts the faulty commit from 2.7.0 that generated two >>> other regression reports before this one. I guess it's all good then >>> (except for the people still on 2.7.0) >> >> Are we good at 2.8.0-rc0, too? Somehow I had an impression that we >> queued "another attempt to do it differently" or something. >> >> ... goes and looks ... >> >> $ rungit maint status -suall >> ?? baz/quux/corge/wibble.txt >> ?? baz/quux/grault.txt >> ?? foo/bar.txt >> $ rungit master status -suall >> ?? baz/quux/corge/wibble.txt >> ?? baz/quux/grault.txt >> ?? baz/waldo.txt >> ?? foo/bar.txt >> ?? foo/garply.txt > > If you swap a60ea8f and bac65a2 so that we can have tracing even > without the problematic commit a60ea8f (dir.c: fix match_pathname() - > 2016-02-15). Without a60ea8f I got > > GIT_TRACE_EXCLUDE=1 ~/w/git/temp/git status -suall 2>&1 >/dev/null > |grep waldo > 07:25:05.639445 dir.c:952 exclude: baz/waldo.txt vs * at > line 1 => yes > > (meaning, baz/waldo.txt matches "*" rule and is decided to be excluded) > > with a60ea8f > >> /tmp/abc $ GIT_TRACE_EXCLUDE=1 ~/w/git/temp/git status -suall 2>&1 >/dev/null |grep waldo > 07:25:24.425125 dir.c:952 exclude: baz/waldo.txt vs /baz > at line 4 => no > > the decision is not taken earlier from line "!/baz" and it's decided s/not taken/taken/ > to be re-included. Which I would argue is the correct thing because > you ask to re-include the whole directory "baz". It should behave this > way because exclude rules without '!' behave this way. > > Because positive any negative rules can be nested, by adding a rule to s/any/and/ > reinclude what's inside baz.. > > * > !/foo > !/foo/bar.txt > !/baz > /baz/* > !/baz/quux > !/baz/quux/**/* > > you'll get baz/waldo.txt excluded. > > Yes it's a behavior change. I think the old behavior is unintended. > But it's probably out there long enough that many .gitignore files may > rely on it and by making it right, I break them. Whether to revert the > series is up to you. Let me know if I should send the revert patch. > -- > Duy -- Duy ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-05 0:50 ` Duy Nguyen @ 2016-03-05 1:00 ` Charles Strahan 2016-03-05 1:35 ` Junio C Hamano 0 siblings, 1 reply; 28+ messages in thread From: Charles Strahan @ 2016-03-05 1:00 UTC (permalink / raw) To: Duy Nguyen, Junio C Hamano; +Cc: Kevin Daudt, Git Mailing List The fix on my side was quite easy (and my .gitignore is probably a _lot_ hairier than most), and as Duy suggests, I think the new behavior makes a bit more sense. Personally, I would be pleased with keeping the new behavior, and chalking it up to an unintentional bug fix (the best kind). Either way, of course, I'd like for it to not change back and forth between releases :). Perhaps just an announcement of the new behavior would suffice - 2.7.0 has been out for a while anyway. If people were going to complain, I figure they would have done so by now. -Charles On Fri, Mar 4, 2016, at 07:50 PM, Duy Nguyen wrote: > typo fixes > > On Sat, Mar 5, 2016 at 7:43 AM, Duy Nguyen <pclouds@gmail.com> wrote: > > On Sat, Mar 5, 2016 at 12:28 AM, Junio C Hamano <gitster@pobox.com> wrote: > >> Duy Nguyen <pclouds@gmail.com> writes: > >> > >>> On Fri, Mar 4, 2016 at 6:56 PM, Kevin Daudt <me@ikke.info> wrote: > >>>> Verified that it's different in 2.7.0, but 2.7.2 gives expected output. > >>> > >>> Thanks. 2.7.1 reverts the faulty commit from 2.7.0 that generated two > >>> other regression reports before this one. I guess it's all good then > >>> (except for the people still on 2.7.0) > >> > >> Are we good at 2.8.0-rc0, too? Somehow I had an impression that we > >> queued "another attempt to do it differently" or something. > >> > >> ... goes and looks ... > >> > >> $ rungit maint status -suall > >> ?? baz/quux/corge/wibble.txt > >> ?? baz/quux/grault.txt > >> ?? foo/bar.txt > >> $ rungit master status -suall > >> ?? baz/quux/corge/wibble.txt > >> ?? baz/quux/grault.txt > >> ?? baz/waldo.txt > >> ?? foo/bar.txt > >> ?? foo/garply.txt > > > > If you swap a60ea8f and bac65a2 so that we can have tracing even > > without the problematic commit a60ea8f (dir.c: fix match_pathname() - > > 2016-02-15). Without a60ea8f I got > > > > GIT_TRACE_EXCLUDE=1 ~/w/git/temp/git status -suall 2>&1 >/dev/null > > |grep waldo > > 07:25:05.639445 dir.c:952 exclude: baz/waldo.txt vs * at > > line 1 => yes > > > > (meaning, baz/waldo.txt matches "*" rule and is decided to be excluded) > > > > with a60ea8f > > > >> /tmp/abc $ GIT_TRACE_EXCLUDE=1 ~/w/git/temp/git status -suall 2>&1 >/dev/null |grep waldo > > 07:25:24.425125 dir.c:952 exclude: baz/waldo.txt vs /baz > > at line 4 => no > > > > the decision is not taken earlier from line "!/baz" and it's decided > > s/not taken/taken/ > > > to be re-included. Which I would argue is the correct thing because > > you ask to re-include the whole directory "baz". It should behave this > > way because exclude rules without '!' behave this way. > > > > Because positive any negative rules can be nested, by adding a rule to > > s/any/and/ > > > reinclude what's inside baz.. > > > > * > > !/foo > > !/foo/bar.txt > > !/baz > > /baz/* > > !/baz/quux > > !/baz/quux/**/* > > > > you'll get baz/waldo.txt excluded. > > > > Yes it's a behavior change. I think the old behavior is unintended. > > But it's probably out there long enough that many .gitignore files may > > rely on it and by making it right, I break them. Whether to revert the > > series is up to you. Let me know if I should send the revert patch. > > -- > > Duy > > > > -- > Duy ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-05 1:00 ` Charles Strahan @ 2016-03-05 1:35 ` Junio C Hamano 0 siblings, 0 replies; 28+ messages in thread From: Junio C Hamano @ 2016-03-05 1:35 UTC (permalink / raw) To: Charles Strahan; +Cc: Duy Nguyen, Kevin Daudt, Git Mailing List Charles Strahan <charles@cstrahan.com> writes: > ...as Duy suggests, I think the new behavior makes a bit > more sense. After re-reading your original example, I am inclined to agree with this. > Either way, of course, I'd like for it to not change back and > forth between releases :). > > Perhaps just an announcement of the new behavior would suffice - > 2.7.0 has been out for a while anyway. If people were going to > complain, I figure they would have done so by now. Yup, I think a documentation update to clarify how positive and negative ignore patterns interact with each other may be necessary, with some examples. Care to work on a patch? Thanks. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-05 0:43 ` Duy Nguyen 2016-03-05 0:50 ` Duy Nguyen @ 2016-03-07 21:11 ` Junio C Hamano 2016-03-08 6:14 ` Junio C Hamano 1 sibling, 1 reply; 28+ messages in thread From: Junio C Hamano @ 2016-03-07 21:11 UTC (permalink / raw) To: Duy Nguyen; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List Duy Nguyen <pclouds@gmail.com> writes: > On Sat, Mar 5, 2016 at 12:28 AM, Junio C Hamano <gitster@pobox.com> wrote: > >> Are we good at 2.8.0-rc0, too? Somehow I had an impression that we >> queued "another attempt to do it differently" or something. >> >> ... goes and looks ... >> >> $ rungit maint status -suall >> ?? baz/quux/corge/wibble.txt >> ?? baz/quux/grault.txt >> ?? foo/bar.txt >> $ rungit master status -suall >> ?? baz/quux/corge/wibble.txt >> ?? baz/quux/grault.txt >> ?? baz/waldo.txt >> ?? foo/bar.txt >> ?? foo/garply.txt > ... > the decision is not taken earlier from line "!/baz" and it's decided > to be re-included. Which I would argue is the correct thing because > you ask to re-include the whole directory "baz". It should behave this > way because exclude rules without '!' behave this way. We need documentation update to settle this one before 2.8 final ships, as we seem to be seeing more and more end-user confusion on the list. I tried to come up with a trimmed-down example, which is shown below, but I suspect that the code is not exactly working the way it is described in that (1) dir/file1 is ignored and (3) !dir/file3 entry makes difference. Where did my example go wrong? FYI, if I prefix '/' to all the .gitignore entries in the example, i.e. making it * !/dir /dir/file2 !/dir/file3 instead, then dir/file1 and dir/file3 do get shown as unignored. If it is documented somewhere, then I can update the example and declare victory (but then the text that accompanies the example still needs to remind the readers why the leading '/' matters. Thanks. Documentation/gitignore.txt | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt index 3ded6fd..b841233 100644 --- a/Documentation/gitignore.txt +++ b/Documentation/gitignore.txt @@ -150,6 +150,40 @@ excluded, the following conditions must be met: - The directory part in the re-include rules must be literal (i.e. no wildcards) +A re-inclusion of a directory makes all files in the directory +unignored. For example, suppose you have files `.gitignore`, +`dir/file1`, `dir/file2`, and `dir/file3`, and have the following in +your `.gitignore`: + +---------------- +* +!dir +# dir/file1 is not mentioned in .gitignore +dir/file2 +!dir/file3 +---------------- + +Then: + + - `.gitignore` gets ignored, because it matches the `*` at the top + level; + + - `dir/file1` gets unignored, because `dir` marks everything + underneath `dir/` to be unignored unless otherwise specified; + + - `dir/file2` gets ignored, because `dir/file2` is listed to be + ignored; + + - `dir/file3` gets unignored, because `dir/file3` is listed to be + ignored. Note that the entry `!dir/file3` is redundant because + everything underneath `dir/` is marked to be unignored already. + +Some earlier versions of Git treated `!dir` differently in that it +did not cause the paths under it unignored, but this has been +corrected to be consistent with `dir` that says "`dir` and everything +below are ignored." + + EXAMPLES -------- ^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-07 21:11 ` Junio C Hamano @ 2016-03-08 6:14 ` Junio C Hamano 2016-03-08 10:19 ` Duy Nguyen 0 siblings, 1 reply; 28+ messages in thread From: Junio C Hamano @ 2016-03-08 6:14 UTC (permalink / raw) To: Duy Nguyen; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List Junio C Hamano <gitster@pobox.com> writes: > We need documentation update to settle this one before 2.8 final > ships, as we seem to be seeing more and more end-user confusion on > the list. I tried to come up with a trimmed-down example, which is > shown below, but I suspect that the code is not exactly working the > way it is described in that (1) dir/file1 is ignored and (3) > !dir/file3 entry makes difference. > > Where did my example go wrong? > > FYI, if I prefix '/' to all the .gitignore entries in the example, i.e. > making it > > * > !/dir > /dir/file2 > !/dir/file3 > > instead, then dir/file1 and dir/file3 do get shown as unignored. > > If it is documented somewhere, then I can update the example and > declare victory (but then the text that accompanies the example > still needs to remind the readers why the leading '/' matters. I also found that having an extra slash at the end of the "everything underneath 'dir' directory is included", i.e. * !/dir/ /dir/file2 !/dir/file3 breaks it. dir/file1 is ignored, dir/file3 isn't but the latter is only because there is an explicit !/dir/file3. This is contrary to this rule in the documentation: - If the pattern ends with a slash, it is removed for the purpose of the following description, but it would only find a match with a directory. In other words, `foo/` will match a directory `foo` and paths underneath it, but will not match a regular file or a symbolic link `foo` (this is consistent with the way how pathspec works in general in Git). In other words, '!/dir/' does not seem to match the directory dir and paths underneath it. Thanks. > Documentation/gitignore.txt | 34 ++++++++++++++++++++++++++++++++++ > 1 file changed, 34 insertions(+) > > diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt > index 3ded6fd..b841233 100644 > --- a/Documentation/gitignore.txt > +++ b/Documentation/gitignore.txt > @@ -150,6 +150,40 @@ excluded, the following conditions must be met: > - The directory part in the re-include rules must be literal (i.e. no > wildcards) > > +A re-inclusion of a directory makes all files in the directory > +unignored. For example, suppose you have files `.gitignore`, > +`dir/file1`, `dir/file2`, and `dir/file3`, and have the following in > +your `.gitignore`: > + > +---------------- > +* > +!dir > +# dir/file1 is not mentioned in .gitignore > +dir/file2 > +!dir/file3 > +---------------- > + > +Then: > + > + - `.gitignore` gets ignored, because it matches the `*` at the top > + level; > + > + - `dir/file1` gets unignored, because `dir` marks everything > + underneath `dir/` to be unignored unless otherwise specified; > + > + - `dir/file2` gets ignored, because `dir/file2` is listed to be > + ignored; > + > + - `dir/file3` gets unignored, because `dir/file3` is listed to be > + ignored. Note that the entry `!dir/file3` is redundant because > + everything underneath `dir/` is marked to be unignored already. > + > +Some earlier versions of Git treated `!dir` differently in that it > +did not cause the paths under it unignored, but this has been > +corrected to be consistent with `dir` that says "`dir` and everything > +below are ignored." > + > + > EXAMPLES > -------- > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-08 6:14 ` Junio C Hamano @ 2016-03-08 10:19 ` Duy Nguyen 2016-03-08 18:10 ` Junio C Hamano 0 siblings, 1 reply; 28+ messages in thread From: Duy Nguyen @ 2016-03-08 10:19 UTC (permalink / raw) To: Junio C Hamano; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List On Tue, Mar 8, 2016 at 1:14 PM, Junio C Hamano <gitster@pobox.com> wrote: > Junio C Hamano <gitster@pobox.com> writes: > >> We need documentation update to settle this one before 2.8 final >> ships, as we seem to be seeing more and more end-user confusion on >> the list. I tried to come up with a trimmed-down example, which is >> shown below, but I suspect that the code is not exactly working the >> way it is described in that (1) dir/file1 is ignored and (3) >> !dir/file3 entry makes difference. >> >> Where did my example go wrong? >> >> FYI, if I prefix '/' to all the .gitignore entries in the example, i.e. >> making it >> >> * >> !/dir >> /dir/file2 >> !/dir/file3 >> >> instead, then dir/file1 and dir/file3 do get shown as unignored. Arghhh.. bug!!! The difference between "dir" and "/dir" is, the former is basename matching while the latter is pathname matching. When we check dir/file1 after we enter "dir", we do try to check rule "!/dir" (or "!dir") before rule "*". In the pathname matching case, it works thanks to a60ea8f. In the basename matching case (i.e. rule "!dir"), the code does not do the right thing. It blindly checks the base name of dir/file1, which is "file1", against the pattern "dir". The right thing to do is check the "dir" in "dir/file1" part against pattern "dir". Failing that, we fall back to pattern "*" and excludes dir/file1 as well. >> If it is documented somewhere, then I can update the example and >> declare victory (but then the text that accompanies the example >> still needs to remind the readers why the leading '/' matters. > > I also found that having an extra slash at the end of the > "everything underneath 'dir' directory is included", i.e. > > * > !/dir/ > /dir/file2 > !/dir/file3 > > breaks it. dir/file1 is ignored, dir/file3 isn't but the latter is > only because there is an explicit !/dir/file3. This is contrary to > this rule in the documentation: This is pretty much the same. But instead basename matching unable to deal with nested rules, the trailing slash means "check if it is a directory". Again, the code tries to check if "dir/file1" is a directory instead of "dir". I haven't dug back in history, but my impression is it has been so probably from the beginning of "!" introduction. This has nothing to do with nd/exclusion-regression-fix, which is more about dir !dir/file than !dir dir/file Although the first patch in that series happens to fix the pathname matching case in this example. I don't know. It seems to me I should fix this anyway, by making both "NODIR" and "MUSTBEDIR" code work well inside a directory. That should fix it. I hope I don't have to turn dir.c up side down for that. Last time I looked, it wasn't easy, which led to hack/avoid it with 57534ee and that was eventually reverted. -- Duy ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-08 10:19 ` Duy Nguyen @ 2016-03-08 18:10 ` Junio C Hamano 2016-03-09 0:18 ` Duy Nguyen 2016-03-09 9:48 ` Change in .gitignore handling: intended or bug? Duy Nguyen 0 siblings, 2 replies; 28+ messages in thread From: Junio C Hamano @ 2016-03-08 18:10 UTC (permalink / raw) To: Duy Nguyen; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List Duy Nguyen <pclouds@gmail.com> writes: > On Tue, Mar 8, 2016 at 1:14 PM, Junio C Hamano <gitster@pobox.com> wrote: >> Junio C Hamano <gitster@pobox.com> writes: >> >>> We need documentation update to settle this one before 2.8 final >>> ships, as we seem to be seeing more and more end-user confusion on >>> the list. I tried to come up with a trimmed-down example, which is >>> shown below, but I suspect that the code is not exactly working the >>> way it is described in that (1) dir/file1 is ignored and (3) >>> !dir/file3 entry makes difference. >>> >>> Where did my example go wrong? >>> >>> FYI, if I prefix '/' to all the .gitignore entries in the example, i.e. >>> making it >>> >>> * >>> !/dir >>> /dir/file2 >>> !/dir/file3 >>> >>> instead, then dir/file1 and dir/file3 do get shown as unignored. > > Arghhh.. bug!!! > > The difference between "dir" and "/dir" is, the former is basename > matching while the latter is pathname matching. When we check > dir/file1 after we enter "dir", we do try to check rule "!/dir" (or > "!dir") before rule "*". In the pathname matching case, it works > thanks to a60ea8f. So what do we want to do for the upcoming release? I am OK to leave the code as-is for now and describe it as a known bug that is still being worked on (as long as it indeed is being worked on, that is), as the desired endgame of making "!dir" act in a way more similar to how "dir" acts does sound sensible. If we are going that route, perhaps something like this is the minimum we would need before 2.8 final. Thoughts? Documentation/gitignore.txt | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt index 3ded6fd..91d1ce2 100644 --- a/Documentation/gitignore.txt +++ b/Documentation/gitignore.txt @@ -148,7 +148,43 @@ excluded, the following conditions must be met: be in the same .gitignore file. - The directory part in the re-include rules must be literal (i.e. no - wildcards) + wildcards and has to start with a `/`). + +A re-inclusion of a directory makes all files in the directory +unignored. For example, suppose you have files `.gitignore`, +`dir/file1`, `dir/file2`, and `dir/file3`, and have the following in +your `.gitignore`: + +---------------- +# .gitignore is not mentioned in .gitignore +* +!/dir +# dir/file1 is not mentioned in .gitignore +dir/file2 +!dir/file3 +---------------- + +Then: + + - `.gitignore` gets ignored, because it matches the `*` at the top + level; + + - `dir/file1` does not get ignored, because `/dir` marks everything + underneath `dir/` directory to be 're-included' unless otherwise + specified; + + - `dir/file2` gets ignored, because `dir/file2` matches it. + + - `dir/file3` does not get ignored, because `!dir/file3` matches it. + Note that the entry `!dir/file3` is redundant because everything + underneath `dir/` is marked to be 're-included' already. + +Some earlier versions of Git treated `!/dir` above differently in +that it did not cause the paths under it unignored (but merely told +Git that patterns that begin with dir/ should not be ignored), but +this has been corrected to be consistent with `/dir` that says "the +directory `dir/` and everything below are ignored." + EXAMPLES -------- ^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-08 18:10 ` Junio C Hamano @ 2016-03-09 0:18 ` Duy Nguyen 2016-03-09 0:32 ` Junio C Hamano 2016-03-09 9:48 ` Change in .gitignore handling: intended or bug? Duy Nguyen 1 sibling, 1 reply; 28+ messages in thread From: Duy Nguyen @ 2016-03-09 0:18 UTC (permalink / raw) To: Junio C Hamano; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List On Wed, Mar 9, 2016 at 1:10 AM, Junio C Hamano <gitster@pobox.com> wrote: > So what do we want to do for the upcoming release? I don't know. Befoire 2.8.0, all three matching cases are broken. With the current changes on 2.8.0, one case is fixed with the other cases broken. I guess it can create even more confusion. Yeah documentation helps a bit. > I am OK to leave > the code as-is for now and describe it as a known bug that is still > being worked on (as long as it indeed is being worked on, that is), I do want to fix it. I don't know how much code is impacted yet (and how many more bugs I'll be introducing while attempting to fix it). It may take a few cycles before the fix can be released. -- Duy ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-09 0:18 ` Duy Nguyen @ 2016-03-09 0:32 ` Junio C Hamano 2016-03-09 0:45 ` Junio C Hamano 0 siblings, 1 reply; 28+ messages in thread From: Junio C Hamano @ 2016-03-09 0:32 UTC (permalink / raw) To: Duy Nguyen; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List Duy Nguyen <pclouds@gmail.com> writes: > On Wed, Mar 9, 2016 at 1:10 AM, Junio C Hamano <gitster@pobox.com> wrote: >> So what do we want to do for the upcoming release? > > I don't know. Befoire 2.8.0, all three matching cases are broken. With > the current changes on 2.8.0, one case is fixed with the other cases > broken. I guess it can create even more confusion. Yeah documentation > helps a bit. > >> I am OK to leave >> the code as-is for now and describe it as a known bug that is still >> being worked on (as long as it indeed is being worked on, that is), > > I do want to fix it. I don't know how much code is impacted yet (and > how many more bugs I'll be introducing while attempting to fix it). It > may take a few cycles before the fix can be released. Sorry, but I should have been more clear. At this point in the release cycle, I do not think it is an option to pile on more "fixes" to risk destabilizing the end-user experience even more before 2.8.0 final happens. It is between (1) the current code is good enough that with a (temporary) limitation clearly described in the documentation users can work around the implementation deficiency and get a benaviour that is closer than 2.7.2, or (2) the half-way implementation we have does not give enough advancement toward the final goal (i.e. the !dir re-inclusion behaves consistently with the dir that ignores the whole thing underneath, while allowing subpaths ignored with follow-on entries in the same .gitignore file), and we are better off reverting the whole thing to go back to 2.7.2 behaviour, planning to do a better job in the next cycle. I was hoping that (1) would be the case. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-09 0:32 ` Junio C Hamano @ 2016-03-09 0:45 ` Junio C Hamano 2016-03-09 11:08 ` [PATCH] dir.c: fix dir re-inclusion rules with "NODIR" and "MUSTBEDIR" Nguyễn Thái Ngọc Duy 0 siblings, 1 reply; 28+ messages in thread From: Junio C Hamano @ 2016-03-09 0:45 UTC (permalink / raw) To: Duy Nguyen; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List Junio C Hamano <gitster@pobox.com> writes: > It is between (1) the current code is good enough ... > or (2) the half-way implementation we > have does not give enough advancement ... and we > are better off reverting the whole thing to go back to 2.7.2 > behaviour, planning to do a better job in the next cycle. > > I was hoping that (1) would be the case. Oh and of course I still am--otherwise I wouldn't have been attempting these documentation updates. I just wanted to make sure that I covered most (if not all) of the corner cases that we know the current code does not work by documenting workarounds. ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH] dir.c: fix dir re-inclusion rules with "NODIR" and "MUSTBEDIR" 2016-03-09 0:45 ` Junio C Hamano @ 2016-03-09 11:08 ` Nguyễn Thái Ngọc Duy 2016-03-09 17:55 ` Junio C Hamano 0 siblings, 1 reply; 28+ messages in thread From: Nguyễn Thái Ngọc Duy @ 2016-03-09 11:08 UTC (permalink / raw) To: git Cc: Junio C Hamano, Kevin Daudt, Charles Strahan, Nguyễn Thái Ngọc Duy For NODIR case, the patterns look like this * # exclude dir, dir/file1 and dir/file2.. !dir # ..except that dir and everything inside is re-included.. dir/file2 # ..except (again!) that dir/file2 is excluded # ..which means dir/file1 stays included When we stay at topdir and test "dir", everything is hunky dory, current code returns "re-include dir" as expected. When we stay in "dir" and examine "dir/file1", however, match_basename() checks if the base name component, which is "file1", matches "dir" from the second rule. This is wrong. We contradict ourselves because earlier we decided to re-include dir/file1 (from the second rule) when we were at toplevel. Because the second rule is ignored, we hit the first one and return "excluded" even though "dir/file1" should be re-included. Side note, it's probably a bad idea to use basename matching on a negative rule (ie. no slashes in the pattern) because what the pattern says is "re-include _any_ directory named 'dir'", not just the directory "dir" at right below this directory. In the MUSTBEDIR case, the patterns look like this * # exclude dir, dir/file1 and dir/file2.. !dir/ # ..except that dir and everything inside is re-included.. dir/file2 # ..except (again!) that dir/file2 is excluded # ..which means dir/file1 stays included Again, we're ok at the toplevel, then we enter "dir" and test "dir/file1". The MUSTBEDIR code tests if the _full_ path (ie. "dir/file1") is a directory. We want it to test the "dir" part from "dir/file1" instead. In both cases, we want to test if the pattern matches a parent directory. match_dir_component() is for this purpose. We do want to be careful not to get back too far. Given the file foo/bar/.gitignore, we should only check as far back as foo/bar because this .gitignore file can never match outside that directory, which is "toplevel" in the above paragraphs, to begin with. The remaining matching case (neither NODIR nor MUSTBEDIR is set) is already fixed in a60ea8f (dir.c: fix match_pathname() - 2016-02-15) Reported-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> --- The fix may look like this (I didn't think about the "**" trick in wildmatch, which makes things simpler). No it's not meant for 2.8.0. I didn't even optimize for the no-wildcard case, or add tests. But we can still stare at it in the meantime to see if I analyzed anything wrong. I almost thought I was wrong to the declare the bug while I was on my ride back home.. dir.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/dir.c b/dir.c index 69e0be6..5123483 100644 --- a/dir.c +++ b/dir.c @@ -992,6 +992,51 @@ static struct exclude *should_descend(const char *pathname, int pathlen, } /* + * Given a "NODIR" pattern, check if it matches any directory + * component after the x->base part. + * + * If the pattern is not NODIR (ie. pathname matching) _and_ is + * MUSTBE, check if it matches a directory as well. + * + * Note that "path" and "len" must cover the basename part as well, + * looking from last_exclude_matching_from_list(), not just the dirname. + */ +static int match_dir_component(const char *path, int len, struct exclude *x) +{ + struct strbuf new_pattern = STRBUF_INIT; + int ret; + + if (x->flags & EXC_FLAG_NODIR) { + if (!x->baselen) { + strbuf_addf(&new_pattern, "%s/**", x->pattern); + ret = !fnmatch_icase_mem(new_pattern.buf, new_pattern.len, + path, strlen(path), + WM_PATHNAME); + strbuf_reset(&new_pattern); + if (ret) + return ret; + } + + strbuf_addf(&new_pattern, "%.*s**/%s/**", x->baselen, x->base, x->pattern); + ret = !fnmatch_icase_mem(new_pattern.buf, new_pattern.len, + path, strlen(path), + WM_PATHNAME); + strbuf_reset(&new_pattern); + return ret; + } + + assert(x->flags & EXC_FLAG_MUSTBEDIR); + strbuf_addf(&new_pattern, "%.*s%s/**", + x->baselen, x->base, + *x->pattern == '/' ? x->pattern+1 : x->pattern); + ret = !fnmatch_icase_mem(new_pattern.buf, new_pattern.len, + path, strlen(path), + WM_PATHNAME); + strbuf_release(&new_pattern); + return ret; +} + +/* * Scan the given exclude list in reverse to see whether pathname * should be ignored. The first match (i.e. the last on the list), if * any, determines the fate. Returns the exclude_list element which @@ -1033,7 +1078,8 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname, if (x->flags & EXC_FLAG_MUSTBEDIR) { if (*dtype == DT_UNKNOWN) *dtype = get_dtype(NULL, pathname, pathlen); - if (*dtype != DT_DIR) + if (*dtype != DT_DIR && + !match_dir_component(pathname, strlen(pathname), x)) continue; } @@ -1041,7 +1087,8 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname, if (match_basename(basename, pathlen - (basename - pathname), exclude, prefix, x->patternlen, - x->flags)) { + x->flags) || + match_dir_component(pathname, strlen(pathname), x)) { exc = x; break; } -- 2.8.0.rc0.208.g69d9f93 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH] dir.c: fix dir re-inclusion rules with "NODIR" and "MUSTBEDIR" 2016-03-09 11:08 ` [PATCH] dir.c: fix dir re-inclusion rules with "NODIR" and "MUSTBEDIR" Nguyễn Thái Ngọc Duy @ 2016-03-09 17:55 ` Junio C Hamano 2016-03-10 0:39 ` Duy Nguyen 0 siblings, 1 reply; 28+ messages in thread From: Junio C Hamano @ 2016-03-09 17:55 UTC (permalink / raw) To: Nguyễn Thái Ngọc Duy; +Cc: git, Kevin Daudt, Charles Strahan Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes: > Side note, it's probably a bad idea to use basename matching on a > negative rule (ie. no slashes in the pattern) because what the pattern > says is "re-include _any_ directory named 'dir'", not just the directory > "dir" at right below this directory. I am not sure I agree with this comment. When we say '.depend/' in our .gitignore file, we do want to ignore everything in the directory with that name anywhere in that tree. Perhaps '!include/' followed by '*' may be a good way to pick only the header files that are found in any directory with that name anywhere in the tree in a similar fashion. It certainly is a disappointing comment if made by somebody who wants to make 'dir' and '!dir' behave in a more similar way, I'd have to say. > In the MUSTBEDIR case, the patterns look like this > > * # exclude dir, dir/file1 and dir/file2.. > !dir/ # ..except that dir and everything inside is re-included.. > dir/file2 # ..except (again!) that dir/file2 is excluded > # ..which means dir/file1 stays included > > Again, we're ok at the toplevel, then we enter "dir" and test > "dir/file1". The MUSTBEDIR code tests if the _full_ path (ie. "dir/file1") > is a directory. We want it to test the "dir" part from "dir/file1" > instead. That certainly sounds like a breakage worth fixing. > In both cases, we want to test if the pattern matches a parent > directory. match_dir_component() is for this purpose. I do not follow. I would understand "In all cases, we want to behave as if we are testing the _full_ path against the pattern", though. IOW, "dir/file1" matches '*' (because 'file1' and '*' matches), '!dir/' (because the pattern is "everything under dir/ directory), and nothing else in the pattern list, and the last match wins---which happens to be negative ignore, hence dir/file1 is not ignored. > We do want to be careful not to get back too far. Given the file > foo/bar/.gitignore, we should only check as far back as foo/bar because > this .gitignore file can never match outside that directory, which is > "toplevel" in the above paragraphs, to begin with. Yes. But isn't that what exclude_stack mechanism already gives us? That is, when you are not looking at a path inside foo/bar/, entries stored in foo/bar/.gitignore will not participate the determination of the fate of the path. I am not sure why you have to say this. Puzzled... ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] dir.c: fix dir re-inclusion rules with "NODIR" and "MUSTBEDIR" 2016-03-09 17:55 ` Junio C Hamano @ 2016-03-10 0:39 ` Duy Nguyen 0 siblings, 0 replies; 28+ messages in thread From: Duy Nguyen @ 2016-03-10 0:39 UTC (permalink / raw) To: Junio C Hamano; +Cc: Git Mailing List, Kevin Daudt, Charles Strahan On Thu, Mar 10, 2016 at 12:55 AM, Junio C Hamano <gitster@pobox.com> wrote: > Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes: > >> Side note, it's probably a bad idea to use basename matching on a >> negative rule (ie. no slashes in the pattern) because what the pattern >> says is "re-include _any_ directory named 'dir'", not just the directory >> "dir" at right below this directory. > > I am not sure I agree with this comment. When we say '.depend/' in > our .gitignore file, we do want to ignore everything in the > directory with that name anywhere in that tree. Perhaps '!include/' > followed by '*' may be a good way to pick only the header files that > are found in any directory with that name anywhere in the tree in a > similar fashion. It certainly is a disappointing comment if made by > somebody who wants to make 'dir' and '!dir' behave in a more similar > way, I'd have to say. Hmm.. yeah personal view. I'll take this out. >> In both cases, we want to test if the pattern matches a parent >> directory. match_dir_component() is for this purpose. > > I do not follow. I would understand "In all cases, we want to > behave as if we are testing the _full_ path against the pattern", > though. > > IOW, "dir/file1" matches '*' (because 'file1' and '*' matches), > '!dir/' (because the pattern is "everything under dir/ directory), > and nothing else in the pattern list, and the last match > wins---which happens to be negative ignore, hence dir/file1 is not > ignored. Yep, bad phrasing. >> We do want to be careful not to get back too far. Given the file >> foo/bar/.gitignore, we should only check as far back as foo/bar because >> this .gitignore file can never match outside that directory, which is >> "toplevel" in the above paragraphs, to begin with. > > Yes. But isn't that what exclude_stack mechanism already gives us? > That is, when you are not looking at a path inside foo/bar/, entries > stored in foo/bar/.gitignore will not participate the determination > of the fate of the path. > > I am not sure why you have to say this. Puzzled... Naively speaking, in order to fix this without reorganizing a lot of code, when given path 'foo/bar/dir/file1' and the pattern '!dir/', we first still test if the full path "foo/bar/dir/file1" is a directory, then we cut "file1" out (pretend that we are in foo/bar instead of in foo/bar/dir) and test again the full path, which is just foo/bar/dir, if it's a directory. Repeat again and again. This trick does not go through the normal prep_exclude(), so patterns are not popping out when .gitignore should not be used any more. The implementation is a bit different. Instead of going up one level, test, and go up again, I construct the new pattern "foo/bar/**/dir/**" and match it (only once) against the original full path foo/bar/dir/file1. The note was there because I would have just constructed "**/dir/**" instead and matched too much. -- Duy ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-08 18:10 ` Junio C Hamano 2016-03-09 0:18 ` Duy Nguyen @ 2016-03-09 9:48 ` Duy Nguyen 2016-03-09 18:02 ` Junio C Hamano 1 sibling, 1 reply; 28+ messages in thread From: Duy Nguyen @ 2016-03-09 9:48 UTC (permalink / raw) To: Junio C Hamano; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List On Wed, Mar 9, 2016 at 1:10 AM, Junio C Hamano <gitster@pobox.com> wrote: > diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt > index 3ded6fd..91d1ce2 100644 > --- a/Documentation/gitignore.txt > +++ b/Documentation/gitignore.txt > @@ -148,7 +148,43 @@ excluded, the following conditions must be met: > be in the same .gitignore file. > > - The directory part in the re-include rules must be literal (i.e. no > - wildcards) > + wildcards and has to start with a `/`). Technically '/' can just appear anywhere in the pattern, except at the end. But because the patterns in question must look like this dir # or any pattern, even "*" !dir/someth*ng even if there is a slash at the end (and is ignored), we are still good. Not sure how to phrase that though. > + > +A re-inclusion of a directory makes all files in the directory > +unignored. For example, suppose you have files `.gitignore`, > +`dir/file1`, `dir/file2`, and `dir/file3`, and have the following in > +your `.gitignore`: > + > +---------------- > +# .gitignore is not mentioned in .gitignore > +* > +!/dir > +# dir/file1 is not mentioned in .gitignore > +dir/file2 > +!dir/file3 > +---------------- > + > +Then: > + > + - `.gitignore` gets ignored, because it matches the `*` at the top > + level; > + > + - `dir/file1` does not get ignored, because `/dir` marks everything > + underneath `dir/` directory to be 're-included' unless otherwise > + specified; > + > + - `dir/file2` gets ignored, because `dir/file2` matches it. > + > + - `dir/file3` does not get ignored, because `!dir/file3` matches it. > + Note that the entry `!dir/file3` is redundant because everything > + underneath `dir/` is marked to be 're-included' already. > + > +Some earlier versions of Git treated `!/dir` above differently in > +that it did not cause the paths under it unignored (but merely told > +Git that patterns that begin with dir/ should not be ignored), but > +this has been corrected to be consistent with `/dir` that says "the > +directory `dir/` and everything below are ignored." > + Looks good. -- Duy ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-09 9:48 ` Change in .gitignore handling: intended or bug? Duy Nguyen @ 2016-03-09 18:02 ` Junio C Hamano 2016-03-10 0:26 ` Duy Nguyen 0 siblings, 1 reply; 28+ messages in thread From: Junio C Hamano @ 2016-03-09 18:02 UTC (permalink / raw) To: Duy Nguyen; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List Duy Nguyen <pclouds@gmail.com> writes: > On Wed, Mar 9, 2016 at 1:10 AM, Junio C Hamano <gitster@pobox.com> wrote: >> diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt >> index 3ded6fd..91d1ce2 100644 >> --- a/Documentation/gitignore.txt >> +++ b/Documentation/gitignore.txt >> @@ -148,7 +148,43 @@ excluded, the following conditions must be met: >> be in the same .gitignore file. >> >> - The directory part in the re-include rules must be literal (i.e. no >> - wildcards) >> + wildcards and has to start with a `/`). > > Technically '/' can just appear anywhere in the pattern, except at the > end. But because the patterns in question must look like this > > dir # or any pattern, even "*" > !dir/someth*ng > > even if there is a slash at the end (and is ignored), we are still > good. Not sure how to phrase that though. Post 2.8, we'd be correcting this properly anyway, we should aim for the simplest-to-explain way to work around the limitation in the current code, that will still work once the bug is fixed. I am not sure if "Technically it can be other things" helps, unless it makes it a lot easier to use. With that in mind, do you think we need to find a better phrase to loosen what I wrote that is overly-strict? That is, is "must begin with '/' to anchor it to the level .gitignore appears" too strict to make it too hard to use? ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-09 18:02 ` Junio C Hamano @ 2016-03-10 0:26 ` Duy Nguyen 2016-03-10 0:37 ` Junio C Hamano 0 siblings, 1 reply; 28+ messages in thread From: Duy Nguyen @ 2016-03-10 0:26 UTC (permalink / raw) To: Junio C Hamano; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List On Thu, Mar 10, 2016 at 1:02 AM, Junio C Hamano <gitster@pobox.com> wrote: > Duy Nguyen <pclouds@gmail.com> writes: > >> On Wed, Mar 9, 2016 at 1:10 AM, Junio C Hamano <gitster@pobox.com> wrote: >>> diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt >>> index 3ded6fd..91d1ce2 100644 >>> --- a/Documentation/gitignore.txt >>> +++ b/Documentation/gitignore.txt >>> @@ -148,7 +148,43 @@ excluded, the following conditions must be met: >>> be in the same .gitignore file. >>> >>> - The directory part in the re-include rules must be literal (i.e. no >>> - wildcards) >>> + wildcards and has to start with a `/`). >> >> Technically '/' can just appear anywhere in the pattern, except at the >> end. But because the patterns in question must look like this >> >> dir # or any pattern, even "*" >> !dir/someth*ng >> >> even if there is a slash at the end (and is ignored), we are still >> good. Not sure how to phrase that though. > > Post 2.8, we'd be correcting this properly anyway, we should aim for > the simplest-to-explain way to work around the limitation in the > current code, that will still work once the bug is fixed. I am not > sure if "Technically it can be other things" helps, unless it makes > it a lot easier to use. > > With that in mind, do you think we need to find a better phrase to > loosen what I wrote that is overly-strict? That is, is "must begin > with '/' to anchor it to the level .gitignore appears" too strict to > make it too hard to use? > If we can name rules from the syntax part, then we can simply say "patterns that meet rules x and y". A bit off topic, but these two paragraphs may need rephrasing, I don't really understand what it's trying to say - If the pattern does not contain a slash '/', Git treats it as a shell glob pattern and checks for a match against the pathname relative to the location of the `.gitignore` file (relative to the toplevel of the work tree if not from a `.gitignore` file). Not sure why "relative to the location of .gitignore file" matters. We basically just take `basename $path` out and try to match it. - Otherwise, Git treats the pattern as a shell glob suitable for consumption by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the pattern will not match a / in the pathname. For example, "Documentation/{asterisk}.html" matches "Documentation/git.html" but not "Documentation/ppc/ppc.html" or "tools/perf/Documentation/perf.html". Perhaps "Otherwise" can be stated explicitly that "if the pattern does contain any slash, besides the trailing one". The "wildcards not matching /" is also true for the "pattern does not contain a slash" rule above. We can make it a generic note about wildcards and remove this "otherwise" rule, maybe... -- Duy ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-10 0:26 ` Duy Nguyen @ 2016-03-10 0:37 ` Junio C Hamano 2016-03-10 0:59 ` Junio C Hamano 0 siblings, 1 reply; 28+ messages in thread From: Junio C Hamano @ 2016-03-10 0:37 UTC (permalink / raw) To: Duy Nguyen; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List Duy Nguyen <pclouds@gmail.com> writes: > A bit off topic, but these two paragraphs may need rephrasing, I don't > really understand what it's trying to say > > - If the pattern does not contain a slash '/', Git treats it as > a shell glob pattern and checks for a match against the > pathname relative to the location of the `.gitignore` file > (relative to the toplevel of the work tree if not from a > `.gitignore` file). > > Not sure why "relative to the location of .gitignore file" matters. We > basically just take `basename $path` out and try to match it. That is because the documentation was written with a single consistent matching mode in mind: you match various patterns against the FULL path in the repository, no matter where you find the path. If you find a pattern "*.c" in d/.gitignore file, a path d/hello.c matches, even though '*.c' does not match 'd/hello.c' in the shell glob sense, and the rule needs to clarify that the leading directory part "d/" in the path "d/hello.c" does not participate when matching it against the pattern "*.c" taken from "d/.gitignore" file. If you start from a mindset to match hello.c part with *.c when you find both in d/ directory, "relative to the location" part would sound redundant or even confusing. > - Otherwise, Git treats the pattern as a shell glob suitable > for consumption by fnmatch(3) with the FNM_PATHNAME flag: > wildcards in the pattern will not match a / in the pathname. > For example, "Documentation/{asterisk}.html" matches > "Documentation/git.html" but not "Documentation/ppc/ppc.html" > or "tools/perf/Documentation/perf.html". > > Perhaps "Otherwise" can be stated explicitly that "if the pattern does > contain any slash, besides the trailing one". Yeah, I think there originally was just two (it has slasn or it doesn't) and "If ..." followed by "Otherwise" was clear enough, but spellin it out would not hurt. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-10 0:37 ` Junio C Hamano @ 2016-03-10 0:59 ` Junio C Hamano 2016-03-10 10:56 ` Duy Nguyen 0 siblings, 1 reply; 28+ messages in thread From: Junio C Hamano @ 2016-03-10 0:59 UTC (permalink / raw) To: Duy Nguyen; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List Junio C Hamano <gitster@pobox.com> writes: > Duy Nguyen <pclouds@gmail.com> writes: > >> A bit off topic, but these two paragraphs may need rephrasing, I don't >> really understand what it's trying to say >> >> - If the pattern does not contain a slash '/', Git treats it as >> a shell glob pattern and checks for a match against the >> pathname relative to the location of the `.gitignore` file >> (relative to the toplevel of the work tree if not from a >> `.gitignore` file). >> >> Not sure why "relative to the location of .gitignore file" matters. We >> basically just take `basename $path` out and try to match it. > > That is because the documentation was written with ... > matches, even though '*.c' does not match 'd/hello.c' in the shell > glob sense,... Sorry, this does not make much sense, as d/e/hello.c would still match '*.c' in d/.gitignore. So it is a straight-forward match against the basename, and there is nothing relative to the location of .gitignore. If anything, relative to where the pattern is found should be relevant to a pattern _with_ slash in it. I should have been more careful and thought things through, but as this was an "off topic" comment, I didn't. Sorry about that. In any case, back to "on topic" part again; I couldn't come up with a better rewrite using named rules (partly because you need to clearly define each rule before referring them, and some of the rules are temporary workarounds for the 2.8 regression that will hopefully disappear in near future). I think you understand the bug and the limitation of the current code a lot better than I do, so if you can please send a final version of the documentation update in the coming 18 hours (I have an option of using what is already queued on 'pu' as a fall-back-good-enough version but I want to keep the last-resort option as that--if I know a potential source of a better version, I'd choose to ask first ;-). Thanks. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: Change in .gitignore handling: intended or bug? 2016-03-10 0:59 ` Junio C Hamano @ 2016-03-10 10:56 ` Duy Nguyen 0 siblings, 0 replies; 28+ messages in thread From: Duy Nguyen @ 2016-03-10 10:56 UTC (permalink / raw) To: Junio C Hamano; +Cc: Kevin Daudt, Charles Strahan, Git Mailing List On Thu, Mar 10, 2016 at 7:59 AM, Junio C Hamano <gitster@pobox.com> wrote: > In any case, back to "on topic" part again; I couldn't come up with > a better rewrite using named rules (partly because you need to > clearly define each rule before referring them, and some of the > rules are temporary workarounds for the 2.8 regression that will > hopefully disappear in near future). I think you understand the bug > and the limitation of the current code a lot better than I do, so if > you can please send a final version of the documentation update in > the coming 18 hours (I have an option of using what is already > queued on 'pu' as a fall-back-good-enough version but I want to keep > the last-resort option as that--if I know a potential source of a > better version, I'd choose to ask first ;-). I'm never good with words, especially in a rush. Let's merge yours. I'll fix the bug and update gitignore.txt in one go. -- Duy ^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2016-03-10 10:56 UTC | newest] Thread overview: 28+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-03-04 2:11 Change in .gitignore handling: intended or bug? Charles Strahan 2016-03-04 3:09 ` Duy Nguyen 2016-03-04 5:51 ` Kevin Daudt 2016-03-04 6:12 ` Charles Strahan 2016-03-04 11:56 ` Kevin Daudt 2016-03-04 12:36 ` Duy Nguyen 2016-03-04 17:28 ` Junio C Hamano 2016-03-04 19:12 ` Junio C Hamano 2016-03-05 0:43 ` Duy Nguyen 2016-03-05 0:50 ` Duy Nguyen 2016-03-05 1:00 ` Charles Strahan 2016-03-05 1:35 ` Junio C Hamano 2016-03-07 21:11 ` Junio C Hamano 2016-03-08 6:14 ` Junio C Hamano 2016-03-08 10:19 ` Duy Nguyen 2016-03-08 18:10 ` Junio C Hamano 2016-03-09 0:18 ` Duy Nguyen 2016-03-09 0:32 ` Junio C Hamano 2016-03-09 0:45 ` Junio C Hamano 2016-03-09 11:08 ` [PATCH] dir.c: fix dir re-inclusion rules with "NODIR" and "MUSTBEDIR" Nguyễn Thái Ngọc Duy 2016-03-09 17:55 ` Junio C Hamano 2016-03-10 0:39 ` Duy Nguyen 2016-03-09 9:48 ` Change in .gitignore handling: intended or bug? Duy Nguyen 2016-03-09 18:02 ` Junio C Hamano 2016-03-10 0:26 ` Duy Nguyen 2016-03-10 0:37 ` Junio C Hamano 2016-03-10 0:59 ` Junio C Hamano 2016-03-10 10:56 ` Duy Nguyen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).