Найдите промежуточные файлы в ловушке git `pre-commit` при использовании` git commit -a` - PullRequest
0 голосов
/ 24 января 2019

Я использую хук git pre-commit, чтобы автоматически форматировать все мои подготовленные файлы.Я определяю подготовленные файлы с помощью git diff --name-only --cached, а затем вызываю скрипт для этих файлов.Все это хорошо работает в стандартном случае использования, однако оно не работает, когда я фиксирую через

git commit -a ..

, потому что файлы еще не подготовлены.

Есть ли какой-то способ:

  1. Запустить эффект -a (добавить файлы в область подготовки) перед хуком pre-commit?

  2. Узнать, что предварительная фиксацияработает в -a коммите?

Должен быть способ справиться с этим.

1 Ответ

0 голосов
/ 24 января 2019

, поскольку файлы еще не подготовлены

На самом деле это не совсем так.Но это также не совсем неверно.

Вот (глупый, предназначенный только для иллюстрации) хук предварительной фиксации, чтобы продемонстрировать проблему:

$ cat .git/hooks/pre-commit
#! /bin/sh
echo \$GIT_INDEX_FILE = $GIT_INDEX_FILE
git diff-index --cached --name-only HEAD
exit 1

Этот хук использует правильный (изв любом случае перспектива надежности), git diff-index --cached HEAD, чтобы найти имена промежуточных файлов.Однако сначала он печатает имя индекса, который используется для фиксации файлов.(Наконец, это предотвращает фиксацию, поскольку я не хочу ничего фиксировать.)

Я сделал этот исполняемый файл (в Git-репозитории для самого Git) и изменил несколько файлов без git add ing ing:

$ git status --short
 M Makefile
 M wt-status.c

(обратите внимание, что M s во втором столбце).Затем:

$ git commit
$GIT_INDEX_FILE = .git/index
$ git commit -a
$GIT_INDEX_FILE = [redacted]/.git/index.lock
Makefile
wt-status.c

Первый вызов ловушки echo говорит нам, что мы используем реальный (основной) индекс, а его git diff-index не производит вывода.

Второй вызовговорит нам, что мы используем альтернативный индексный файл с именем .git/index.lock (я обрезал исходный путь).Он показывает два поэтапных файла.

Давайте продолжим делать еще одну вещь: я git add изменил Makefile и внесу второе изменение в Makefile.Теперь у нас есть:

$ git status --short
MM Makefile
 M wt-status.c

Первая строка показывает нам, что HEAD:Makefile (в коммите, заморожено) отличается от :Makefile (в индексе, поэтапно), который отличается от Makefile (врабочее дерево, без обработки), и действительно, мы видим, что три файла различны:

$ git show HEAD:Makefile | head -2
# The default target of this Makefile is...
all::
$ git show :Makefile | head -2
#
# The default target of this Makefile is...
$ head -2 Makefile
# different
# The default target of this Makefile is...

Запуск git commit против git commit -a теперь выдает:

$ git commit
$GIT_INDEX_FILE = .git/index
Makefile
$ git commit -a
$GIT_INDEX_FILE = [redacted]/.git/index.lock
Makefile
wt-status.c

Если яне помешали не -a версии git commit, что было бы зафиксировано git commit является версией Makefile в (main / real / .git/index) индексе,не версия в рабочем дереве.Следовательно, если вы хотите проверить файлы, которые будут зафиксированы, вы должны посмотреть в индексе.Вы можете использовать git checkout-index для извлечения файлов из индекса, но будьте осторожны, чтобы не забить версии рабочего дерева, которые могут отличаться.

Что было бы зафиксировано git commit -a, так этоверсия Makefile в рабочем дереве, которую Git уже добавил в (нестандартный, временный) индекс .git/index.lock.Когда git commit -a закончится, этот нестандартный временный индекс станет реальным индексом, уничтожив мою промежуточную специальную поэтапную копию Makefile.Опять же, чтобы проверить файлы, которые будут зафиксированы, посмотрите в индекс - используя перенаправленный индекс, как Git автоматически, для git diff-index и git checkout-index.

(Так как я не совсем понимаю, чтоВаш сценарий нуждается, я не могу дать конкретные рекомендации о том, как именно использовать git checkout-index для извлечения интересующих файлов. Однако рассмотрите возможность использования --work-tree= и временного каталога.)

(См. также мой ответна Пропустить прошедшую (полную) область подготовки и зафиксировать файл или патч напрямую? , в котором обсуждается, что на самом деле -a, --only и --include действительно делают внутри.)

...