I also found the old description very confusing. I have created a PR to improve the rules. I think its much better now.
Here an excerpt of the new docs.
The slash / is used as the directory separator. Separators may occur
at the beginning, middle or end of the .gitignore search pattern.
If there is a separator at the beginning or middle (or both) of the
pattern, then the pattern is relative to the directory level of the
particular .gitignore file itself. Otherwise the pattern may also
match at any level below the .gitignore level.
If there is a separator at the end of the pattern then the pattern
will only match directories, otherwise the pattern can match both
files and directories.
For example, a pattern doc/frotz/ matches doc/frotz directory, but not
a/doc/frotz directory; however frotz/ matches frotz and a/frotz that
is a directory (all paths are relative from the .gitignore file).
Nevertheless here is the answer to your questions:
If the pattern ends with a slash, it is removed for the purpose of the following description"
What is removed? What is the "following description" ?
It means that trailing slashes are excluded when slashes are mentioned. But it actually effects only the next paragraph.
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 [..] Otherwise, Git treats the pattern as a shell glob
"Otherwise" from what? Are they contrasting "with" and "without" slash in the pattern? If so, how are the two cases treated differently?
So with the above explanation in mind the first paragraph means this:
If the pattern contains no slash '/' other then a trailing slash, then the pattern will match in all directories.
In other words, foo/
will match /bar/foo/
and foo
will match /bar/foo
And the "Otherwise part" means:
If the pattern contains a slash '/' other then a trailing slash, it is always considered from the root.
In other words, foo/bar
will match /foo/bar
but not /bar/foo/bar
.
A trailing "/**" matches everything inside.
Is that the same result as a trailing /
without the asterisks? It looks like it from what I can see in the bullet point about the trailing slash ("foo/ will match a directory foo and paths underneath it").
There is a subtle difference. foo/
will ignore the folder, while foo/**
will ignore the folder and its content.
So if this is your file structure:
.gitignore
foo
├── bar.json
└── foo.txt
then the following .gitignore file would track everything:
foo/
!foo/
However
foo/**
!foo/
would track nothing. Because you first ignore all files, then you unignore the folder /foo
but since the folder has no trackable files it is empty and empty folders are not tracked by git.