Gitフックを使用して開発および展開タスクを自動化する方法

前書き

バージョン管理は、最新のソフトウェア開発の中心的な要件となっています。 これにより、プロジェクトは安全に変更を追跡し、復帰、整合性チェック、コラボレーションなどの利点を実現できます。 特に、 `+ git +`バージョン管理システムは、分散型アーキテクチャと、パーティ間で変更を行い、転送できる速度のために、近年広く採用されています。

ツールの `+ git +`スイートは多くの適切に実装された機能を提供しますが、最も有用な特徴の1つはその柔軟性です。 「フック」システムを使用することにより、gitは開発者と管理者がさまざまなイベントやアクションに基づいてgitが呼び出すスクリプトを指定することで機能を拡張できるようにします。

このガイドでは、gitフックの概念を探り、独自の環境でタスクを自動化するのに役立つコードを実装する方法を示します。 このガイドではUbuntu 14.04サーバーを使用しますが、gitを実行できるシステムであれば同様に機能するはずです。

前提条件

始める前に、サーバーに `+ git +`をインストールする必要があります。 Ubuntu 14.04をフォローしている場合は、https://www.digitalocean.com/community/tutorials/how-to-install-git-on-ubuntu-14-04 [gitのインストール方法]でガイドを確認できます。 Ubuntu 14.04で]こちら。

一般的な意味でのgitの使用方法に精通している必要があります。 導入が必要な場合は、https://www.digitalocean.com/community/tutorial_series/introduction-to-git-installation-usage-and-branchesと呼ばれる、インストールが含まれるシリーズ[Introduction to Git:Installation] 、使用法、およびブランチ]は、開始するのに適した場所です。

上記の要件を完了したら、続行します。

Gitフックの基本的な考え方

Gitフックは、ニーズに対応するために実装されたかなり単純な概念です。 共有プロジェクトでソフトウェアを開発するとき、スタイルガイドの標準を維持するとき、またはソフトウェアを展開するとき(すべてgitが関与することが多い状況です)、アクションが実行されるたびに実行する必要のある反復的なタスクがしばしばあります。

Gitフックはイベントベースです。 特定のgitコマンドを実行すると、ソフトウェアはgitリポジトリ内の `+ hooks +`ディレクトリをチェックして、実行する関連スクリプトがあるかどうかを確認します。

一部のスクリプトは、アクションが実行される前に実行されます。これは、標準へのコードのコンプライアンスを確保するため、健全性チェックのため、または環境のセットアップのために使用できます。 他のスクリプトはイベントの後に実行され、コードをデプロイしたり、正しいパーミッションを再確立したりします(gitがうまく追跡できないものなど)。

これらの機能を使用して、ポリシーを実施し、一貫性を確保し、環境を制御し、展開タスクを処理することもできます。

Scott Chaconによる本http://git-scm.com/book[Pro Git]は、異なるタイプのフックをカテゴリーに分割しようとしています。 彼はそれらを次のように分類します。

  • クライアント側のフック:コミッターのコンピューターで呼び出されて実行されるフック。 これらは順番にいくつかの個別のカテゴリに分けられます。

  • Committing-Workflowフック:コミットフックは、コミットが行われているときに実行する必要があるアクションを指示するために使用されます。 これらは、健全性チェックの実行、コミットメッセージの事前入力、およびメッセージの詳細の確認に使用されます。 これを使用して、コミット時に通知を提供することもできます。

  • 電子メールワークフローフック:このカテゴリのフックには、電子メールで送信されたパッチを操作するときに実行されるアクションが含まれます。 Linuxカーネルなどのプロジェクトは、電子メールを使用してパッチを提出およびレビューします。 これらはコミットフックと同様の流れですが、提出されたコードの適用を担当するメンテナーが使用できます。

  • その他:他のクライアント側フックには、リポジトリのマージ、チェックアウト、リベース、書き換え、およびクリーンアップ時に実行されるフックが含まれます。

  • サーバー側フック:これらのフックは、プッシュの受信に使用されるサーバーで実行されます。 一般的に、それはプロジェクトのメインgitリポジトリになります。 繰り返しますが、Chaconはこれらをカテゴリに分類しました。

  • 事前受信および事後受信:これらは、プッシュを受信するサーバー上で実行され、プロジェクトの適合性の確認やプッシュ後のデプロイなどを行います。

  • 更新:これは事前受信に似ていますが、ブランチごとに動作して、各ブランチが受け入れられる前にコードを実行します。

これらの分類は、オプションでフックを設定できるイベントの一般的なアイデアを得るのに役立ちます。 しかし、これらのアイテムがどのように機能するかを実際に理解するには、実験して、実装しようとしているソリューションを見つけることが最善です。

特定のフックもパラメーターを受け取ります。 これは、gitがフックのスクリプトを呼び出すときに、スクリプトがタスクを完了するために使用できる関連データを渡すことを意味します。 完全に、利用可能なフックは次のとおりです。

Hook Name Invoked By Description Parameters (Number and Description)

applypatch-msg

git am

Can edit the commit message file and is often used to verify or actively format a patch’s message to a project’s standards. A non-zero exit status aborts the commit.

(1) name of the file containing the proposed commit message

pre-applypatch

git am

This is actually called after the patch is applied, but before the changes are committed. Exiting with a non-zero status will leave the changes in an uncommitted state. Can be used to check the state of the tree before actually committing the changes.

(none)

post-applypatch

git am

This hook is run after the patch is applied and committed. Because of this, it cannot abort the process, and is mainly used for creating notifications.

(none)

pre-commit

git commit

This hook is called before obtaining the proposed commit message. Exiting with anything other than zero will abort the commit. It is used to check the commit itself (rather than the message).

(none)

prepare-commit-msg

git commit

Called after receiving the default commit message, just prior to firing up the commit message editor. A non-zero exit aborts the commit. This is used to edit the message in a way that cannot be suppressed.

(1 to 3) Name of the file with the commit message, the source of the commit message (message, template, merge, squash, or commit), and the commit SHA-1 (when operating on an existing commit).

commit-msg

git commit

Can be used to adjust the message after it has been edited in order to ensure conformity to a standard or to reject based on any criteria. It can abort the commit if it exits with a non-zero value.

(1) The file that holds the proposed message.

post-commit

git commit

Called after the actual commit is made. Because of this, it cannot disrupt the commit. It is mainly used to allow notifications.

(none)

pre-rebase

git rebase

Called when rebasing a branch. Mainly used to halt the rebase if it is not desirable.

(1 or 2) The upstream from where it was forked, the branch being rebased (not set when rebasing current)

post-checkout

git checkout and git clone

Run when a checkout is called after updating the worktree or after git clone. It is mainly used to verify conditions, display differences, and configure the environment if necessary.

(3) Ref of the previous HEAD, ref of the new HEAD, flag indicating whether it was a branch checkout (1) or a file checkout (0)

post-merge

git merge or git pull

Called after a merge. Because of this, it cannot abort a merge. Can be used to save or apply permissions or other kinds of data that git does not handle.

(1) Flag indicating whether the merge was a squash.

pre-push

git push

Called prior to a push to a remote. In addition to the parameters, additional information, separated by a space is passed in through stdin in the form of “<local ref> <local sha1> <remote ref> <remote sha1>”. Parsing the input can get you additional information that you can use to check. For instance, if the local sha1 is 40 zeros long, the push is a delete and if the remote sha1 is 40 zeros, it is a new branch. This can be used to do many comparisons of the pushed ref to what is currently there. A non-zero exit status aborts the push.

(2) Name of the destination remote, location of the destination remote

pre-receive

git-receive-pack on the remote repo

This is called on the remote repo just before updating the pushed refs. A non-zero status will abort the process. Although it receives no parameters, it is passed a string through stdin in the form of “<old-value> <new-value> <ref-name>” for each ref.

(none)

update

git-receive-pack on the remote repo

This is run on the remote repo once for each ref being pushed instead of once for each push. A non-zero status will abort the process. This can be used to make sure all commits are only fast-forward, for instance.

(3) The name of the ref being updated, the old object name, the new object name

post-receive

git-receive-pack on the remote repo

This is run on the remote when pushing after the all refs have been updated. It does not take parameters, but receives info through stdin in the form of “<old-value> <new-value> <ref-name>”. Because it is called after the updates, it cannot abort the process.

(none)

post-update

git-receive-pack on the remote repo

This is run only once after all of the refs have been pushed. It is similar to the post-receive hook in that regard, but does not receive the old or new values. It is used mostly to implement notifications for the pushed refs.

(?) A parameter for each of the pushed refs containing its name

pre-auto-gc

git gc --auto

Is used to do some checks before automatically cleaning repos.

(none)

post-rewrite

git commit --amend, git-rebase

This is called when git commands are rewriting already committed data. In addition to the parameters, it receives strings in stdin in the form of “<old-sha1> <new-sha1>”.

(1) Name of the command that invoked it (amend or rebase)

この一般的な情報はすべて揃ったので、いくつかのシナリオでこれらを実装する方法を示します。

リポジトリのセットアップ

まず、ホームディレクトリに新しい空のリポジトリを作成します。 これを「+ proj +」と呼びます。

mkdir ~/proj
cd ~/proj
git init
Initialized empty Git repository in /home/demo/proj/.git/

これで、gitで制御されるディレクトリの空の作業ディレクトリにいます。 他の作業を行う前に、このディレクトリ内の「+ .git +」という隠しファイルに保存されているリポジトリにジャンプしましょう。

cd .git
ls -F
branches/  config  description  HEAD  hooks/  info/  objects/  refs/

多数のファイルとディレクトリを確認できます。 私たちが興味を持っているのは `+ hooks +`ディレクトリです:

cd hooks
ls -l
total 40
-rwxrwxr-x 1 demo demo  452 Aug  8 16:50 applypatch-msg.sample
-rwxrwxr-x 1 demo demo  896 Aug  8 16:50 commit-msg.sample
-rwxrwxr-x 1 demo demo  189 Aug  8 16:50 post-update.sample
-rwxrwxr-x 1 demo demo  398 Aug  8 16:50 pre-applypatch.sample
-rwxrwxr-x 1 demo demo 1642 Aug  8 16:50 pre-commit.sample
-rwxrwxr-x 1 demo demo 1239 Aug  8 16:50 prepare-commit-msg.sample
-rwxrwxr-x 1 demo demo 1352 Aug  8 16:50 pre-push.sample
-rwxrwxr-x 1 demo demo 4898 Aug  8 16:50 pre-rebase.sample
-rwxrwxr-x 1 demo demo 3611 Aug  8 16:50 update.sample

ここでいくつかのことがわかります。 まず、これらのファイルのそれぞれが実行可能とマークされていることがわかります。 これらのスクリプトは名前で呼び出されるため、実行可能で、最初の行は正しいスクリプトインタープリターを呼び出すためのhttp://en.wikipedia.org/wiki/Shebang_(Unix)#Magic_number[shebang magic number]参照でなければなりません。 最も一般的には、これらはbash、perl、pythonなどのスクリプト言語です。

2つ目に気付くのは、すべてのファイルの末尾が `+ .sample a`であることです。 これは、実行するフックファイルを見つけようとするときにgitがファイル名を単純に調べるためです。 スクリプトの名前から逸脱すると、gitは基本的にスクリプトを無効にします。 このディレクトリ内のスクリプトを有効にするには、 `+ .sample +`サフィックスを削除する必要があります。

作業ディレクトリに戻りましょう。

cd ../..

最初の例:コミット後フックを使用してローカルWebサーバーにデプロイする

最初の例では、 `+ post-commit +`フックを使用して、コミットが行われるたびにローカルWebサーバーにデプロイする方法を示します。 これは、実稼働環境で使用するフックではありませんが、フックを使用する際に知っておく必要がある、ほとんど文書化されていない重要な項目をいくつか示します。

最初に、Apache Webサーバーをインストールしてデモを行います。

sudo apt-get update
sudo apt-get install apache2

スクリプトが `+ / var / www / html`のWebルートを変更するため(これはUbuntu 14.04のドキュメントルートです。 必要に応じて変更します)、書き込み権限が必要です。 このディレクトリの通常のユーザー所有権を与えましょう。 これを行うには、次のように入力します。

sudo chown -R `whoami`:`id -gn` /var/www/html

それでは、プロジェクトディレクトリで、 `+ index.html +`ファイルを作成しましょう。

cd ~/proj
nano index.html

内部には、アイデアを示すためだけにHTMLを少し追加できます。 複雑である必要はありません。

<h1>Here is a title!</h1>

<p>Please deploy me!</p>

新しいファイルを追加して、gitにファイルを追跡するよう指示します。

git add .

さて、コミットする前に、リポジトリの `+ post-commit `フックを設定します。 プロジェクトの ` .git / hooks +`ディレクトリ内にこのファイルを作成します。

vim .git/hooks/post-commit

このファイルに何を入れるかを検討する前に、フックを実行するときにgitが環境を設定する方法について少し学ぶ必要があります。

Gitフックを使用した環境変数について

スクリプトを開始する前に、フックを呼び出すときにgitが設定する環境変数について少し学ぶ必要があります。 スクリプトを機能させるには、最終的に、 `+ post-commit`フックを呼び出すときにgitが設定する環境変数を設定解除する必要があります。

これは、信頼できる方法で機能するgitフックを作成する場合に、内部化するための非常に重要なポイントです。 Gitは、呼び出されるフックに応じて異なる環境変数を設定します。 これは、gitが情報をプルする環境がフックによって異なることを意味します。

これに関する最初の問題は、どの変数が自動的に設定されているかを知らない場合、スクリプト環境を非常に予測不能にする可能性があることです。 2番目の問題は、設定されている変数がgitのドキュメントにほとんど完全に存在しないことです。

幸い、Mark Longairは、これらのフックを実行するときにhttp://longair.net/blog/2011/04/09/missing-git-hooks-documentation/[gitが設定する各変数をテストする方法]を開発しました。 次の内容をさまざまなgitフックスクリプトに配置する必要があります。

#!/bin/bash
echo Running $BASH_SOURCE
set | egrep GIT
echo PWD is $PWD

彼のサイトの情報は、2011年からgitバージョン1.7.1で動作しているため、いくつかの変更が加えられています。 2014年8月のこの記事の執筆時点で、Ubuntu 14.04のgitの現在のバージョンは1.9.1です。

このバージョンのgitでのテストの結果は以下のとおりです(各フックを実行するときにgitから見た作業ディレクトリを含む)。 テストのローカル作業ディレクトリは「+ / home / demo / test_hooks 」であり、裸のリモート(必要な場合)は「 / home / demo / origin / test_hooks.git +」です。

  • フック+ applypatch-msg ++ pre-applypatch ++ post-applypatch +

  • 環境変数

  • + GIT_AUTHOR_DATE = 'Mon、11 Aug 2014 11:25:16 -0400' +

  • + GIT_AUTHOR_EMAIL = demo @ example.com +

  • + GIT_AUTHOR_NAME = 'デモユーザー' +

  • + GIT_INTERNAL_GETTEXT_SH_SCHEME = gnu +

  • + GIT_REFLOG_ACTION = am +

  • 作業ディレクトリ+ / home / demo / test_hooks +

  • フック+ pre-commit、` + prepare-commit-msg`、 + commit-msg ++ post-commit

  • 環境変数

  • + GIT_AUTHOR_DATE = '@ 1407774159 -0400' +

  • + GIT_AUTHOR_EMAIL = demo @ example.com +

  • + GIT_AUTHOR_NAME = 'デモユーザー' +

  • + GIT_DIR = .git +

  • + GIT_EDITOR =:+

  • + GIT INDEX FILE = .git / index

  • + GIT_PREFIX = +

  • 作業ディレクトリ+ / home / demo / test_hooks +

  • フック+ pre-rebase +

  • 環境変数

  • + GIT_INTERNAL_GETTEXT_SH_SCHEME = gnu +

  • + GIT_REFLOG_ACTION = rebase +

  • 作業ディレクトリ+ / home / demo / test_hooks +

  • フック+ post-checkout +

  • 環境変数

  • + GIT_DIR = .git +

  • + GIT_PREFIX = +

  • 作業ディレクトリ+ / home / demo / test_hooks +

  • フック+ post-merge

  • 環境変数

  • + GITHEAD_4b407c …​ +

  • + GIT_DIR = .git +

  • + GIT_INTERNAL_GETTEXT_SH_SCHEME = gnu +

  • + GIT_PREFIX = +

  • + GIT_REFLOG_ACTION = '他のマスターをプルする' +

  • 作業ディレクトリ+ / home / demo / test_hooks +

  • フック+ pre-push +

  • 環境変数

  • + GIT_PREFIX = +

  • 作業ディレクトリ+ / home / demo / test_hooks +

  • フック+ pre-receive、` + update`、 + post-receive、` + post-update`

  • 環境変数

  • + GIT_DIR =。+

  • 作業ディレクトリ+ / home / demo / origin / test_hooks.git +

  • フック+ pre-auto-gc +

  • (これを確実にトリガーすることが難しいため不明)

  • フック+ post-rewrite +

  • 環境変数

  • + GIT_AUTHOR_DATE = '@ 1407773551 -0400' +

  • + GIT_AUTHOR_EMAIL = demo @ example.com +

  • + GIT_AUTHOR_NAME = 'デモユーザー' +

  • + GIT_DIR = .git +

  • + GIT_PREFIX = +

  • 作業ディレクトリ+ / home / demo / test_hooks +

これらの変数は、gitが環境をどのように見ているかに影響を与えます。 変数に関する上記の情報を使用して、スクリプトが環境を正しく考慮するようにします。

スクリプトに戻る

配置される環境のタイプについてのアイデアが得られたので( `+ post-commit +`フックに設定された変数を見てください)、スクリプトを開始できます。

gitフックは標準のスクリプトであるため、使用するインタープリターをgitに伝える必要があります。

#!/bin/bash

その後、git自体を使用して、コミット後にリポジトリの最新バージョンをWebディレクトリに展開します。 これを行うには、作業ディレクトリをApacheのドキュメントルートに設定する必要があります。 また、gitディレクトリをリポジトリに設定する必要があります。

現在作業ディレクトリにあるものとの間に競合がある場合でも、このトランザクションが毎回成功するように強制する必要があります。 これは次のようになります。

#!/bin/bash
git --work-tree=/var/www/html --git-dir=/home//proj/.git checkout -f

この時点で、ほぼ完了です。 ただし、 `+ post-commit `フックが呼び出されるたびに設定される環境変数をさらに詳しく調べる必要があります。 特に、「 GIT INDEX FILE」は「+ .git / index」に設定されます。

このパスは、作業ディレクトリ(この場合は + / var / www / html +)に関連しています。 gitインデックスはこの場所に存在しないため、そのままにしておくとスクリプトは失敗します。 この状況を回避するために、変数を手動で_unset_することができます。これにより、通常はgitがレポジトリーに関連して検索します。 これをチェックアウト行の上に追加する必要があります。

#!/bin/bash

git --work-tree=/var/www/html --git-dir=/home//proj/.git checkout -f

これらのタイプの競合が、gitフックの問題の診断が難しい場合がある理由です。 gitが動作している環境をどのように構築したかを知っておく必要があります。

これらの変更が完了したら、ファイルを保存して閉じます。

これは通常のスクリプトファイルであるため、実行可能にする必要があります。

chmod +x .git/hooks/post-commit

これで、ついにgitリポジトリで行った変更をコミットする準備が整いました。 正しいディレクトリに戻っていることを確認してから、変更をコミットします。

cd ~/proj
git commit -m "here we go..."

ブラウザでサーバーのドメイン名またはIPアドレスにアクセスすると、作成した `+ index.html +`ファイルが表示されるはずです。

http://

image:https://assets.digitalocean.com/articles/git_hooks/first_deploy.png [テストindex.html]

ご覧のとおり、最新の変更はコミット時にWebサーバーのドキュメントルートに自動的にプッシュされています。 各コミットで機能することを示すために、いくつかの追加変更を加えることができます。

echo "<p>Here is a change.</p>" >> index.html
git add .
git commit -m "First change"

ブラウザを更新すると、適用した新しい変更がすぐに表示されます。

image:https://assets.digitalocean.com/articles/git_hooks/deploy_changes.png [変更をデプロイ]

ご覧のように、このタイプのセットアップにより、ローカルで変更をテストするのが簡単になります。 ただし、実稼働環境ではコミット時に公開することはほとんどありません。 コードをテストして準備ができていることを確認してからプッシュする方がはるかに安全です。

Gitフックを使用して別の運用サーバーに展開する

この次の例では、実稼働サーバーを更新するより良い方法を示します。 これを行うには、プッシュデプロイモデルを使用して、ベアgitリポジトリにプッシュするたびにWebサーバーを更新します。

開発マシンとしてセットアップしたのと同じサーバーを使用できます。 ここで作業を行います。 コミットするたびに変更を確認できます。

本番マシンでは、別のWebサーバー、変更をプッシュするベアgitリポジトリ、プッシュを受信するたびに実行されるgitフックを設定します。 sudo特権を持つ通常のユーザーとして以下の手順を完了します。

実稼働サーバーの受信後フックのセットアップ

実動サーバーで、Webサーバーをインストールすることから始めます。

sudo apt-get update
sudo apt-get install apache2

繰り返しますが、ドキュメントルートの所有権は、次のように操作しているユーザーに与える必要があります。

sudo chown -R `whoami`:`id -gn` /var/www/html

このマシンにもgitをインストールすることを忘れないでください:

sudo apt-get install git

これで、リポジトリを保持するためにユーザーのホームディレクトリ内にディレクトリを作成できます。 その後、そのディレクトリに移動して、ベアリポジトリを初期化できます。 ベアリポジトリには作業ディレクトリがなく、あまり直接作業しないサーバーには適しています。

mkdir ~/proj
cd ~/proj
git init --bare

これはむき出しのリポジトリであるため、作業ディレクトリはなく、従来のセットアップで「+ .git +」にあるファイルはすべてメインディレクトリ自体にあります。

別のgitフックを作成する必要があります。 今回は、 `+ git push `を受信するサーバーで実行される ` post-receive +`フックに興味があります。 エディターでこのファイルを開きます。

nano hooks/post-receive

繰り返しますが、最初に作成するスクリプトの種類を識別する必要があります。 その後、 `+ post-commit +`ファイルで使用したものと同じチェックアウトコマンドを入力し、このマシン上のパスを使用するように変更します。

#!/bin/bash
git --work-tree=/var/www/html --git-dir=/home//proj checkout -f

これはむき出しのリポジトリであるため、 `+-git-dir +`はそのリポジトリの最上位ディレクトリを指す必要があります。 残りはかなり似ています。

ただし、このスクリプトにいくつかのロジックを追加する必要があります。 誤って `+ test-feature `ブランチをこのサーバーにプッシュした場合、それをデプロイしたくありません。 ` master +`ブランチのみをデプロイするようにします。

`+ post-receive +`フックについては、以前の表で、gitが古いリビジョンのコミットハッシュ、新しいリビジョンのコミットハッシュ、およびスクリプトへの標準入力としてプッシュされている参照を渡すことに気付いたかもしれません。 これを使用して、refがマスターブランチであるかどうかを確認できます。

まず、標準入力を読む必要があります。 プッシュされるrefごとに、3つの情報(古いrev、新しいrev、ref)が標準入力として空白で区切られてスクリプトに送られます。 + git`コマンドを囲む + while`ループでこれを読むことができます:

#!/bin/bash
while read oldrev newrev ref
do
   git --work-tree=/var/www/html --git-dir=/home//proj checkout -f
done

そのため、プッシュされる内容に基づいて3つの変数が設定されます。 マスターブランチプッシュの場合、 `+ ref `オブジェクトには ` refs / heads / master `のようなものが含まれます。 ` if +`構文を使用して、サーバーが受信しているrefがこの形式であるかどうかを確認できます。

#!/bin/bash
while read oldrev newrev ref
do
   if [[ $ref =~ .*/master$ ]];
   then
       git --work-tree=/var/www/html --git-dir=/home//proj checkout -f
   fi
done

サーバー側フックの場合、gitは実際にメッセージをクライアントに渡すことができます。 標準出力に送信されたものはすべてクライアントにリダイレクトされます。 これにより、どのような決定が行われたかをユーザーに明示的に通知する機会が与えられます。

検出された状況と実行されたアクションを説明するテキストを追加する必要があります。 アクションがデプロイをトリガーしない場合でも、マスター以外のブランチが正常に受信されたときにユーザーに通知するために、 `+ else +`ブロックを追加する必要があります。

#!/bin/bash
while read oldrev newrev ref
do
   if [[ $ref =~ .*/master$ ]];
   then
       echo "Master ref received.  Deploying master branch to production..."
       git --work-tree=/var/www/html --git-dir=/home//proj checkout -f
   else
       echo "Ref $ref successfully received.  Doing nothing: only the master branch may be deployed on this server."
   fi
done

終了したら、ファイルを保存して閉じます。

フックが機能するには、スクリプトを実行可能にする必要があります。

chmod +x hooks/post-receive

これで、クライアント上でこのリモートサーバーへのアクセスを設定できます。

クライアントマシンでリモートサーバーを構成する

クライアント(開発)マシンに戻り、プロジェクトの作業ディレクトリに戻ります。

cd ~/proj

内部で、リモートサーバーを「+ production」というリモートとして追加します。 運用サーバーで使用したユーザー名と、そのIPアドレスまたはドメイン名を知る必要があります。 また、ユーザーのホームディレクトリに関連して設定したベアリポジトリの場所を知る必要があります。

入力するコマンドは次のようになります。

git remote add production @:proj

現在のマスターブランチを運用サーバーにプッシュしましょう。

git push production master

SSHキーが構成されていない場合は、運用サーバーユーザーのパスワードを入力する必要があります。 次のようなものが表示されるはずです。

Counting objects: 8, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 473 bytes | 0 bytes/s, done.
Total 4 (delta 0), reused 0 (delta 0)

To [email protected]:proj
  009183f..f1b9027  master -> master

ご覧のとおり、 `+ post-receive`フックからのテキストはコマンドの出力にあります。 Webブラウザで本番サーバーのドメイン名またはIPアドレスにアクセスすると、プロジェクトの現在のバージョンが表示されます。

image:https://assets.digitalocean.com/articles/git_hooks/pushed_prod.png [プッシュ生産]

情報を受信すると、フックがコードを本番環境に正常にプッシュしたようです。

それでは、新しいコードをテストしてみましょう。 開発マシンに戻り、変更を保持するために新しいブランチを作成します。 これにより、実稼働環境にデプロイする前に、すべての準備が整ったことを確認できます。

「+ test_feature +」という新しいブランチを作成し、次のように入力して新しいブランチをチェックアウトします。

git checkout -b test_feature

現在、 `+ test_feature +`ブランチで作業しています。 変更を加えて、本稼働に移行する可能性があります。 このブランチにコミットします:

echo "<h2>New Feature Here</h2>" >> index.html
git add .
git commit -m "Trying out new feature"

この時点で、開発マシンのIPアドレスまたはドメイン名にアクセスすると、変更が表示されます:

image:https://assets.digitalocean.com/articles/git_hooks/devel_commit.png [変更をコミット]

これは、開発マシンがコミットごとにまだ再デプロイされているためです。 このワークフローは、本番環境に移行する前に変更をテストするのに最適です。

`+ test_feature +`ブランチをリモートの本番サーバーにプッシュできます:

git push production test_feature

出力に `+ post-receive +`フックからの他のメッセージが表示されるはずです。

Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 301 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)

To [email protected]:proj
  83e9dc4..5617b50  test_feature -> test_feature

ブラウザで本番サーバーを再度チェックアウトすると、何も変わっていないことがわかります。 プッシュした変更はmasterブランチにはなかったので、これは私たちが期待するものです。

開発マシンで変更をテストしたので、この機能をmasterブランチに組み込みたいと確信しています。 `+ master `ブランチをチェックアウトして、開発マシンの ` test_feature +`ブランチにマージできます。

git checkout master
git merge test_feature

これで、新しい機能がmasterブランチにマージされました。 実動サーバーにプッシュすると、変更がデプロイされます。

git push production master

実稼働サーバーのドメイン名またはIPアドレスをチェックアウトすると、変更が表示されます。

image:https://assets.digitalocean.com/articles/git_hooks/new_prod.png [本番環境にプッシュ]

このワークフローを使用すると、コミットされた変更をすぐに表示する開発マシンを使用できます。 本番マシンは、masterブランチをプッシュするたびに更新されます。

結論

ここまで進んでいると、gitフックがタスクの一部を自動化するのに役立つさまざまな方法を確認できるはずです。 それらは、コードの展開を支援したり、不適合な変更を拒否したりメッセージをコミットしたりすることで品質基準を維持するのに役立ちます。

gitフックの有用性を議論することは困難ですが、実際の実装は把握するのがかなり難しく、トラブルシューティングするのが面倒です。 さまざまな構成の実装の実践、引数と標準入力の解析の実験、およびgitがフックの環境を構築する方法の追跡は、効果的なフックの作成方法を教える上で大いに役立ちます。 長い目で見れば、プロジェクトの全期間にわたってあなたとあなたのチームの手作業を簡単に節約できるので、通常は時間投資は価値があります。