Git Post-Receive Hook для создания сайта

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

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

#!/bin/sh
git reset --hard HEAD
echo "Changes pushed to server."
 takeshin01 окт. 2010 г., 15:15
@VonC: самая важная частьваш ответ было написано в основном вbash язык, в то время как downvoter, вероятно, утверждал свой родной;)

Ответы на вопрос(6)

http://toroid.org/ams/git-website-howto - Следующая команда сделала это:

sudo chmod +x hooks/post-receive

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

у меня работает (абсолютно никаких гарантий).

#!/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".

set -e

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 [email protected]{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 [email protected]{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
    # need to touch some files or restart the application? do that here:
    # touch *.wsgi
    )

}

if [ x"${is_bare}" = x"false" ]
then
    active_branch=$(git symbolic-ref HEAD)
    export GIT_DIR=$(cd ${GIT_DIR}; pwd)
    GIT_WORK_TREE="${GIT_DIR}/.."
    for ref in $(cat)
    do
        if [ x"$ref" = x"${active_branch}" ]
        then
            update_wc $ref
        fi
    done
fi
 VonC27 июл. 2012 г., 19:28
+1 Интересная обратная связь. Я должен проверить это.
Решение Вопроса

http://toroid.org/ams/git-website-howto

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

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

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

 Matt01 окт. 2010 г., 16:30
Спасибо, я все еще новичок в Git, и когда я начал работать с этим проектом, я не был уверен, почему должен быть пустой репозиторий, когда я мог бы перейти в корневой каталог документа и просто запустить git init. Я думаю, теперь понимаю, что это просто держит метаданные git от корня документа. Это верно?
 Ian Dunn15 авг. 2012 г., 01:49
Веб-ориентированный рабочий процесс Git это еще одна хорошая статья с немного другим подходом.
 Eddie B04 мая 2012 г., 22:02
+1 ... Это решение кажется наиболее разумным из всех, что я когда-либо видел ... Позволяет не только переносить изменения с помощью нескольких командных шагов ... но и поддерживать цепочку поставок, так сказать, когда работа выполняется непосредственно на сервере, требуя извлечения при внесении изменений удаленно ...
 Paul04 окт. 2010 г., 16:29
Мэтт, пустой репозиторий обычно используется на вашем центральном сервере. Если у вас есть только одна копия репозитория, и вы развертываете непосредственно из этого, вы быстро столкнетесь с проблемами. Создайте пустой репозиторий в другом каталоге сgit init --bare, Затем в вашем локальном клоне хранилища выполнитеgit origin add path_to_central_repo пометить новый центральный репо как оригинал. В заключение,git push origin master подтолкнет все, что вы сделали с мастером. Создайте отдельное рабочее дерево из центрального репо, и вы будете размещать свой сайт с каждымpush от вашего клона.
 Matt01 окт. 2010 г., 16:35
Кроме того, в примере, приведенном выше по ссылке, показано, как начать с нуля и отправить на сервер из локального репозитория. Каков наилучший способ получения чистого репозитория (вне корневого каталога веб-документа) из того, который в настоящее время находится там?

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

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

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

Phing (или муравей)Гудзон + Git плагин

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

Простой скрипт для настройки этого развертывания 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
 Honza21 сент. 2013 г., 17:31
Vi: Когда я пытаюсь сделать это без "git reset --hard", рабочее дерево sametime не изменилось, когда я запустил репозиторий, и git вел себя так, как будто я вручную изменил файлы в рабочем дереве сервера.
 Vi.21 сент. 2013 г., 03:23
Зачем тебеgit reset --hard BTW?
 Vi.21 сент. 2013 г., 03:23
Вы также можете добавитьgit diff -R --cached --name-status перед проверкой, чтобы получить хороший список того, какие файлы обновляются на стороне нажатия.
 Vi.21 сент. 2013 г., 03:22
Вы также можете использовать внешнее рабочее дерево:git config core.worktree /path/to/workdir, Для этого можно превратить голое хранилище в одно с рабочим деревом (git config core.bare false)

Как я уже упоминал вЧто это за предупреждение Git при отправке изменений в удаленный репозиторий?«Вы можете подтолкнутьнепосредственно на не-голое репо сейчас (Git 2.3.0+, февраль 2015) с:

git config receive.denyCurrentBranch updateInstead

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

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

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

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

#!/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 [email protected]{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 [email protected]{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
 Tronic27 июл. 2012 г., 18:52
Этот сценарий полностью fubar, и он ничего не делает. Мне удалось его починить (надеюсь, правильно), смотрите мой ответ ...
 Chris Johnsen01 окт. 2010 г., 15:39
+1: сценарий может показаться громоздким или многословным, но это так по веской причине; в отличие от тупых подходов использования равниныgit reset --hard или жеgit checkout -f, он сохранит любые незафиксированные изменения в тайнике.
 Aurelien15 мар. 2015 г., 21:37
С Git 2.3 вам больше не нужен этот хук, который вы можете сделатьgit config receive.denyCurrentBranch updateInstead, Увидетьgithub.com/blog/1957-git-2-3-has-been-released .
 VonC15 мар. 2015 г., 21:51
@ Aurelien Правда, хорошая мысль. Я отредактировал ответ, так как на самом деле этот вариант был рассмотрен вstackoverflow.com/a/28262104/6309 в феврале прошлого года

Ваш ответ на вопрос