59

git pull現在のバージョンをローカルで動作さgit pushせ、変更をリモートサーバーにプッシュできるように、Web サイトをステージングするために Git をセットアップしようとしています。希望どおりに動作するようにセットアップしましたが、プッシュした後、手動で実行するgit checkout -fgit reset --hard HEAD、リモートサーバーで実行する必要があります。

これらをサーバーの受信後フックとしてシェルスクリプトに入れてみましたが、効果がないようです。プッシュ後に「変更がサーバーにプッシュされました」と表示されるため、スクリプトが実行されていることがわかります。受信後フックは次のとおりです。

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

6 に答える 6

73

あなたの質問への答えはここにあります: http://toroid.org/ams/git-website-howto

要するに、やりたいことは「切り離された作業ツリー」を裸のリポジトリに追加することです。通常、作業ツリーは.gitディレクトリを含むものと考えます。ベア リポジトリには定義上ワーク ツリーはありませんが、ベア リポジトリとは別のディレクトリにある限り作成できます。

git checkout -fpost-receive フックは、リポジトリHEADを作業ディレクトリに複製する単純なものです。Apache はそれをドキュメント ルートとして使用するので、準備は完了です。ベア リポジトリにプッシュすると、Apache はすぐにサービスを開始します。

私は通常、これを使用してステージング サーバーに自動的にプッシュし、「実際の」環境が私の​​変更を吐き出すかどうかを確認します。ライブ サーバーへのデプロイは、まったく別の話です。:-)

于 2010-10-01T11:40:57.403 に答える
15

2015 年 3 月の更新

変更をリモート リポジトリにプッシュするときに、この Git 警告メッセージとは何ですか? 」で述べたように、実際には、現在 (Git 2.3.0+、2015 年 2 月) を使用して、非ベア リポジトリに直接プッシュできます。

git config receive.denyCurrentBranch updateInstead

それに応じて作業ツリーを更新しますが、コミットされていない変更がある場合は更新を拒否します。

これにより、受信後のフックを回避できます。


(元の回答: 2010 年 10 月)

GitFAQは、このポスト更新フックを非裸レポに推奨しています:
(フックの実行で実際に何が起こっているかについて、より多くの手がかりが得られるかもしれません。これは、post-receive ではなく、post-update フックであることに注意してください)

#!/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
于 2010-10-01T11:39:38.733 に答える
11

まったく同じ問題がありました。このリンクへの返信: http://toroid.org/ams/git-website-howto - 次のコマンドで実行できます:

sudo chmod +x hooks/post-receive

最初に設定したsudo権限がありませんでした。

于 2012-01-04T00:55:44.413 に答える
6

この 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
于 2013-07-10T18:35:27.057 に答える
6

VonCのスクリプトの修正版は、私にとってはうまくいきます(絶対に保証はありません)。

#!/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 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
    # 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
于 2012-07-27T17:00:53.063 に答える
1

推測ですが、これはパーミッションの問題かもしれません (フルパスが必要ですかcd??)。ログ ファイルで実際に何が起こっているかを確認します。

ただし、git を介してファイルを公開することは、常に公開プロセスの 1 つのタスクにすぎません。通常、いくつかのファイルのコピー、他のファイルの削除、セットアップ、アクセス許可の更新、ドキュメントの生成などを行う必要があります。

複雑なソリューションの場合、ビルド スクリプトはどの git フックよりも優れている場合があります。これらのタスクをうまく処理できるツール:

(これはあなたが期待している答えではないことは承知していますが、コメントとして投稿するには長すぎます)

于 2010-10-01T13:05:20.183 に答える