Узнайте подготовленные файлы в хуке git `pre-commit` при использовании `git commit -a`

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

git commit -a ..

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

Есть ли способ:

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

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

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


person knub    schedule 24.01.2019    source источник


Ответы (1)


потому что файлы еще не поставлены

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

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

$ 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 adding:

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

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

$ 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 в (основном/реальном/.git/index) индексе, а не версия в рабочем состоянии. дерево. Следовательно, если вы хотите проверить файлы, которые будут зафиксированы, вам следует заглянуть в файл 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 действительно работают внутри компании.)

person torek    schedule 24.01.2019