Может ли ловушка Git автоматически добавлять файлы в коммит? - PullRequest
53 голосов
/ 19 июля 2010

Я бы хотел добавить автоматически сгенерированный файл в тот же коммит, используя хук до или после фиксации в Git, в зависимости от файлов, которые были изменены в этом коммите. Как бы я пошел по этому поводу?

Я пробовал это как хук перед фиксацией, но не повезло:

#!/bin/sh
files=`git diff --cached --name-status`
re="<files of importance>"
if [[ $files =~ $re ]]
then
  echo "Creating files"
  exec bundle exec create_my_files
  exec git add my_files
  exec git commit --amend -C HEAD
fi

Это успешно добавляет их в репозиторий, но не добавляет их в коммит. Я также пытался использовать последние две строки exec в хуке post-commit вместе с проверкой перед фиксацией, но тоже ничего хорошего.

Ответы [ 10 ]

38 голосов
/ 09 октября 2012

Поскольку git add также не работал для меня при предварительной фиксации, я следовал идее Марка об использовании файла .commit и разделении процесса до и после фиксации.

Вот код, который должен быть прост для понимания

В предварительной фиксации:

  • Нажмите файл .commit или что-то. (обязательно добавьте это в .gitignore)
#!/bin/sh 
echo 
touch .commit 
exit

В пост-коммите:

если .commit существует, вы знаете, что фиксация только что произошла, но post-commit еще не запущен. Итак, вы можете сделать генерацию кода здесь. Кроме того, проверьте .commit и, если он существует:

  • добавить файлы
  • commit --amend -C HEAD --no-verify (избегать зацикливания)
  • удалить файл .commit
#!/bin/sh
echo
if [ -a .commit ]
    then
    rm .commit
    git add yourfile
    git commit --amend -C HEAD --no-verify
fi
exit

Надеюсь, это поможет людям с небольшим знанием bash следовать идее Марка.

30 голосов
/ 19 октября 2010

Можно делать то, что вы хотите, используя pre-commit hooks. Мы делаем нечто подобное для развертывания heroku (компилируем coffeescript в javascript). Причина, по которой ваш скрипт не работает, заключается в том, что вы неправильно использовали команду exec.

со страницы руководства :

Встроенная функция exec используется для замены текущего образа процесса оболочки на новую команду. При успешном завершении exec никогда не возвращается. exec нельзя использовать внутри конвейера.

Только ваша первая команда exec выполняется. После этого ваш скрипт в основном завершается.

Попробуйте что-то вроде этого (в качестве ловушки перед фиксацией):

#!/bin/sh
files=`git diff --cached --name-status`
re="<files of importance>"
if [[ $files =~ $re ]]
then
  echo "Creating files"
  bundle exec create_my_files
  git add my_files
fi
8 голосов
/ 17 апреля 2012

Вы можете использовать комбинацию скрипта до и после коммита.

В предварительной фиксации:

  • Коснитесь файла .commit или чего-то еще.(обязательно добавьте это в .gitignore)

В пост-коммите:

если .commit существует, вы знаете, что коммит только что произошел, но пост-фиксация не прошлапока не бегу.Итак, вы можете сделать генерацию кода здесь.Кроме того, проверьте .commit и, если он существует:

  • , добавьте файлы
  • commit --ammend -C HEAD --no-verify (избежать цикла)
  • удалить файл .commit

Это примерно тот процесс, который я использую для хранения файла .metadata в хранилище, сгенерированном из metastore.

Если кто-нибудь знает лучший способ, я всеуши, но, кажется, работает на данный момент.

6 голосов
/ 14 февраля 2013
#!/bin/sh
#
#  .git/hooks/pre-commit
#

git add file.xyz

Это прекрасно сработало для меня.Он будет частью текущего коммита.

git version 1.7.12.4 (Apple Git-37)

5 голосов
/ 19 июля 2010

Вы можете использовать update-index:

git update-index --add my_files

1 голос
/ 20 июля 2010

Как насчет написания скрипта post-commit, который генерирует ваши файлы, а затем имеет , что делает (что-то вроде) git add my_files; git commit --amend.

1 голос
/ 19 июля 2010

Если файлы генерируются автоматически, и они могут быть сгенерированы где угодно (подразумевается, что вы хотите встроить их в ловушку Git pre-commit), тогда вам не следует помещать их под контроль исходного кода. Вы должны контролировать только исходные файлы - сгенерированные файлы должны быть сгенерированы как часть сценариев сборки.

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

Добавлена ​​

С http://git -scm.com / docs / githooks :

pre-commit Этот хук вызывается git совершить, и может быть обойдено с Опция --no-verify. Он не принимает никаких параметров и вызывается раньше получение предложенного журнала коммитов сообщение и сделать коммит. Выход с ненулевым статусом из этого скрипта вызывает отмену коммита git.

Стандартный хук pre-commit, когда включен, ловит введение строк с замыкающими пробелами и прерываниями коммит, когда такая строка найдена.

Все git-коммиты запускаются с переменной среды GIT_EDITOR =: если команда не будет вызвать редактор, чтобы изменить сообщение коммита.

Цель ловушки перед фиксацией заключается в том, чтобы перед выполнением фиксации проверить состояние рабочего пространства и содержимое коммита. Попытка изменить содержимое коммита не будет работать.

Я рекомендую добавить два шага к вашим сценариям сборки: (1) шаг, который соберет все устаревшие файлы, которые необходимо сгенерировать (и добавит их в рабочее пространство), и (2) шаг, который проверит, чтобы убедиться, что все сгенерированные файлы обновлены и вернули ненулевой код состояния. Ваш Git pre-commit hook должен выполнить второй шаг. Ваши разработчики должны быть обучены запускать первый шаг по мере необходимости.

0 голосов
/ 08 ноября 2016

Я также столкнулся с той же проблемой в ловушке pre-commit. Я изменял один файл и делал коммит, но он брал предыдущий файл, а не обновленный файл, поэтому, добавив команду git (как показано ниже) в ловушку перед фиксацией, он решил.

git add $file

примечание: $file - это ваш файл для добавления.

Спасибо

0 голосов
/ 21 июля 2016

Да, вы можете автоматически добавлять сгенерированные файлы в коммит, используя git hooks!Но для этого нужен сложный сценарий.

Здесь вы можете найти решенную проблему.Там он обновляет версию файла при каждом коммите, добавляет новый измененный файл и вносит изменения в коммит по мере необходимости.Он полностью работает: https://github.com/evandrocoan/.versioning

Затем вы просто заменяете алгоритм «Замена файла версии» в файле «updateVersion.sh» своим алгоритмом.Может быть, вам нужно изменить несколько вещей, таких как, удалить ограничение ветки, потому что там, скрипт запускается только если вы находитесь в ветке 'Develop'.

Кроме того, он только изменит указанный файл, еслипоставил.Если файл не является промежуточным, он ничего не сделает, кроме обычного / обычного коммита.Точнее, он распечатывает, что он делает на каждом шагу.

Я собираюсь объяснить, этот трюк.Это довольно сложно.На методе prepare-commit-msg-hook он определяет, находится ли нужный файл в стадии размещения и фиксации.После этого он создает файл флагов и останавливает подготовку-фиксацию-msg-hook.Позже на post-commit-hook он проверяет, существует ли файл флага.Если да, то он исправляет файлы в коммите.

Внимание, это создаст бесконечный цикл, потому что он снова вызовет prepare-commit-msg-hook (как мы исправляем).Но это не происходит из-за файла флага.Когда выполняется prepare-commit-msg-hook и находит файл флага, он «знает», что происходит.Затем просто удаляет файл флага и не создает его снова.Делая это, он заблокирует post-commit-hook от повторного внесения изменений, что позволит завершить фиксацию навсегда.

0 голосов
/ 10 января 2012

У меня была такая же потребность, и этот подход работал довольно хорошо для меня:

#!/bin/sh
files='git diff --cached --name-only'
re="<files of importance>"
if [[ $files =~ $re ]]
then
   echo "Creating files"
   create_my_files && git add my_files
fi

, где «create_my_files» должен быть исполняемым, например, если это файл python, вы можете выполнить его как «python create_my_files»&& git add my_files "

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

...