Самый быстрый способ получить статус git в bash
Некоторое время я использовал функцию __git_ps1
в своем приглашении bash PS1
(с PS1='\w$(__git_ps1)'
). Теперь я хочу покрасить его в зависимости от ветки
положение дел.
Я написал функцию bash, которая проверяет, изменена ли текущая ветка, и
цвета красного или белого цвета в зависимости от состояния. Проблема в том, что он использует git
status
для проверки состояния (это единственный способ, которым я знаю), и что несколько
раза медленнее, чем __git_ps1
, что достаточно, чтобы вызвать раздражающую задержку, когда
Я использую подсказку (у меня очень слабый нетбук).
Итак, я спрашиваю: есть ли более быстрый способ проверить состояние текущей папки git?
__git_ps1
намного быстрее, чем ручная разборка git branch
, поэтому я думаю
может быть какая-то другая скрытая функция git.
Ответы
Ответ 1
Не совсем ваш ответ, но bash -completion имеет этот встроенный модуль.
Если вы установите значение bash ENV GIT_PS1_SHOWDIRTYSTATE на непустое значение, рядом с именем ветки будут показаны неустановленные (*) и поэтапные (+) изменения. Вы можете настроить этот репозиторий с переменной bash.showDirtyState, которая по умолчанию имеет значение true, когда включена функция GIT_PS1_SHOWDIRTYSTATE.
Вы также можете увидеть, если в настоящее время что-то спрятано, установив GIT_PS1_SHOWSTASHSTATE на непустое значение. Если что-то спрятано, то рядом с именем ветки будет отображаться "$".
Если вы хотите посмотреть, есть ли файлы без следа, вы можете установить GIT_PS1_SHOWUNTRACKEDFILES на непустое значение. Если есть необработанные файлы, тогда рядом с именем ветки будет показано "%".
Не уверен, что скорость ухудшится, если вы включите это.
Если вы хотите сделать раскраску:
Поэтажные файлы:
if git rev-parse --quiet --verify HEAD >/dev/null; then
git diff-index --cached --quiet HEAD -- || color for staged changes
else
color unstaged changes
fi
Спрятанные файлы
git rev-parse --verify refs/stash >/dev/null 2>&1 && color for stashed files
Отслеживаемые файлы
if [ -n "$(git ls-files --others --exclude-standard)" ]; then
Color untrack files
fi
Вышеприведенные фрагменты взяты из bash -completion script.
Ответ 2
git diff --quiet
возвращает 1, если в рабочий каталог есть изменения, а git diff --quiet --cached
делает то же самое для индекса.
Вы можете использовать его:
git diff --quiet
|| echo "There be changes!"
Ответ 3
Примечание: Git 2.6+ (Q3 2015) должен ускорить этот статус __git_ps1
:
См. commit dd160d7, совершить 6bfab99 (19 июля 2015) SZEDER Gábor (szeder
).
(слияние Junio C Hamano - gitster
- в совершить 461c119, 03 августа 2015 г.)
bash prompt: быстрый индикатор отсутствия слежения с неподготовленными каталогами
Если индикатор состояния без следа включен, __git_ps1()
ищет ненужные файлы, запустив 'git ls-files
'.
Это может быть заметно медленным в случае отсутствия следящей директории, содержащей много файлов, потому что в ней перечислены все файлы, найденные в нетрезвом каталоге, только для прямого перенаправления на /dev/null
.
Это фактическая команда, выполняемая __git_ps1()
:
$ ls untracked-dir/ |wc -l
100000
$ time git ls-files --others --exclude-standard --error-unmatch \
-- ':/*' >/dev/null 2>/dev/null
real 0m0.955s
user 0m0.936s
sys 0m0.016s
Устранить эту задержку, добавив опцию '--directory --no-empty-directory
' в 'git ls-files
', чтобы отображать только имя непустых неподготовленных каталогов вместо всего их содержимого:
$ time git ls-files --others --exclude-standard --directory \
--no-empty-directory --error-unmatch -- ':/*' >/dev/null 2>/dev/null
real 0m0.010s
user 0m0.008s
sys 0m0.000s
Это следует за выражением ea95c7b (завершение: улучшить невоспроизводимый каталог фильтрация для завершения имени файла, 2013-09-18, Git 1.8.5).
Ответ 4
! git diff-index --cached --quiet HEAD # fastest staged-changes test
! git diff-files --quiet # fastest unstaged-changes test
! git diff-index --quiet HEAD # fastest any-changes test
stdbuf -oL git ls-files -o | grep -qs . # fastest untracked-files test
git rev-parse -q --verify refs/stash >&- # fastest any-stash test
Если игнорируемое состояние имеет значение для неотслеживаемых файлов, используйте --exclude-standard -oi
для неотслеживаемого игнорируемого и --exclude-standard -o
для неотслеживаемого и игнорируемого.
Самый быстрый способ, которым я знаю, чтобы получить заголовок HEAD (название ветки или ша)
{ git symbolic-ref -q --short HEAD || git rev-parse -q --short --verify HEAD; } 2>&-
который оставляет код возврата, если вы не в репо, так что вы можете, например,
if HEAD='{ git symbolic-ref -q --short HEAD || git rev-parse -q --verify HEAD; } 2>&-'
then
: in a git repo, $HEAD is the branch name or sha
fi
ЗАМЕТЬТЕ, что тест с неотслеживаемыми файлами зависит от запуска с shopt -s lastpipe
для bash
. zsh
и ksh
работают таким образом по умолчанию.
Ответ 5
Я использую Ksh и у меня та же проблема. В довершение ко всему, мои репозитории Git находятся на монтируемых NFS, что делает время отклика еще медленнее.
Чтобы напрямую ответить на вопрос о скорости, попробуйте использовать:
git ls-files -m
кажется намного быстрее, чем "git status -s", после первого входа в другой репозиторий. Оказавшись в репозитории, кэширование ОС и NFS значительно ускоряет выполнение этой команды. Эта команда также кажется очень быстрой, когда глубоко внутри нижних листьев дерева рабочих каталогов git.
Ответ 6
Вам всегда нужно вызывать git --porcelain
или что-то в этом роде, чтобы получить информацию о статусе. Так что единственный способ сделать это быстро - вызвать git
только один раз и убедиться, что обработка выполняется максимально быстро.
Я написал очень быстрый git-статус в C++ с максимальной оптимизацией. Он даже имеет параметр --refresh-sec
который позволит избежать дополнительных вызовов git
если предыдущий вызов был меньше, чем --refresh-sec
несколько секунд назад. Я думаю, что это самый быстрый способ сделать это.
Это для Zsh, но вы можете адаптировать его для Bash. И это очень быстро: https://gitlab.com/cosurgi/zsh-git-cal-status-cpp