Ключом к надежному «написанию сценариев» Git является использование «слесарных» команд.
Разработчики позаботятся о том, чтобы при смене сантехнических команд они обеспечивали очень стабильные интерфейсы (т. Е. Заданная комбинация состояния репозитория, стандартного ввода, параметров командной строки, аргументов и т. Д. Будет производить одинаковый вывод во всех версиях Git, где команда / опция существует). Новые варианты вывода в сантехнических командах могут быть введены с помощью новых опций, но это не может создавать проблем для программ, которые уже были написаны для более старых версий (они не будут использовать новые опции, поскольку их не было (или, по крайней мере, не использовался) на момент написания сценария).
К сожалению, «повседневные» команды Git - это «фарфоровые» команды, поэтому большинство пользователей Git могут быть не знакомы с сантехническими командами. Различия между командами фарфора и сантехники выполняются в основной справочной странице git (см. Подразделы Команды высокого уровня (фарфор) и Команды низкого уровня (сантехника) .
Чтобы узнать о несвязанных изменениях, вам, вероятно, понадобится git diff-index
(сравнить индекс (и, возможно, отслеживаемые биты рабочего дерева) с некоторыми другими древовидными (например, HEAD
)), возможно, git diff-files
(сравнить рабочее дерево с индексом) и, возможно, git ls-files
(список файлов; например, список неотслеживаемых, незарегистрированных файлов).
(Обратите внимание, что в приведенных ниже командах вместо HEAD
используется HEAD --
, потому что в противном случае команда завершится неудачно , если существует файл с именем HEAD
.)
Чтобы проверить, нет ли в хранилище изменений (еще не зафиксированных), используйте это:
git diff-index --quiet --cached HEAD --
- Если он завершается с
0
, то различий не было (1
означает, что различия были).
Чтобы проверить, есть ли в рабочем дереве изменения, которые можно поставить:
git diff-files --quiet
- Код выхода такой же, как для
git diff-index
(0
== нет различий; 1
== различия).
Чтобы проверить, изменяется ли комбинация индекса и отслеживаемых файлов в рабочем дереве относительно HEAD
:
git diff-index --quiet HEAD --
- Это похоже на комбинацию двух предыдущих. Одно из главных отличий состоит в том, что он по-прежнему будет сообщать об отсутствии различий, если у вас есть поэтапное изменение, которое вы «отменили» в рабочем дереве (вернемся к содержимому в
HEAD
). В этой же ситуации обе отдельные команды будут возвращать отчеты о «существующих различиях».
Вы также упомянули неотслеживаемые файлы. Вы можете иметь в виду «неотслеживаемый и игнорируемый», или вы можете иметь в виду просто «неотслеживаемый» (включая игнорируемые файлы). В любом случае, git ls-files
является инструментом для работы:
Для «неотслеживаемых» (включая игнорируемые файлы, если они есть):
git ls-files --others
Для «без отслеживания и без подписи»:
git ls-files --exclude-standard --others
Моя первая мысль - просто проверить, выводятся ли эти команды:
test -z "$(git ls-files --others)"
- Если он завершается с
0
, то нет неотслеживаемых файлов. Если он завершается с 1
, то есть неотслеживаемые файлы.
Существует небольшая вероятность того, что это преобразует ненормальные выходы из git ls-files
в отчеты «без отслеживания файлов» (оба результата приводят к ненулевым выходам вышеуказанной команды). Более надежная версия может выглядеть так:
u="$(git ls-files --others)" && test -z "$u"
- Идея та же, что и в предыдущей команде, но она позволяет распространяться неожиданным ошибкам из
git ls-files
. В этом случае ненулевой выход может означать «есть неотслеживаемые файлы» или может означать, что произошла ошибка. Если вы хотите, чтобы результаты «ошибка» сочетались с результатом «нет неотслеживаемых файлов», используйте test -n "$u"
(где выход 0
означает «некоторые неотслеживаемые файлы», а ненулевое значение означает ошибку или «нет неотслеживаемых файлов») .
Другая идея - использовать --error-unmatch
, чтобы вызвать ненулевой выход, когдаЭто не неотслеживаемые файлы. Это также рискует связать «нет неотслеживаемых файлов» (выход 1
) с «произошла ошибка» (выход ненулевой, но, вероятно, 128
). Но проверка на 0
против 1
против ненулевых кодов выхода, вероятно, достаточно надежна:
git ls-files --others --error-unmatch . >/dev/null 2>&1; ec=$?
if test "$ec" = 0; then
echo some untracked files
elif test "$ec" = 1; then
echo no untracked files
else
echo error from ls-files
fi
Любой из вышеприведенных git ls-files
примеров может занять --exclude-standard
, если вы хотите рассматривать только неотслеживаемые и незарегистрированные файлы.