Проверка на наличие грязного индекса или неотслеженных файлов с помощью Git
Как я могу проверить, есть ли у меня какие-либо незафиксированные изменения в моем репозитории git:
- изменения добавлены в индекс, но не совершенные
- Untracked files
из скрипта?
git-status кажется, всегда возвращает ноль с Git версии 1.6.4.2.
12 ответов:
замечательно! Я написал сообщение в блоге именно об этом несколько дней назад, когда я понял, как добавить информацию о статусе git в мою подсказку.
вот что я делаю:
для грязного статус:
# Returns "*" if the current git branch is dirty. function evil_git_dirty { [[ $(git diff --shortstat 2> /dev/null | tail -n1) != "" ]] && echo "*" }для неотслеженных файлов (обратите внимание на
--porcelainфлагgit statusчто дает вам хороший разбор-способный вывод):# Returns the number of untracked files 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для файлов.)Edit:
вот такие сообщения:
добавление информации о состоянии Git в приглашение терминала
ключ к надежному "сценарию" Git-использовать команды "сантехника".
разработчики заботятся при изменении команд сантехники, чтобы убедиться, что они обеспечивают очень стабильные интерфейсы (т. е. заданную комбинацию состояния репозитория, stdin, параметров командной строки, аргументов и т. д. будет производить тот же вывод во всех версиях Git, где существует команда/опция). Новые варианты вывода в командах сантехники могут быть введены с помощью новых опций, но это не может ввести никаких проблемы для программ, которые уже были написаны против старых версий (они не будут использовать новые параметры, так как они не существовали (или, по крайней мере, не использовались) на момент написания сценария).
к сожалению, "повседневные" команды Git - это команды "фарфор", поэтому большинство пользователей Git могут быть не знакомы с командами сантехники. Различие между фарфором и сантехникой команды производится в основном git manpage (см. подразделы под названием команды высокого уровня (фарфор) и команды низкого уровня (сантехника).
чтобы узнать о несогласованных изменениях, вам, вероятно, понадобится
git diff-index(сравните индекс (и, возможно, отслеживаемые биты рабочего дерева) против некоторых других деревьев (например,HEAD)), можетgit diff-files(сравнить рабочее дерево с индексом), и, возможно,git ls-files(list files; например, list untracked, unignored архив.)(обратите внимание, что в приведенных ниже командах,
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). В этой же ситуации две отдельные команды будут возвращать отчеты о "существующих различиях".Вы упомянули неотслеживаемый файлы. Вы может имеете в виду "неотслеживаемые и unignored", или вы имели ввиду просто "неотслеживаемые" (включая игнорируемые файлы). В любом случае,
git ls-files- это инструмент для работы:для " untracked "(будет включать игнорируемые файлы, если присутствует):
git ls-files --othersдля "untracked and unignored":
git ls-files --exclude-standard --othersмоя первая мысль - просто проверить, имеют ли эти команды выход:
test -z "$(git ls-files --others)"
- если он выходит с
0тогда нет никаких неотслеженных файлов. Если он выходит с есть неотслеживаемый файлы.есть небольшой шанс, что это будет ненормальным выходы из
git ls-filesв отчеты" нет неотслеженных файлов " (оба результата не равны нулю выходы из приведенной выше команды). Немного более надежная версия может выглядеть так:u="$(git ls-files --others)" && test -z "$u"
- идея такая же, как и предыдущая команда, но она допускает неожиданные ошибки от
git ls-filesдля распространения. В этом случае ненулевой выход может означать "есть неотслеженные файлы" или это может означать, что произошла ошибка. Если вы хотите, чтобы результаты" error "сочетались с результатом" no untracked files", используйтеtest -n "$u"(где выход0означает "некоторые неотслеженные файлы", и ненулевое значение означает ошибку или"нет неотслеженных файлов").еще одна идея заключается в использовании
--error-unmatchчтобы вызвать ненулевой выход, когда нет неотслеженных файлов. Это также рискует объединить "нет неотслеженных файлов" (exit1) С "произошла ошибка "(выход ненулевой, но, вероятно,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если вы хотите рассматривать только неотслеженные и неориентированные файлы.
предполагая, что вы находитесь на git 1.7.0 или более поздней версии...
после прочтения всех ответов на этой странице и некоторых экспериментов, я думаю, что метод, который поражает правильное сочетание правильности и краткости:
test -n "$(git status --porcelain)"в то время как git позволяет много нюансов между тем, что отслеживается, игнорируется, не отслеживается, но не отображается и т. д., Я считаю, что типичный случай использования-это автоматизация сценариев сборки, где вы хотите остановить все, если ваша проверка не является чистый.
в этом случае имеет смысл смоделировать то, что сделал бы программист: введите
git statusи посмотрите на результат. Но мы не хотим полагаться на конкретные слова, поэтому мы используем--porcelainрежим, введенный в 1.7.0; когда включено, чистый каталог не приводит к выходу.затем мы используем
test -nчтобы увидеть, был ли какой-либо выход или нет.эта команда вернет 1, если рабочий каталог чист и 0, если есть изменения, которые необходимо зафиксировать. Вы можно изменить
-nдо-zесли вы хотите наоборот. Это полезно для связывания этого с командой в скрипте. Например:test -z "$(git status --porcelain)" || red-alert "UNCLEAN UNCLEAN"это фактически говорит: "либо нет никаких изменений, которые нужно сделать, либо установить будильник"; этот однострочный может быть предпочтительнее оператора if в зависимости от сценария, который вы пишете.
реализация от VonC'ы ответ:
if [[ -n $(git status --porcelain) ]]; then echo "repo is dirty"; fi
просмотрел несколько из этих ответов... (и были различные проблемы на *nix и windows, что было требованием, которое у меня было)... нашел следующее работает хорошо...
git diff --no-ext-diff --quiet --exit-codeчтобы проверить код выхода в *nix
echo $? #returns 1 if the repo has changes (0 if clean)чтобы проверить код выхода в окно$
echo %errorlevel% #returns 1 if the repos has changes (0 if clean)получены из https://github.com/sindresorhus/pure/issues/115 Спасибо @paulirish на этом посту для обмена
Почему бы не инкапсулировать '
git statusсценарий которых:
- проанализирует вывод этой команды
- вернет соответствующий код ошибки на основе того, что вам нужно
таким образом, вы можете использовать этот "расширенный" статус в своем скрипте.
как 0xfe упоминает в своей отличный ответ!--17-->,
git status --porcelainиграет важную роль в любом скриптовом решении--porcelainдайте выход в стабильном, простом для разбора формате для скриптов.
В настоящее время это идентично--short output, но гарантированно не изменится в будущем, что делает его безопасным для скриптов.
одна из возможных поделок, на 0xfe'предложение з
#!/bin/sh exit $(git status --porcelain | wc -l)Как отмечает Крис Йонсен, это работает только на Git 1.7.0 или новее.
это более удобный вариант оболочки для выяснения, если любой в репозитории существуют неотслеживаемые файлы:
# Works in bash and zsh if [[ "$(git status --porcelain 2>/dev/null)" = *\?\?* ]]; then echo untracked files fiэто не вилка второй процесс,
grep, и не нужно проверять, находитесь ли вы в репозитории git или нет. Что удобно для подсказок оболочки и т. д.
вы также можете сделать
git describe --dirty. Он добавит слово "- грязный " в конце, если он обнаруживает грязное рабочее дерево. Согласно
git-describe(1):--dirty[=<mark>] Describe the working tree. It means describe HEAD and appends <mark> (-dirty by default) if the working tree is dirty.. Предостережение: неотслеженные файлы не считаются "грязными", потому что, как говорится в manpage, он заботится только о рабочем дереве.
там может быть лучшее сочетание ответов из этой темы.. но это работает для меня... для вашего
.gitconfig' s ...# git untracked && echo "There are untracked files!" untracked = ! git status --porcelain 2>/dev/null | grep -q "^??" # git unclean && echo "There are uncommited changes!" unclean = ! ! git diff --quiet --ignore-submodules HEAD > /dev/null 2>&1 # git dirty && echo "There are uncommitted changes OR untracked files!" dirty = ! git untracked || git unclean
самый простой автоматический тест, который я использую для обнаружения состоянии = любые изменения, включая неотслеженные файлы:
git add --all git diff-index --exit-code HEADПримечание:
- без
add --alldiff-indexне замечает неотслеживаемый файлы.- обычно, я бегу
git resetпосле тестирования кода ошибки, чтобы unstage все обратно.
вот лучший, самый чистый способ. Выбранный ответ по какой-то причине не работал для меня, он не принимал изменений, которые были новыми файлами, которые не были зафиксированы.
function git_dirty { text=$(git status) changed_text="Changes to be committed" untracked_files="Untracked files" dirty=false if [[ ${text} = *"$changed_text"* ]];then dirty=true fi if [[ ${text} = *"$untracked_files"* ]];then dirty=true fi echo $dirty }
Comments