Проверка грязный индекс или неотслеженные файлы с Мерзавцем

Как может я проверять, есть ли у меня какие-либо незафиксированные изменения в моем репозитории мерзавца:

  1. Изменения, добавленные к индексу, но не фиксировавший
  2. Неотслеженные файлы

из сценария?

git-status кажется, всегда возвращает нуль с версией 1.6.4.2 мерзавца.

236
задан Robert Munteanu 16 April 2010 в 22:41
поделиться

4 ответа

Отличное время! Я написал об этом сообщение в блоге несколько дней назад, когда выяснил, как добавить информацию о статусе git в мою подсказку.

Вот что я делаю:

  1. Для грязного статуса:

     # Возвращает "*", если текущая ветка git грязная.
    function evil_git_dirty {
     [[$ (git diff --shortstat 2> / dev / null | tail -n1)! = ""]] && echo "*" 
    } 
     
  2. Для неотслеживаемых файлов (обратите внимание на флаг - 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 в подсказку терминала

Улучшено Подсказка оболочки с включенной функцией Git

167
ответ дан 23 November 2019 в 03:24
поделиться

Почему бы не инкапсулировать ' git status скриптом, который:

  • проанализирует вывод этой команды,
  • вернет соответствующий код ошибки в зависимости от того, что вам нужно

Таким образом, вы можете использовать этот «расширенный» статус в своем скрипте.


Как 0xfe упоминает в своем отличном ответе , git status --porcelain играет важную роль в любом решении, основанном на сценариях.

--porcelain

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

4
ответ дан 23 November 2019 в 03:24
поделиться

Ключ к надежному« написанию сценариев »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 , если вы хотите рассматривать только неотслеживаемые и не проигнорированные файлы.

388
ответ дан 23 November 2019 в 03:24
поделиться

Одна возможность самостоятельного изготовления, обновленная в соответствии с предложением 0xfe

#!/bin/sh
exit $(git status --porcelain | wc -l) 

Как отметил Крис Джонсен , это работает только в Git 1.7.0 или новее.

4
ответ дан 23 November 2019 в 03:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: