Значение Git оформить двойные тире


274

Что означает двойная тире перед именем файла в этой команде git?

git checkout --ours -- path/to/file.txt
git checkout --theirs -- path/to/file.txt

Они обязательны? Это эквивалентно

git checkout --ours path/to/file.txt
git checkout --theirs path/to/file.txt

24
Это выражение оболочки. См. Unix.stackexchange.com/questions/11376/…
iltempo

15
@iltempo: Это немного по-другому для Git. Для Git он отделяет дерево от путей в тех случаях, когда деревья и пути могут выглядеть одинаково.
Дитрих Эпп

@Dietrich_Epp. Понимаю. Спасибо за разъяснение.
iltempo

Также задокументировано в stackoverflow.com/a/1192194/6309
VonC

3
Это дубликат, но этот дубликат, по крайней мере, доступен для поиска по запросу «git double dash».
Торн̈

Ответы:


376

Предположим, у меня есть файл с именем path/to/file.txtв моем Git-репозитории, и я хочу отменить изменения в нем.

git checkout path/to/file.txt

Теперь предположим, что файл называется master...

git checkout master

Упс! Это изменило ветви вместо этого. В --разъединяет дерево вы хотите проверить из файлов , которые вы хотите проверить.

git checkout -- master

Это также помогает нам, если какой-то freako добавил файл с именем -fв наш репозиторий:

git checkout -f      # wrong
git checkout -- -f   # right

Это задокументировано в git-checkout: Аргументация неоднозначности .


12
Это верно для многих команд bash, а не только для команд git, да?
NHDaly

40
@NHDaly: Да, это правда. Тем не менее, примечание по терминологии: «Bash» имеет только несколько команд (может быть, около 20), большинство команд являются отдельными программами от Bash. На самом деле это часть стандарта POSIX, которую --можно использовать для отделения опций от других аргументов, так что вы увидите это в таких командах, как cpи mv(которые не являются частью Bash).
Дитрих Эпп

6
Любая идея, почему этот синтаксис не описан должным образом в checkoutдокументации команды?
TanguyP

4
@DietrichEpp В некоторых местах он указан как возможный параметр checkoutкоманды, но нигде документация не объясняет, что она делает и почему она используется ... именно это в конечном итоге и привело меня сюда.
Крис

7
@DietrichEpp Правильно, но, прочитав синтаксис (и примеры) перед переходом в Stack Overflow, я все еще не понимал, почему кто-то будет или не хочет его использовать --. Как кто-то, кто не пришел из Linux, не очевидно, что это делает. Для меня это был синтаксис, специфичный для git, без описания его функционального назначения. Я думаю, что было бы лучше иметь краткое описание, как и другие варианты, или хотя бы ссылку на справочную страницу Linux .
Крис

109

Двойная черта "-" означает "флаги конца командной строки", то есть она говорит предыдущей команде не пытаться анализировать то, что следует за параметрами командной строки.


2
Для ясности, gitэто означает больше, чем это, поскольку это также означает, что аргумент после --not не может быть именем ветви, и, как следствие, аргумент перед --не может быть путем к файлу.
Джем Тейлор

0

Обратите внимание, что вам это не понадобится, так как Git 2.5 (2 квартал 2015 г.) стоит ' --', если ваш аргумент включает подстановочный знак ( *)

Эвристика, помогающая git <cmd> <revs> <pathspec>соглашению " " в командной строке отлавливать неправильно набранные пути, состоит в том, чтобы убедиться, что все не-rev параметры в более поздней части командной строки являются именами файлов в рабочем дереве, но это означает, что " git grep $str -- \*.c" всегда должно быть с неоднозначностью " --", потому что никто в здравом уме не создаст файл, имя которого буквально - звездочка-точка-см.

Git 2.5 теряет эвристику, чтобы объявить, что с помощью подстановочной строки пользователь, вероятно, намеревался дать нам указание пути .

git checkout 'a*'
# same as
git checkout -- 'a*'

Смотрите коммит 28fcc0b (02 мая 2015 г.) от Duy Nguyen ( nguyenlocduy) .
(Слито Junio C Hamano - gitster- в фиксации 949d167 , 19 мая 2015 года)

pathspec: избегайте необходимости " --" при использовании подстановочного знака

Когда --в командной строке отсутствует "" и команда может принимать как обороты, так и пути, идея состоит в том, что если аргумент можно рассматривать как расширенный SHA-1 и путь, тогда --требуется "" или git отказывается продолжать.
В настоящее время это реализовано как:

  • (1) если аргумент является rev, то он не должен существовать в рабочем дереве
  • (2) иначе, он должен существовать в рабочем дереве
  • (3) иначе " --" требуется.

Эти правила работают для литеральных путей, но когда задействована не буквальная спецификация пути, почти всегда требуется, чтобы пользователь добавил « --», потому что он терпит неудачу (2) и (1) действительно редко встречаются ( *.cнапример, «взять» ), (1) встречается, если есть ссылка с именем " *.c").

Этот патч немного изменяет правила, рассматривая любой допустимый *шаблон пути valid ( ) «существует в рабочем дереве».
Правила становятся:

  • (1) если arg является rev, то он должен либо существовать в рабочем дереве, либо не быть допустимым подстановочным символом.
  • (2) в противном случае он либо существует в рабочем дереве, либо является шаблоном пути
  • (3) иначе " --" требуется.

С новыми правилами " --" не требуется большую часть времени, когда задействован подстановочный путь.


В Git 2.26 (Q1 2020) логика устранения неоднозначности для разделения ревизий и спецификаций пути была изменена таким образом, чтобы специальные символы глобуса с обратной косой чертой не учитывались в правиле «подстановочные знаки являются спецификацией пути».

См. Коммит 39e21c6 (25 января 2020 г.) Джеффа Кинга ( peff) .
(Слиты Junio C Hamano - gitster- в фиксации 341f8a6 , 12 Feb 2020)

verify_filename(): обрабатывать обратную косую черту в правиле "подстановочные знаки являются путями"

Автор сообщения: Дэвид Берстрем
Подписано: Джефф Кинг

Фиксировать 28fcc0b71a ( pathspec: избегать необходимости " --" при использовании подстановочного знака, 2015-05-02) разрешено:

git rev-parse '*.c'

без двойной черты.

Но правило, которое оно использует для проверки подстановочных знаков, на самом деле ищет какой-то специальный глобус.
Это слишком либерально, поскольку это означает, что шаблон, который на самом деле не выполняет подстановочных знаков, например " a\b", будет считаться спецификацией пути.

Если у вас есть такой файл на диске, это, вероятно, то, что вы хотели.
Но если вы этого не сделаете, результаты сбивают с толку: вместо того, чтобы сказать « there's no such path a\b», мы спокойно примем это как спецификацию пути, которая, скорее всего, не соответствует ничему (или, по крайней мере, не соответствует тому, что вы намеревались).
Аналогично, поиск пути " a\*b" вообще не расширяет поиск; он найдет только одну запись " a*b".

Эта фиксация переключает правило на срабатывание только тогда, когда метасимволы glob расширяют поиск, что означает, что оба этих случая теперь сообщат об ошибке (вы --, конечно, можете устранить неоднозначность, используя « »; мы просто ужесточаем эвристику DWIM).

( DWIM: делай, что я имею в виду )

Обратите внимание, что мы не тестировали оригинальную функцию в 28fcc0b71a .
Так что этот патч не только проверяет эти угловые случаи, но также добавляет регрессионный тест для существующего поведения.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.