Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 407475 - Directory entries in .gitignore are ignored.
Summary: Directory entries in .gitignore are ignored.
Status: RESOLVED FIXED
Alias: None
Product: EGit
Classification: Technology
Component: Core (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: 3.6   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 448094 (view as bug list)
Depends on: 407643
Blocks: 448094
  Show dependency tree
 
Reported: 2013-05-07 19:11 EDT by Michal Rus CLA
Modified: 2014-11-28 19:29 EST (History)
3 users (show)

See Also:


Attachments
Example project to see the issue (1.45 KB, application/zip)
2014-10-22 03:06 EDT, Andrey Loskutov CLA
no flags Details
An example (7.63 KB, application/x-xz)
2014-10-22 08:07 EDT, Michal Rus CLA
no flags Details
egit-gitignore.tar (70.00 KB, application/x-tar)
2014-10-22 08:31 EDT, Michal Rus CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Michal Rus CLA 2013-05-07 19:11:26 EDT
Consider the following project structure:

/.gitignore
/src/.gitignore

Contents of /.gitignore:

/*
!/src/

Contents of /src/.gitignore:

*
!*.java
!*/

So basically it means "ignore everything that is not a *.java file somewhere in /src/ directory". This works with command-line git.

However, Egit still marks these files with a '?'.
Comment 1 Andrey Loskutov CLA 2014-10-21 10:24:37 EDT
@Michal: funny enough for your purpose the src/.gitignore can be changed to make both git and jgit happy (just remove last !*/ line ):

Fixed contents of /src/.gitignore:
*
!*.java

... and then jgit will show same picture as git.

Nevertheless, jgit shouldn't be confused.

I'm actually pretty much confused too, so what exactly !*/ should mean in the context of previous rules?

I would expect !*/ should be "negate last ignore rule if it matches any *folder* in src", and this would be * rule from /src/.gitignore and as next the parent .gitignore file should be applied, which then says "ignore everything but src". So following this logic, jgit shows all children under src/a directory as untracked (not ignored).


BTW here is the test which shows the current state (just add to org.eclipse.jgit.ignore.IgnoreNodeTest)

	@Test
	public void testNegationAllExceptJavaInSrcAndExceptChildDirInSrc()
			throws IOException {
		// ignore all files except from src directory
		writeIgnoreFile(".gitignore", "/*", "!/src/");
		writeTrashFile("nothere.o", "");

		// ignore all files except java in src folder.
		// Last ignore rule breaks jgit and my mind too.
		// CLI git shows untracked *directory* src/a/ which is at least strange
		// CLI git also ignores everything in child directories too, recursively
		writeIgnoreFile("src/.gitignore", "*", "!*.java", "!*/");

		writeTrashFile("src/keep.java", "");
		writeTrashFile("src/nothere.o", "");
		writeTrashFile("src/a/nothere.java", "");
		writeTrashFile("src/a/nothere.o", "");

		beginWalk();
		assertEntry(F, ignored, ".gitignore");
		assertEntry(F, ignored, "nothere.o");
		assertEntry(D, false, "src");
		assertEntry(F, ignored, "src/.gitignore");
		assertEntry(D, tracked, "src/a");

		// this two cases below differ between CLI git and jgit.
		// CLI git shows both as ignored.
		assertEntry(F, tracked, "src/a/nothere.java");
		assertEntry(F, tracked, "src/a/nothere.o");

		assertEntry(F, tracked, "src/keep.java");
	}
Comment 2 Andrey Loskutov CLA 2014-10-22 03:06:21 EDT
Created attachment 248076 [details]
Example project to see the issue
Comment 3 Andrey Loskutov CLA 2014-10-22 05:41:51 EDT
In context of the fix of the bug 448094 I've tried to understand the behavior of CLI git on last "!*/" rule and failed.

AFAIK it is not allowed to me to read the CLI git source code because of GPL / EPL incompatibility - and there is no other reliable documentation I'm aware of.

I simply have no idea which logic CLI git applied here - the publicly available "documentation" of ignore rule behavior is a joke (see [1, 2]) and I give up here unless someone gives a hint.

[1] https://www.kernel.org/pub/software/scm/git/docs/gitignore.html
[2] http://git-scm.com/docs/gitignore
Comment 4 Michal Rus CLA 2014-10-22 07:35:43 EDT
@Andrey,

as for `!*/` in /src/.gitignore, create this file/dir structure:

/.gitignore
/boom
/boom/x.java
/src
/src/blah.java
/src/.gitignore
/src/xyz
/src/xyz/boom.txt
/src/xyz/blah.java

Now, with `!*/` added to /src/.gitignore, when you issue `$ git status`, you get:

        src/blah.java
        src/xyz/blah.java

Without the `!*/`, you get only:

        src/blah.java

Why? Because `*` in the first line of /src/.gitignore catches also /src/xyz/ directory. :) You've got to exclude directories inside /src/, so that the /src/xyz/blah.java can even be seen. That's what `!*/` does → unignores all directories inside of /src/.

Cheers!

m.
Comment 5 Andrey Loskutov CLA 2014-10-22 07:54:46 EDT
(In reply to Michal Rus from comment #4)
> @Andrey,
> 
> as for `!*/` in /src/.gitignore, create this file/dir structure:
> 
> /.gitignore
> /boom
> /boom/x.java
> /src
> /src/blah.java
> /src/.gitignore
> /src/xyz
> /src/xyz/boom.txt
> /src/xyz/blah.java

Michal,
can you please zip your directory above with *all* files and attach here? This will simplify my life greatly :-)
Comment 6 Michal Rus CLA 2014-10-22 08:07:51 EDT
Created attachment 248090 [details]
An example

So:

$ tar -xf egit-gitignore.tar.xz
$ cd egit-gitignore
$ git status

Now we're getting only:

        src/wont-be-ignored.java

However, when you switch to `correct` branch (with `!*/` added to src/.gitignore):

$ git checkout correct
$ git status

        src/subdir/shouldnt-be-ignored.java
        src/wont-be-ignored.java

The only difference is:

$ git diff correct master 
diff --git a/src/.gitignore b/src/.gitignore
index a7bb6a4..387e4bd 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,3 +1,2 @@
 *
 !*.java
-!*/
Comment 7 Andrey Loskutov CLA 2014-10-22 08:26:23 EDT
(In reply to Michal Rus from comment #6)
> Created attachment 248090 [details]
> An example
> 
> So:
> 
> $ tar -xf egit-gitignore.tar.xz

You will hate me, but:
tar -xf egit-gitignore.tar.xz
tar: This does not look like a tar archive
tar: Skipping to next header
tar: Archive contains obsolescent base-64 headers
tar: Error exit delayed from previous errors
Comment 8 Michal Rus CLA 2014-10-22 08:31:20 EDT
Created attachment 248091 [details]
egit-gitignore.tar

=P No, my fault. xz is still kind of new (5 years old, though ;b). Attaching unzipped version (10× the size). Now:

$ tar -xz egit-gitignore.tar

m.
Comment 9 Michal Rus CLA 2014-10-22 08:32:01 EDT
No, no, not `-xz`! Obviously it's still `-xf`. :)
Comment 10 Andrey Loskutov CLA 2014-10-22 08:52:07 EDT
Ok,
looks like my patch for bug 448094 works for your example too, just my CLI git is too old to produce meaningful report:

socbl593:egit-gitignore$ jgit status
On branch correct
Untracked files:

        src/subdir/shouldnt-be-ignored.java
        src/wont-be-ignored.java
socbl593:egit-gitignore$ git status
# On branch correct
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       src/subdir/
#       src/wont-be-ignored.java
nothing added to commit but untracked files present (use "git add" to track)
socbl593:egit-gitignore$ git --version
git version 1.8.2

I'm on RHEL 5.8 so the system is a little bit ancient :(

Which git version do you have?

If you want verify the fix, please apply patch  https://git.eclipse.org/r/35295 to the head of jgit or grab my private binary snapshot of jgit from ~1 week ago plus all my gerrit patches (including for bug 448094) on top:

https://drive.google.com/file/d/0B7vALkuico9hTUNDdlFQc3JNUzQ/view?usp=sharing
Comment 11 Michal Rus CLA 2014-10-22 08:57:20 EDT
I'm on ArchLinux so bleeding edge here. =b

m@arch:~$ git --version
git version 2.1.2
m@arch:~$ 

Happy to hear that your patch fixes this. ♥

However, I've not been using jgit/egit for quite some time now, so I'll just keep to believing you.

I'll be more than happy to vote for it (is there a voting system here?).

Keep up the good work! =)

m.
Comment 12 Andrey Loskutov CLA 2014-10-22 09:17:15 EDT
*** Bug 448094 has been marked as a duplicate of this bug. ***
Comment 13 Andrey Loskutov CLA 2014-10-22 09:35:08 EDT
Just for the record: the patch https://git.eclipse.org/r/35295 fixes this bug, bug 448094 and bug 407643.
Comment 14 Matthias Sohn CLA 2014-11-28 19:29:19 EST
merged as 147e24a7b224fe6d643bb24100030ff70bfbca35