Проверка на наличие грязного индекса или неотслеженных файлов с помощью Git



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




  1. изменения добавлены в индекс, но не совершенные

  2. Untracked files


из скрипта?



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

790   12  

12 ответов:

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

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

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

    # Returns "*" if the current git branch is dirty.
    function evil_git_dirty {
      [[ $(git diff --shortstat 2> /dev/null | tail -n1) != "" ]] && echo "*"
    }
    
  2. для неотслеженных файлов (обратите внимание на --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 с поддержкой командной строки

ключ к надежному "сценарию" 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 чтобы вызвать ненулевой выход, когда нет неотслеженных файлов. Это также рискует объединить "нет неотслеженных файлов" (exit 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 если вы хотите рассматривать только неотслеженные и неориентированные файлы.

предполагая, что вы находитесь на 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

    Ничего не найдено.