Во-первых, давайте ответим на вопрос, который вы на самом деле задали, потому что вам все равно нужно это знать:
Как я могу сделать так, чтобы он проверял только код текущего коммита, который должен быть зафиксирован?
Содержимое коммита, который будет сделан, — это то, что находится в индексе.
Это каждый файл, а не только файлы, которые вы недавно git add
редактировали. Например, если в вашем рабочем дереве есть восемь файлов *.py
Python с контролируемым исходным кодом, и вы изменили и git add
отредактировали два из них, на этот раз будет зафиксировано восемь *.py
файлов. Каждая фиксация содержит каждый файл, а не набор изменений из какого-то предыдущего файла(ов).1
Чтобы проверить эти восемь файлов (а не текущее содержимое рабочего дерева), вам нужно где-то извлечь содержимое индекса.
Конечно, это не то, что вы на самом деле хотите:
на самом деле он проверяет всю ветку, и если он находит в ветке что-то, что не следует за pep8, он прекращает работу (этот репозиторий немного устарел, и некоторый код не следует за pep8 с самого начала, поэтому я знаю, что его можно реорганизовать, но я не нужен предварительный хук, чтобы сообщить мне об уже зафиксированном коде)
Опять же, на самом деле он не проверяет ветвь; он проверяет рабочее дерево. Хотя это не поможет вам сразу добраться туда, куда вам нужно, это важно.
Здесь нам нужно извлечь, возможно, из индекса файлы, которые отличаются от текущего коммита.
Способ сделать это — сделать новый коммит. В идеале мы могли бы сделать эту фиксацию не в текущей ветке, а в другом месте, потому что, если мы сделаем это в ветке, позже нам придется отменить ее снова.
Есть команда, которая делает это — делает коммиты из индекса, но не из ветки — и это команда git stash
. К сожалению, есть ошибка в git stash
, когда вы используете его таким образом. Вместо того, чтобы использовать обходные пути, которые я описываю в этом ответе, мы можем сделать что-то другое: мы можем создать собственное дерево во временном каталоге после сравнения текущего индекса с коммитом HEAD
.
Сценарий для этого (даже протестированный!) приведен ниже.
1Вы можете возразить, что git log -p
или git show
показывают вам изменения. Вы правы в том, что он показывает вам изменения, но делает это, запуская git diff
против предыдущего коммита, который также содержит все файлы. Сравнивая предыдущую версию «всего» со следующей версией «всего», git обнаруживает, что изменилось.
#! /bin/sh
# run-checks: run some checking command(s) on a proposed commit.
#
# Optionally, run it only on files that differ from those in
# the current commit (added or modified, treating rename as
# modify), and/or do not run it at all if there are
# no such files (e.g., if the commit consists only of file
# removals).
usage()
{
echo "usage: $0 [-d] checkcmd [args ...]" 1>&2
exit 1
}
# probably should use git rev-parse feature now, oh well
diffmode=false
skipempty=true
while true; do
case "$1" in
-d|--diff) diffmode=true; shift;;
-z|--run-even-if-empty) skipempty=false; shift;;
-dz) diffmode=true; skipempty=false; shift;;
*) break;;
esac
done
case "$#" in
0) usage;;
esac
# from here on, exit on error
set -e
# get temporary directory and arrange to clean it up
tdir=$(mktemp -d -t run-checks)
trap "rm -rf $tdir" 0 1 2 3 15
# Get list of changed files (whether or not we are using
# only the changed files). This includes deleted files.
# For efficiency, we treat renames as delete/add pairs here.
# Require that new commit not match current commit.
if test $(git diff --cached --name-only --no-renames HEAD | wc -l) -eq 0; then
echo "no changes to test before committing"
exit 1
fi
# Populate work tree in temp dir. If we only want changed
# files, limit the checkout to files added or modified. Note
# that this list might be empty.
if $diffmode; then
git diff --cached --name-only --no-renames --diff-filter=AM -z HEAD |
xargs -0 git --work-tree=$tdir checkout -f --
else
git --work-tree=$tdir checkout -f -- .
fi
# Now run checker in temp work tree. Our exit status is
# its exit status. Do not use exec since we must still clean
# up the temp dir, and optionally skip checker if work tree is empty.
cd $tdir
if test $(ls -A | wc -l) -eq 0; then
is_empty=true
else
is_empty=false
fi
if $skipempty && $is_empty; then exit 0; fi
if $is_empty; then
$@
else
$@ *
fi
person
torek
schedule
22.04.2016
git diff --staged --name-only
иgit checkout
+git apply
(по сути тайник). - person Anthony Sottile   schedule 20.09.2016