В чем разница между добавлением bin, bin/, bin/* и bin/** в мой файл .gitignore? Я использовал bin/, но смотрел прочее .gitignore файлы (в файле eclipse двойные и одиночные звезды даже используются вместе следующим образом: tmp/**/* что с этим?) Я вижу, что первые два шаблона также широко используются. Может кто-нибудь объяснить различия между тремя?
.gitignore Синтаксис: bin vs bin/vs. bin/* vs. bin/**
Ответ 1
bin соответствует любым файлам или каталогам с именем 'bin'.
bin/ соответствует любым каталогам с именем "bin", что фактически означает все его содержимое, поскольку Git не отслеживает только каталоги.
bin/* соответствует всем файлам и каталогам непосредственно в любом bin/. Это предотвращает Git автоматически поиск любых файлов в своих подкаталогах, но если, скажем, создается подкаталог bin/foo, это правило будет не соответствовать foo содержимому.
bin/** соответствует всем файлам и каталогам в любом каталоге bin/ и во всех его подкаталогах.
Слово "любое" здесь имеет решающее значение, поскольку правила не относятся к корню репозитория и применяются в любом месте дерева файловой системы. Вы должны начинать правила с / (или !/, чтобы игнорировать), что означает корень репозитория, а не системный корень, чтобы соответствовать только тому, что было предназначено.
ПРЕДУПРЕЖДЕНИЕ.. никогда не используйте правила, такие как dir/*, /dir/** и т.д., если вы также не игнорируете что-то, что существует внутри этого каталога. Опустите звездочку или вы можете навсегда потерять много данных из определенных вызовов git gc, git stash и т.д.
Я действительно не знаю, что делать tmp/**/*. Первоначально я думал, что он может использоваться для сопоставления файлов в подкаталогах tmp/, но не файлов, непосредственно присутствующих в tmp/. Но простой тест, кажется, предполагает, что это игнорирует все файлы в tmp/.
Ответ 2
bin и bin/ отличаются только тем, что последний соответствует только каталогу.
bin/**/* совпадает с bin/** (по-видимому, с 1.8.2, согласно ответу @VonC).
Трудный, что я просто потратил час или около того, вырывая мои волосы, заключается в том, что bin/ и bin/** не совсем то же самое! Поскольку ранее игнорирует каталог в целом, а последний игнорирует каждый из файлов внутри него, а git почти во всех случаях не заботится о каталогах, обычно нет разницы. Однако, если вы попытаетесь использовать !, чтобы игнорировать подпуть, вы обнаружите, что git (ahem) игнорирует его, если вы проигнорировали родительский каталог! (опять же, а не содержимое каталога)
Это яснее на примере, поэтому для недавно созданного репозитория настроено так:
$ cat .gitignore
ignored-file
or-dir
dir-only/
!dir-only/cant-reinclude
dir-contents/**
!dir-contents/can-reinclude
$ mkdir or-dir dir-only dir-contents
$ touch file ignored-file or-dir/ignored-file dir-only/cant-reinclude dir-contents/can-reinclude
Существуют следующие файлы без следа:
$ git ls-files --other
.gitignore
dir-contents/can-reinclude
dir-only/cant-reinclude
file
ignored-file
or-dir/ignored-file
Но вы можете видеть, что следующие файлы не игнорируются:
$ git ls-files --other --exclude-standard
.gitignore
dir-contents/can-reinclude
file
И если вы попытаетесь добавить, вы получите:
$ git add dir-only/cant-reinclude
The following paths are ignored by one of your .gitignore files:
dir-only/cant-reinclude
Use -f if you really want to add them.
fatal: no files added
Я считаю это поведение ошибкой. (Все это на git version 1.8.4.msysgit.0)
Ответ 3
Обратите внимание, что, строго говоря, git не отслеживает каталоги, только файлы. Поэтому невозможно добавить каталог, только его содержимое.
Однако в контексте .gitignore git делает вид, что понимает каталоги только по той причине, что
Невозможно повторно включить файл, если родительский каталог этого файла исключен.
https://git-scm.com/docs/gitignore#_pattern_format
Что это значит для шаблонов исключений? Прочтите их подробно:
bin
Это игнорирует
- с именем
bin. - содержимое папок с именем
bin
Вы можете белыми списками игнорировать bin файлы и папки, добавляя последующие записи !, но вы не можете переадресовывать содержимое папок с именем bin
bin
!bin/file_in_bin # has no effect, since bin/ is blacklisted!
!bin/* # has no effect, since bin/ is blacklisted!
!file_in_bin # has no effect, since bin/ is blacklisted!
!bin # this works
bin/
То же, что и выше, за исключением того, что он не соответствует файлам с именем bin. Добавление конечного / сообщает git только для сопоставления каталогов.
bin/*
Это игнорирует
- файлы, содержащиеся в папке с именем
bin - содержимое прямых подпапок папок с именем
bin
bin/* # blacklists bin/file_in_bin and bin/subfolder/
!bin/subfolder/file_in_sub # has no effect, since bin/subfolder is blacklisted!
!bin # whitelists files named bin/bin, since bin/ itself is not blacklisted
!bin/ # has no effect, since bin/ itself is not blacklisted
!bin/file_in_bin # works since bin/ itself is not blacklisted
!file_in_bin # works too
!bin/subfolder # works (so implicitly whitelists bin/subfolder/file_in_sub)
!bin/subfolder/ # works just as well
!bin/* # works for file_in_bin and subfolder/
bin/**
Это игнорирует
- содержимое
bin - содержимое подпапок (любой уровень вложенности) в
bin
bin/** # blacklists bin/file_in_bin and
# bin/subfolder/ and bin/subfolder/file_in_sub and
# bin/subfolder/2/ and bin/subfolder/2/file_in_sub_2
!bin/subfolder/file_in_sub # has no effect, since bin/subfolder is blacklisted
!bin/subfolder/2/ # has no effect, since bin/subfolder is blacklisted
!bin/subfolder/2/file_in_sub_2 # has no effect, since bin/subfolder is blacklisted
!bin/subfolder # works only in combinations with other whitelist entries,
# since all contents of subfolder are blacklisted (1)
!bin/file_in_bin # works since bin itself is not blacklisted
!bin/* # works for file_in_bin and subfolder; see (1)
Ответ 4
Я только что сделал новое репо и попробовал кое-что. Вот мои результаты:
НОВЫЕ РЕЗУЛЬТАТЫ
git версия 2.10.1.windows.1
- Инициализировать почти пустое репо. Только файл README
- Настройте каталог
binна несколько слоев-
bin.txt -
Test.txt -
bin/a/b/bin.txt -
bin/a/b/Test.txt -
bin/a/bin/bin.txt -
bin/a/bin/Test.txt -
bin/a/bin.txt -
bin/a/Test.txt -
bin/bin.txt -
bin/Test.txt
-
- Добавить
binв gitignore: Результаты- Все ниже
bin(и глубже) теперь игнорируется - Уровень корня не игнорируется (/bin.txt и /Test.txt все еще отображаются)
- Все ниже
- Изменить
binнаbin/в gitignore: Результаты- Без изменений
- Изменить
bin/наbin/*- Без изменений
- Изменить
bin/*наbin/**- Без изменений
- Изменить
bin/**наbin/**/-
bin/bin.txtиbin/Test.txtбольше не игнорируются
-
- Изменить
bin/**/наbin/**/*-
bin/bin.txtиbin/Test.txtвозвращаются к игнорированию
-
СТАРЫЕ РЕЗУЛЬТАТЫ
git версия: 2.7.0.windows.1
- Инициализировать почти пустое репо. Только файл README
- Настройте каталог
binна несколько слоев-
bin/a/b/Test.txt -
bin/a/bin/Test.txt -
bin/a/Test.txt -
bin/Test.txt
-
- Добавить
binв gitignore: Результаты- Все ниже
bin(и глубже) теперь игнорируется
- Все ниже
- Изменить
binнаbin/в gitignore: Результаты- Все под каталогом
bin(и глубже) по-прежнему игнорируется (без изменений)
- Все под каталогом
- Изменить
bin/наbin/*- Все под каталогом
bin(и глубже) по-прежнему игнорируется (без изменений)
- Все под каталогом
- Изменить
bin/*наbin/**- Все под каталогом
bin(и глубже) по-прежнему игнорируется (без изменений)
- Все под каталогом
- Изменить
bin/**наbin/**/-
bin/Test.txtбольше не игнорируется
-
- Изменить
bin/**/наbin/**/*- Все под каталогом
bin(и глубже) снова игнорируется
- Все под каталогом
Ответ 5
Обратите внимание, что '**', когда он объединен с подкаталогом (**/bar), должен был измениться по своему поведению, поскольку примечание к выпуску для git1.8.2 теперь упоминает:
Паттерны в файлах
.gitignoreи.gitattributesмогут иметь**/, как шаблон, который соответствует 0 или более уровням подкаталога.например. "
foo/**/bar" соответствует "bar" в "foo" или в подкаталоге "foo".
Правило для запоминания (и которое помогает понять разницу намерений за этим синтаксисом):
Невозможно повторно включить файл, если родительский каталог этого файла исключен.
Обычно, если вы хотите исключить файлы из подпапки папки f игнорирования, вы должны:
f/**
!f/**/
!f/a/sub/folder/someFile.txt
То есть:
- Если первое правило было
f/, папкаf/была бы проигнорирована, а правила ниже относительноfне имели бы значения. -
f/**достичь того же значения, что иf/, но игнорировать все подэлементы (файлы и подпапки).
Это дает вам возможность вносить в белый список (исключить из gitignore) подпапки:!f/**/. - Поскольку все подтексты
fне игнорируются, вы можете добавить правило для исключения файла (!f/a/sub/folder/someFile.txt)
Ответ 6
Существует еще одно отличие между bin/* и bin/.
bin/ соответствует foo/bin/test.txt (как и ожидалось), но bin/* нет, что кажется странным, но оно документировано: https://git-scm.com/docs/gitignore
"Документация/*. html" соответствует "Документация/ git.html", но не "Документация/ppc/ppc.html" или "tools/perf/Documentation/perf.html".
Причиной этого являются следующие правила:
Если шаблон заканчивается косой чертой, он удаляется с целью следующего описания & hellip;
Если шаблон не содержит косой черты /, Git рассматривает его как шаблон оболочки оболочки и проверяет соответствие имени пути относительно местоположения файла .gitignore & hellip;
В противном случае Git рассматривает шаблон как оболочку оболочки, подходящую для использования fnmatch (3) с флагом FNM_PATHNAME & hellip;
Итак, если шаблон заканчивается косой чертой, косая черта удаляется и обрабатывается как шаблон оболочки оболочки, и в этом случае bin соответствует foo/bin/test.txt.
Если он заканчивается на /*, косая черта не удаляется и передается fnmatch, что не соответствует в подкаталогах.
Однако это не так для foo/bin/ и foo/bin/*, потому что даже после удаления конечной косой черты из foo/bin/ он все еще содержит косую черту, поэтому он рассматривается как шаблон fnmatch, а не glob. То есть он не будет соответствовать bar/foo/bin/test.txt