я сделал следующий скрипт bash для фиксации родительского репо после некоторых изменений в подмодуле. все дело в том, что скрипт хочет cd .. проверить текущую ветку родительского репо, но проблема в том, что cd .. не влияет на предстоящие команды, потому что я предполагаю, что подоболочка
я пытался бежать 1- cd ../ && перед каждой командой 2- сделать псевдоним, но не получилось 3- запустить exec, но скрипт не продолжился
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "post-commit".
commit_msg= git log -1 --pretty=%B
if [[ $(git branch | grep \* | cut -d ' ' -f2) == "int1177/next" ]]; then
cd ..
if [[ $(git branch | grep \* | cut -d ' ' -f2) == "B0/next" ]]; then
git add 6_Tests
git commit -m "bs esss"
echo "development branch B0/next has now new commit"
else
echo "development branch isn't B0/next"
fi
else
echo "current branch isn't int1177/next"
fi
Простая идея состоит в том, чтобы ваша интерактивная оболочка контролировала текущий каталог на наличие файла и source
, а затем удаляла его, если он существует. Это достаточно просто, но, конечно, не совсем беспроблемно (безопасность? Угловые случаи, например, что, если несколько интерактивных оболочек имеют один и тот же рабочий каталог?)
я пытался создать файл foo.sh внутри репозитория и добавил в источник хука foo.sh, но он тоже не работает ... это то, что вы подразумеваете под интерактивным монитором оболочки?
Я повторяю: хук не может изменить среду родительской оболочки, в которой вы запускаете Git. Вы должны заставить свою интерактивную оболочку каким-то образом взаимодействовать с хуком — тем, который отображает подсказку и позволяет вам вводить команды, такие как git commit
. Если вы используете Bash, возможно, стоит добавить что-нибудь в PROMPT_COMMAND
.
На самом деле, эта конкретная проблема связана не с bash, а с Git.
Почему «cd» не работает в сценарии оболочки? в целом действителен и является подходящим ответом на многие вопросы разное. Но этот конкретный post-commit
хук пытается chdir
выйти из подмодуля в его родительский суперпроект, а затем сделать фиксацию внутри родительского суперпроекта. Это является возможно. Это может быть плохой идеей по другим причинам — в общем случае неразумно заставлять обработчики коммитов Git создавать коммиты, даже в других репозиториях1 — но в данном конкретном случае вы сталкиваетесь с тем фактом, что Git находит свои каталоги через переменные среды.
В частности, есть переменная среды GIT_DIR
, которая сообщает Git: Каталог .git
, содержащий репозиторий, находится по этому пути. Когда Git запускает хук Git, Git обычно устанавливает $GIT_DIR
на .
или .git
. Если $GIT_DIR
установлен нет, Git найдет каталог .git
с помощью поиска в дереве каталогов, но если установлен $GIT_DIR
является, Git предполагает, что $GIT_DIR
установлен правильно.
Решение снят с охраныGIT_DIR
:
unset GIT_DIR
cd ..
Остальные команды подоболочки будут выполняться в каталоге на один шаг вверх, и теперь, когда $GIT_DIR
больше не установлено, Git будет искать в рабочем дереве суперпроекта каталог .git
для суперпроекта.
Попутно это:
$(git branch | grep \* | cut -d ' ' -f2)
это неуклюжий способ получить имя текущей ветки. Использовать:
git rev-parse --abbrev-ref HEAD
вместо этого здесь. (Другой вариант — git symbolic-ref --short HEAD
, но он не работает с отсоединенным HEAD, в то время как вы, вероятно, хотите, чтобы тихий результат был просто словом HEAD
, которое выдаст метод rev-parse
.)
1Основная опасность в случае с это заключается в том, что репозиторий суперпроекта не обязательно в состоянии обрабатывать коммит прямо сейчас. Редактировать: или, как обнаружено в этот комментарий, даже не настроен на быть суперпроект для этого подмодуля, тем более для добавления фиксации обновления подмодуля.
Большое спасибо, что касается упомянутой вами повышенной опасности, вы правы, если ветка int1177/next является нормальной веткой. однако это специальная ветвь (ветвь интеграции), в которой только интегратор имеет доступ к фиксации и фиксирует или объединяет только при добавлении или интеграции новой функции.
я пробовал, и у меня это работает, но возникает другая проблема: выполнение git add 6_Tests
создание подмодуля 6_Tests в 6_Tests со следующим предупреждением в журнале: warning: adding embedded git repository: 6_Tests hint: You've added another git repository inside your current repository. hint: Clones of the outer repository will not contain the contents of hint: the embedded repository and will not know how to obtain it. hint: If you meant to add a submodule, use: hint: git submodule add <url> 6_Tests hint: If you added this path by mistake, you can remove it
Эти сообщения (о добавлении репозитория git, который еще не настроен как подмодуль) означают, что суперпроект еще не готов иметь подмодуль — он еще не настроен. Это еще одна опасность подобных вещей.
Выполнение вложенного вызова git в очищенной подоболочке, например. ( eval unset ${!GIT_*}; your; commands; here)
может быть лучшим планом, Git может установить другие, если не сейчас, то в будущем выпуске..
@jthill: возможно, да. Однако неясно, будет ли правильным просто произвольное удаление переменных всеGIT_*
.
Я думаю, что эти вары обязательно установлены для текущего репо, а не для того, на который предназначены вложенные команды.
... Итак, прошло шесть недель, и мой задний мозг наконец понял, что вы говорите: вы не хотите сбрасывать такие вещи, как GIT_EDITOR
и GIT_DISCOVERY_ACROSS_FILESYSTEMS
, если у пользователя они установлены, вы должны использовать $(git rev-parse --local-env-vars)
вместо ${!GIT_*}
. Верно.
@jthill: Верно, но я не знал, что --local-env-vars
существует, это довольно мило!
Git запускает хук в подоболочке, и в этот момент нет возможности изменить окружение родительской оболочки напрямую. Вы должны организовать так, чтобы родительская оболочка каким-то образом получала инструкции от вашего хука. Это не невозможно, но и совсем не тривиально.