Как может я проверять, есть ли у меня какие-либо незафиксированные изменения в моем репозитории мерзавца:
из сценария?
git-status
кажется, всегда возвращает нуль с версией 1.6.4.2 мерзавца.
Отличное время! Я написал об этом сообщение в блоге несколько дней назад, когда выяснил, как добавить информацию о статусе git в мою подсказку.
Вот что я делаю:
Для грязного статуса:
# Возвращает "*", если текущая ветка git грязная.
function evil_git_dirty {
[[$ (git diff --shortstat 2> / dev / null | tail -n1)! = ""]] && echo "*"
}
Для неотслеживаемых файлов (обратите внимание на флаг - porcelain
для git status
, который дает хороший анализируемый вывод):
# Возвращает число неотслеживаемых файлов
function evil_git_num_untracked_files {
expr `git status --porcelain 2> / dev / null | grep "^ ??" | wc -l`
}
Хотя git diff --shortstat
более удобен, вы также можете использовать git status --porcelain
для получение грязных файлов:
# Get number of files added to the index (but uncommitted)
expr $(git status --porcelain 2>/dev/null| grep "^M" | wc -l)
# Get number of files that are uncommitted and not added
expr $(git status --porcelain 2>/dev/null| grep "^ M" | wc -l)
# Get number of total uncommited files
expr $(git status --porcelain 2>/dev/null| egrep "^(M| M)" | wc -l)
Примечание: 2> / dev / null
отфильтровывает сообщения об ошибках, поэтому вы можете использовать эти команды в каталогах, отличных от git. (Они просто вернут 0
для количества файлов.)
Изменить :
Вот сообщения:
Почему бы не инкапсулировать ' git status
скриптом, который:
Таким образом, вы можете использовать этот «расширенный» статус в своем скрипте.
Как 0xfe упоминает в своем отличном ответе , git status --porcelain
играет важную роль в любом решении, основанном на сценариях.
--porcelain
Дайте результат в виде стабильный, простой для анализа формат скриптов.
В настоящее время это идентично- краткий вывод
, но гарантированно не изменится в будущем, что делает его безопасным для сценариев.
Ключ к надежному« написанию сценариев »Git - это использование« сантехнических »команд.
При изменении сантехнических команд разработчики заботятся о том, чтобы они обеспечивали очень стабильные интерфейсы (т. Е. Заданная комбинация состояния репозитория, стандартного ввода, параметров командной строки, аргументов и т. Д. Будет давать одинаковый результат во всех версиях Git, где команда / параметр существует). Новые варианты вывода в командах сантехники могут быть введены с помощью новых параметров, но это не может создать никаких проблем для программ, которые уже были написаны для более старых версий (они не будут использовать новые параметры, поскольку они не существовали (или, по крайней мере, не использовались) на момент написания сценария).
К сожалению, «повседневные» команды Git являются «фарфоровыми» командами, поэтому большинство пользователей Git могут быть не знакомы с командами сантехники. Различие между фарфором и сантехникой. mmand выполняется на главной странице 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
может take - exclude-standard
, если вы хотите рассматривать только неотслеживаемые и не проигнорированные файлы.
Одна возможность самостоятельного изготовления, обновленная в соответствии с предложением 0xfe
#!/bin/sh
exit $(git status --porcelain | wc -l)
Как отметил Крис Джонсен , это работает только в Git 1.7.0 или новее.