web-dev-qa-db-ja.com

Gitプッシュを使用してプロジェクトをデプロイする

git Pushを使用してWebサイトを展開できますか? git hooks を使用してサーバー側でgit reset --hardを実行することと関係があると思いますが、これをどのように達成するのでしょうか?

409
Kyle Cronin

このスクリプトこのサイト で見つけましたが、非常にうまく機能しているようです。

  1. .gitディレクトリをWebサーバーにコピーします
  2. ローカルコピーで、.git/configファイルを変更し、Webサーバーをリモートとして追加します。

    [remote "production"]
        url = username@webserver:/path/to/htdocs/.git
    
  3. サーバーで、.git/hooks/post-updateを this file に置き換えます(以下の回答)

  4. ファイルへの実行アクセス権を追加します(サーバー上でも):

    chmod +x .git/hooks/post-update
    
  5. ここで、ローカルにWebサーバーにプッシュするだけで、作業コピーが自動的に更新されます。

    git Push production
    
287
Kyle Cronin

以下のpost-updateファイルを使用:

  1. .gitディレクトリをWebサーバーにコピーします
  2. ローカルコピーで、.git/configファイルを変更し、Webサーバーをリモートとして追加します。

    [remote "production"]
        url = username@webserver:/path/to/htdocs/.git
    
  3. サーバーで、.git/hooks/post-updateを以下のファイルに置き換えます

  4. ファイルへの実行アクセス権を追加します(サーバー上でも):

    chmod +x .git/hooks/post-update
    
  5. ここで、ローカルにWebサーバーにプッシュするだけで、作業コピーが自動的に更新されます。

    git Push production
    
#!/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
77

多くの誤った開始と行き止まりの後、私はようやく「git Pushremote」でWebサイトのコードをデプロイできるようになりました この記事

著者の更新後スクリプトは1行だけであり、彼のソリューションでは、他の人が行うようにGitリポジトリを隠すために.htaccess構成を必要としません。

これをAmazon EC2インスタンスにデプロイする場合、いくつかの障害が生じます。

1)Sudoを使用してベア宛先リポジトリを作成する場合、リポジトリの所有者をec2-userに変更する必要があります。そうしないと、プッシュが失敗します。 (「chown ec2-user:ec2-userrepo」を試してください。))

2)/ etc/sshにあるAmazon-private-key。pemの場所を事前に設定していない場合、プッシュは失敗します/ ssh_configをIdentityFileパラメーターとして、または〜/ .ssh/configで「[Host]-HostName-IdentityFile-User」レイアウトを使用して説明します here ...

...ただし、ホストが〜/ .ssh/configで構成され、HostNameと異なる場合、Gitプッシュは失敗します。 (これはおそらくGitのバグです)

59
Earl Zedd

サーバーにgitをインストールしたり、そこに.gitフォルダーをコピーしたりしないでください。 git cloneからサーバーを更新するには、次のコマンドを使用できます。

git ls-files -z | rsync --files-from - --copy-links -av0 . [email protected]:/var/www/project

プロジェクトから削除されたファイルを削除する必要がある場合があります。

これにより、チェックインされたすべてのファイルがコピーされます。 rsyncは、とにかくサーバーにインストールされるsshを使用します。

サーバーにインストールするソフトウェアが少なければ少ないほどセキュリティが高くなり、構成の管理と文書化が容易になります。サーバーに完全なgitクローンを保持する必要もありません。すべてを適切に保護することがより複雑になるだけです。

21
Christian

基本的に、必要なことは次のとおりです。

server = $1
branch = $2
git Push $server $branch
ssh <username>@$server "cd /path/to/www; git pull"

deployと呼ばれる実行可能ファイルとしてアプリケーションにこれらの行があります。

そのため、デプロイを行いたいときは、./deploy myserver mybranchと入力します。

12
Lloyd Moore

私がやる方法は、変更をプッシュする展開サーバーに裸のGitリポジトリがあることです。次に、展開サーバーにログインし、実際のWebサーバーのdocsディレクトリに移動して、git pullを実行します。私はこれを自動的に行うためにフックを使用していません。それは価値があるよりも多くのトラブルのようです。

9
Greg Hewgill

receive.denyCurrentBranch updateInstead Git 2.3で追加される可能性があります。

サーバーリポジトリに設定し、作業ツリーがクリーンな場合は更新します。

2.4では、 Push-to-checkoutフックと未分岐ブランチの処理 でさらに改善されています。

サンプル使用法:

git init server
cd server
touch a
git add .
git commit -m 0
git config --local receive.denyCurrentBranch updateInstead

cd ..
git clone server local
cd local
touch b
git add .
git commit -m 1
git Push Origin master:master

cd ../server
ls

出力:

a
b

これには、次のような欠点があります GitHubの発表時

  • サーバーには、プロジェクトの全履歴を含む.gitディレクトリが含まれます。おそらく、ユーザーに提供できないことをさらに確認したいでしょう!
  • 展開中に、ユーザーは、古いバージョンのファイルと新しいバージョンのファイル、または半分書き込まれたファイルでさえ、一時的にサイトが一貫性のない状態になる可能性があります。これがプロジェクトの問題である場合、プッシュデプロイはおそらくあなたのためではありません。
  • プロジェクトに「ビルド」ステップが必要な場合は、おそらくgithooksを使用して、明示的にセットアップする必要があります。

ただし、これらの点はすべてGitの範囲外であり、外部コードで処理する必要があります。その意味で、これはGitフックと一緒に究極のソリューションです。

展開シナリオの場合

このシナリオでは、コードをgithub/bitbucketに保存しており、ライブサーバーにデプロイしたいと考えています。この場合、次の組み合わせが有効です(これはここで非常に支持された回答のリミックスです)

  1. .gitディレクトリをWebサーバーにコピーします
  2. ローカルコピーgit remote add live ssh://user@Host:port/folder
  3. リモートで:git config receive.denyCurrentBranch ignore
  4. リモートで:nano .git/hooks/post-receiveそしてこのコンテンツを追加します:

    #!/bin/sh GIT_WORK_TREE=/var/www/vhosts/example.org git checkout -f

  5. リモートで:chmod +x .git/hooks/post-receive

  6. これで、git Push liveでプッシュできます

ノート

  • このソリューションは、古いgitバージョン(1.7および1.9でテスト済み)で動作します
  • 最初にgithub/bitbucketにプッシュすることを確認する必要があります。そのため、ライブで一貫したレポを使用できます。
  • .gitフォルダーがドキュメントルート内にある場合は、.htaccessに追加して外部から非表示にしてください( source ):

    RedirectMatch 404 /\..*$

5
Attila Fulop

更新:現在、キーエージェントssh -A ...Lloyd Mooreソリューションを使用しています。メインリポジトリにプッシュしてから、すべてのマシンから並行してそこからプルすると、少し速くなり、それらのマシンでのセットアップが少なくて済みます。


ここではこの解決策が見当たりません。 gitがサーバーにインストールされている場合は、sshを介してプッシュします。

ローカルの.git/configに次のエントリが必要です。

[remote "Amazon"]
    url = Amazon:/path/to/project.git
    fetch = +refs/heads/*:refs/remotes/Amazon/*

しかし、ちょっと、Amazon:でそれはどうですか?ローカルの〜/ .ssh/configで、次のエントリを追加する必要があります。

Host Amazon
    Hostname <YOUR_IP>
    User <USER>
    IdentityFile ~/.ssh/Amazon-private-key

今、あなたは電話することができます

git Push Amazon master
ssh <USER>@<YOUR_IP> 'cd /path/to/project && git pull'

(ところで:/path/to/project.gitは実際の作業ディレクトリ/ path/to/projectとは異なります)

5
Karussell

capistrano を使用してデプロイを管理します。 capistranoをビルドしてステージングサーバーに展開し、すべてのサーバーでrsyncを実行します。

cap deploy
cap deploy:start_rsync (when the staging is ok)

Capistranoを使用すると、バグが発生した場合に簡単にロールバックできます

cap deploy:rollback
cap deploy:start_rsync
4
Supernini

Giddyup は言語に依存しないjust-add-watergit Pushを介した展開を自動化するgitフックです。また、Webサーバーの再起動、キャッシュのウォームアップなどのためにカスタムの開始/停止フックを使用できます。

https://github.com/mpalmer/giddyup

examples を確認してください。

2
Artur Bodera

サーバー上に2つのコピーがあるはずです。裸のコピー。プッシュ/プルができ、完了したら変更をプッシュします。その後、これをWebディレクトリにクローンし、cronジョブを設定して、Webディレクトリからgit pullを毎日更新します。そう。

1
Flame

toroid.org による次のソリューションを使用しています。これは、より単純なフックスクリプトです。

サーバー上:

$ mkdir website.git && cd website.git
$ git init --bare
Initialized empty Git repository in /home/ams/website.git/

サーバーにフックをインストールします。

$ mkdir /var/www/www.example.org
$ cat > hooks/post-receive
#!/bin/sh
GIT_WORK_TREE=/var/www/www.example.org git checkout -f
GIT_WORK_TREE=/var/www/www git clean -f -d # clean directory from removed files

$ chmod +x hooks/post-receive

クライアントで:

$ mkdir website && cd website
$ git init
Initialized empty Git repository in /home/ams/website/.git/
$ echo 'Hello, world!' > index.html
$ git add index.html
$ git commit -q -m "The humble beginnings of my web site."

$ git remote add web ssh://server.example.org/home/ams/website.git
$ git Push web +master:refs/heads/master

その後、公開するには、単に入力します

$ git Push web

ウェブサイトに完全な説明があります: http://toroid.org/ams/git-website-howto

1
Synox

補足的な回答として、代替案を提供したいと思います。私はgit-ftpを使用していますが、正常に動作します。

https://github.com/git-ftp/git-ftp

使いやすい、入力のみ:

git ftp Push

gitはプロジェクトファイルを自動的にアップロードします。

よろしく

1
manuelbcd

クリスチャン 解決策に関する私の見解。

git archive --prefix=deploy/  master | tar -x -C $TMPDIR | rsync $TMPDIR/deploy/ --copy-links -av [email protected]:/home/user/my_app && rm -rf $TMPDIR/deploy
  • Masterブランチをtarにアーカイブします
  • Tarアーカイブをシステムのtempフォルダーのdeployディレクトリに抽出します。
  • サーバーへのrsyncの変更
  • 一時フォルダーからdeploy dirを削除します。
1
Priit

「安定した」ブランチを言うためにコミットが行われたときに変更をプルし、PHPサイトに適用するgitフックを設定できます。大きな欠点は、何か問題が発生した場合にあまり制御できず、テストに時間がかかることです。競合の数mayに遭遇します。 1つのサイトのみを実行する場合を除き、サイト固有のファイル(構成ファイルなど)に注意することが重要です。

または、代わりに変更をサイトにプッシュすることを検討しましたか?

Gitフックの詳細については、 githooks のドキュメントを参照してください。

1
Chealion

複数の開発者が同じリポジトリにアクセスしている環境では、次のガイドラインが役立ちます。

すべての開発者が所属するUNIXグループがあることを確認し、そのグループに.gitリポジトリの所有権を付与します。

  1. サーバーリポジトリの.git/configでsharedrepository = trueを設定します。 (これにより、コミットとデプロイメントに必要な複数のユーザーを許可するようにgitに指示します。

  2. bashrcファイルの各ユーザーのumaskを同じに設定します-002が良いスタートです

0
Lloyd Moore

リポジトリから新しい更新を自動的にプルダウンする独自の基本的な展開ツールを作成しました- https://github.com/jesalg/SlimJim -基本的に、github post-receive-hookをリッスンしますプロキシを使用して更新スクリプトをトリガーします。

0
jesal

受信後フックに2つのソリューションを使用します。

展開ソリューション1

#!/bin/bash 
#  /git-repo/hooks/post-receive - file content on server (chmod as 755 to be executed)
# DEPLOY SOLUTION 1 

    export GIT_DIR=/git/repo-bare.git
    export GIT_BRANCH1=master
    export GIT_TARGET1=/var/www/html
    export GIT_BRANCH2=dev
    export GIT_TARGET2=/var/www/dev
    echo "GIT DIR:  $GIT_DIR/"
    echo "GIT TARGET1:  $GIT_TARGET1/"
    echo "GIT BRANCH1:  $GIT_BRANCH1/"
    echo "GIT TARGET2:  $GIT_TARGET2/"
    echo "GIT BRANCH2:  $GIT_BRANCH2/"
    echo ""

    cd $GIT_DIR/

while read oldrev newrev refname
do
    branch=$(git rev-parse --abbrev-ref $refname)
    BRANCH_REGEX='^${GIT_BRANCH1}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET1/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        git checkout -f $branch
    fi

    BRANCH_REGEX='^${GIT_BRANCH2}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET2/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        git checkout -f $branch
    fi
done

展開ソリューション2

#!/bin/bash 
#  /git-repo/hooks/post-receive - file content on server (chmod as 755 to be executed)
# DEPLOY SOLUTION 2

    export GIT_DIR=/git/repo-bare.git
    export GIT_BRANCH1=master
    export GIT_TARGET1=/var/www/html
    export GIT_BRANCH2=dev
    export GIT_TARGET2=/var/www/dev
    export GIT_TEMP_DIR1=/tmp/deploy1
    export GIT_TEMP_DIR2=/tmp/deploy2
    echo "GIT DIR:  $GIT_DIR/"
    echo "GIT TARGET1:  $GIT_TARGET1/"
    echo "GIT BRANCH1:  $GIT_BRANCH1/"
    echo "GIT TARGET2:  $GIT_TARGET2/"
    echo "GIT BRANCH2:  $GIT_BRANCH2/"
    echo "GIT TEMP DIR1:  $GIT_TEMP_DIR1/"
    echo "GIT TEMP DIR2:  $GIT_TEMP_DIR2/"
    echo ""

    cd $GIT_DIR/

while read oldrev newrev refname
do
    branch=$(git rev-parse --abbrev-ref $refname)
    BRANCH_REGEX='^${GIT_BRANCH1}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET1/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        # DEPLOY SOLUTION 2: 
        cd $GIT_DIR/; mkdir -p $GIT_TEMP_DIR1; 
        export GIT_WORK_TREE=$GIT_TEMP_DIR1/.
        git checkout -f $branch
        export GIT_WORK_TREE=$GIT_TARGET1/.
        rsync $GIT_TEMP_DIR1/. -v -q --delete --delete-after -av $GIT_TARGET1/.
        rm -rf $GIT_TEMP_DIR1
    fi

    BRANCH_REGEX='^${GIT_BRANCH2}.*$'
    if [[ $branch =~ $BRANCH_REGEX ]] ; then
        export GIT_WORK_TREE=$GIT_TARGET2/.
        echo "Checking out branch: $branch";
        echo "Checking out to workdir: $GIT_WORK_TREE"; 

        # DEPLOY SOLUTION 2: 
        cd $GIT_DIR/; mkdir -p $GIT_TEMP_DIR2; 
        export GIT_WORK_TREE=$GIT_TEMP_DIR2/.
        git checkout -f $branch
        export GIT_WORK_TREE=$GIT_TARGET2/.
        rsync $GIT_TEMP_DIR2/. -v -q --delete --delete-after -av $GIT_TARGET2/.
        rm -rf $GIT_TEMP_DIR2
    fi
done

両方のソリューションは、このスレッドで利用可能な以前のソリューションに基づいています。

BRANCH_REGEX = '^ $ {GIT_BRANCH1}。$'は、「master」または「dev *」文字列に一致するブランチ名をフィルターし、展開します。プッシュされたブランチが一致する場合、作業ツリー。これにより、開発バージョンとマスターバージョンを異なる場所に展開できます。

DEPLOY SOLUTION 1は、レポジトリの一部であり、コミットによって削除されたファイルのみを削除します。 Deployment Solution 2よりも高速です。

DEPLOY SOLUTION 2には、リポジトリに追加されたかどうかに関係なく、サーバー側で追加された本番ディレクトリから新しいファイルを削除するという利点があります。それは常にレポのきれいなduになります。 Deployment Solution 1よりも低速です。

0
klor