Git Post-Receive Hook для создания сайта - PullRequest
59 голосов
/ 01 октября 2010

Я пытаюсь настроить Git для размещения моего веб-сайта, чтобы я мог git pull заставить текущую версию работать локально, а затем git push передать изменения на удаленный сервер. Я настроил его так, чтобы он работал так, как я хочу, но после нажатия мне нужно вручную запустить git checkout -f или git reset --hard HEAD на удаленном сервере.

Я пытался поместить их в сценарий оболочки в качестве перехвата после получения на сервере, но, похоже, это не дает никакого эффекта. Я знаю, что скрипт запущен, потому что я вижу "Изменения отправлены на сервер" после нажатия. Вот крюк после получения:

#!/bin/sh
git reset --hard HEAD
echo "Changes pushed to server."

Ответы [ 6 ]

73 голосов
/ 01 октября 2010

Ответ на ваш вопрос здесь: http://toroid.org/ams/git-website-howto

Короче говоря, вы хотите добавить «отдельное рабочее дерево» в пустой репозиторий.Обычно вы считаете, что ваше рабочее дерево содержит каталог .git.Голые репозитории не имеют рабочего дерева по определению, но вы можете создать его, если оно находится в другом каталоге, чем обычное хранилище.

Хук пост-получения - это просто git checkout -f для репликациирепозиторий HEAD в рабочий каталог.Apache использует его в качестве корня документа, и все готово.Каждый раз, когда вы перемещаетесь в пустой репозиторий, Apache сразу же начинает его обслуживать.

Я обычно использую это для автоматического перехода на промежуточный сервер, чтобы посмотреть, будет ли "реальная" среда влиять на мои изменения.Развертывание на живом сервере - это совсем другая история.: -)

15 голосов
/ 01 октября 2010

Обновление март 2015

Как я уже упоминал в " Что это за предупреждающее сообщение Git при отправке изменений в удаленный репозиторий? ", вы на самом деле можете нажать напрямую в репозиторий без обнажения (Git 2.3.0+, февраль 2015 г.) с:

git config receive.denyCurrentBranch updateInstead

Обновите рабочее дерево соответствующим образом, но откажитесь сделать это, если есть какие-либо незафиксированные изменения.

Это позволит вам избежать хука после получения.


(Оригинальный ответ: октябрь 2010 г.)

GitFAQ рекомендует для non-bare repo этот хук после обновления:
(он может дать вам больше информации о том, что на самом деле происходит в выполнении хука. Обратите внимание, что это хук после обновления, а непост-получение)

#!/bin/sh
#
# This hook does two things:
#
#  1. update the "info" files that allow the list of references to be
#     queries over dumb transports such as http
#
#  2. if this repository looks like it is a non-bare repository, and
#     the checked-out branch is pushed to, then update the working copy.
#     This makes "push" function somewhat similarly to darcs and bzr.
#
# To enable this hook, make this file executable by "chmod +x post-update".

git-update-server-info

is_bare=$(git-config --get --bool core.bare)

if [ -z "$is_bare" ]
then
    # for compatibility's sake, guess
    git_dir_full=$(cd $GIT_DIR; pwd)
    case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac
fi

update_wc() {
    ref=$1
    echo "Push to checked out branch $ref" >&2
    if [ ! -f $GIT_DIR/logs/HEAD ]
    then
        echo "E:push to non-bare repository requires a HEAD reflog" >&2
        exit 1
    fi
    if (cd $GIT_WORK_TREE; git-diff-files -q --exit-code >/dev/null)
    then
        wc_dirty=0
    else
        echo "W:unstaged changes found in working copy" >&2
        wc_dirty=1
        desc="working copy"
    fi
    if git diff-index --cached HEAD@{1} >/dev/null
    then
        index_dirty=0
    else
        echo "W:uncommitted, staged changes found" >&2
        index_dirty=1
        if [ -n "$desc" ]
        then
            desc="$desc and index"
        else
            desc="index"
        fi
    fi
    if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ]
    then
        new=$(git rev-parse HEAD)
        echo "W:stashing dirty $desc - see git-stash(1)" >&2
        ( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT
        git-update-ref --no-deref HEAD HEAD@{1}
        cd $GIT_WORK_TREE
        git stash save "dirty $desc before update to $new";
        git-symbolic-ref HEAD "$ref"
        )
    fi

    # eye candy - show the WC updates :)
    echo "Updating working copy" >&2
    (cd $GIT_WORK_TREE
    git-diff-index -R --name-status HEAD >&2
    git-reset --hard HEAD)
}

if [ "$is_bare" = "false" ]
then
    active_branch=`git-symbolic-ref HEAD`
    export GIT_DIR=$(cd $GIT_DIR; pwd)
    GIT_WORK_TREE=${GIT_WORK_TREE-..}
    for ref
    do
        if [ "$ref" = "$active_branch" ]
        then
            update_wc $ref
        fi
    done
fi

Чтобы это работало, вам все равно нужно специально разрешить отправку изменений в текущую ветку, используя один из следующих параметров конфигурации:

git config receive.denyCurrentBranch ignore

или

git config receive.denyCurrentBranch warn
11 голосов
/ 04 января 2012

У меня была точно такая же проблема. В ответ на эту ссылку: http://toroid.org/ams/git-website-howto - это сделала следующая команда:

sudo chmod +x hooks/post-receive

Мы пропустили разрешение sudo, сначала настроили материал.

6 голосов
/ 10 июля 2013

Простой скрипт для настройки этого git-развертывания:

Подготовка крюка после получения:

echo '#!/bin/sh'        >  .git/hooks/post-receive
echo 'git checkout -f'  >> .git/hooks/post-receive
echo 'git reset --hard' >> .git/hooks/post-receive
chmod +x .git/hooks/post-receive

Позволяет вставить в этот репозиторий, хотя он не голый:

git config receive.denycurrentbranch false
6 голосов
/ 27 июля 2012

Исправлена ​​версия скрипта VonC, у меня работает (абсолютно никаких гарантий).

1 голос
/ 01 октября 2010

Я просто догадываюсь, но это может быть проблема с разрешением (нужен полный путь? cd?). Проверьте, что действительно происходит в файлах журнала.

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

Для сложного решения сборочный скрипт может быть лучше, чем любой git hook. Инструменты, которые могут очень хорошо справиться с этими задачами:

(я понимаю, что это не тот ответ, который вы ожидаете, но его слишком долго публиковать в качестве комментария)

...