質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
Git

Gitはオープンソースの分散バージョン管理システム(DVCS)です。

Q&A

解決済

hooksのpost-receiveについて、特定のブランチに対してプッシュが行われたときにそれと同じブランチをプルするように設定することは可能か。

ryu_wtd.
ryu_wtd.

総合スコア29

Git

Gitはオープンソースの分散バージョン管理システム(DVCS)です。

1回答

0グッド

1クリップ

447閲覧

投稿2022/11/16 01:32

編集2022/11/16 01:34

前提

現在Gitの環境を構築中で、
ローカルリポジトリからサーバー上のリモートリポジトリへプッシュが行われると、同じサーバー上に置かれたノンベアリポジトリが自動でプルを行うように設定しています。

目的はcronなど実際のサーバー上での動作確認が必要なもののテスト環境をサーバーに作成することで、
本番環境についてはさらに別で取引先のサーバー上に作ることを想定しています。

現状は特定のブランチをpost-receive内で指定してそのブランチについてプルを行うやり方しかわかりません。

GitHubなどのホスティングサービスは利用しておらず、自社で借りているレンタルサーバーにGitの環境を構築しています。

実現したいこと

  • Git-Flowを参考にしたブランチ運用を想定しているため、developにプッシュされたときはdevelopを、masterにプッシュされたときはmasterをプルするように設定したいがこれは実現可能か。その場合どのようにして実現するか。

該当のソースコード

git

1#現在のリモートリポジトリ内のpost-receive内の記述 2#!/bin/sh 3 4cd ~/test/project/ 5git --git-dir=.git pull origin master 6

試したこと

hooks内でのif文の記述方法について調べてみましたが、自分が実現したい状況をどのように記述したらいいかを理解するまでには至らず、そもそも実現可能なことなのか疑問に思ったため質問させていただきました。

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

3

ベストアンサー

このノンベアリポジトリが同じGitマシン内に存在するのであれば、
post-receiveファイル内でブランチ名を特定した上で、ノンベアリポジトリのディレクトリへ移動して新たなgitコマンドを発行するだけで終わりです。
参考記事: Gitのpost-receive Hookでブランチ名などを受け取ったりする

もし別マシンだった場合が厄介です。
post-receiveという実行ファイル1個で別マシンに遠隔操作でGit操作を行わせる事になり、相当困難な作業となります。

この場合はWebhookの仕組みを活用したり、メッセージングサーバを立ち上げる事で解決します。
こういう仕組みを作るのが上手な人なら1,2週間程度でさくっと作ってくれるかもしれませんが、
エラーのハンドリング等も考えると大変かもしれないですね。

この流れを説明していきます。


今回の登場人物は3人です

  • A: 質問者さんのパソコン
  • B: Gitのサーバ
  • C: 追従したい別マシン

A -> Bに向けて更新したmasterブランチをpushしました。
この時、通信はAB間で完結してしまっているので、Cはそれを知る術がありません。

B内で実行されるpost-receiveファイルを使って、
Cにmasterブランチの更新を知らせてCにpullをさせる必要があります。


post-receiveに関して

postreceiveは実行ファイルである必要があります。
実行ファイルということでコンパイルしたC言語やRustの実行ファイルを
post-receiveという名前にして配置するのが基本ですかね。

しかし質問文にあった「該当のソースコード」の中身はテキストファイルです。
実行ファイルじゃないのに実行出来るわけないじゃん。

Linux等でテキストファイルに実行権限を付与して実行した場合、
ファイルの1行目に書かれている#!/bin/sh、これをシバンと呼び、
書かれている実行ファイルを探して、そいつに読み込ませて実行するという挙動をしてくれます。

#!/bin/shはシェルスクリプトですね。
一般的によく使われるbashあたりなんじゃね?とは思いますが、
一概にshと書かれている場合はashbashを始めとして多くの候補が存在するので、100%bashのコードが動作するとは限りません。

シェルスクリプトで他のマシンへの通知や実行を全て任せるのはちと荷が重いので、
RubyやPython、Node.js等の汎用スクリプト言語の力を借りるのが楽だと思います。
#!/usr/bin/env rubyという感じのシバンを書けばシェルスクリプト以外も動作させる事が可能です。


どうやって実行ファイル1個で
追従したい別マシンにmasterブランチの更新を知らせてpullをさせるか?
これが今回の障壁となる部分です。

「Gitのサーバ」で実行ファイルを動作させても、
影響を及ぼせるのは「Gitのサーバ」内だけです。
その垣根を勝手に超えて「別マシン」を操作しようなんて、遠隔操作・セキュリティホールに他なりません。

ここは「別マシンでgit pull origin masterを実行するだけ」の仕組みを作って
その用途だけに使うのが良いでしょう。
こうしておけば仮に悪意の第三者に知られても「別マシンでgit pull origin masterを実行するだけ」という機能を何度も実行されるだけの被害で済みます。

  • 別マシンでWebサーバを稼働して、特定のURLにアクセスすると「Gitサーバのブランチが更新した」と見なしてpullを試みる
  • PubSub方式のメッセージングサーバを稼働させ、別マシンはメッセージングサーバにSubscribe側として接続しっぱなしにする。GitサーバからPublishして「Gitサーバのブランチが更新」された事を検知させてpullを試みる
  • Node.jsでWebSocketサーバを開設して、Gitサーバと別マシンを接続しっぱなしにする

1番目の方法はGitHubでもWebhookという仕組みで提供されています。
ブランチが更新された等の契機で、機械的にHTTPアクセスを飛ばして通知します。
受け手となる別マシンにそのHTTPアクセスを受け取れるWebサーバを構築しておけば良いですね。

実現だけなら最も楽だと思います。
デメリットはGitサーバのpost-receive内に受け手となる別マシンへHTTPリクエストを飛ばすという情報を覚えさせる必要がある点ですね。
エンジニアの感覚として、なんで俺がそれを覚える必要があるの?になります。

他の方法は別ルートで通知する経路を確保しておいて、
post-receiveファイルはその経路を利用してメッセージを伝えるというアプローチです。
Yahoo!ではPlusarというメッセージングの仕組みを開発・運用してその筋では有名になりました。
大規模なマシン達を管理するとなると、こういうアプローチは欠かせないというわけですね。

投稿2022/11/16 04:50

編集2022/11/16 07:36
miyabi-sun

総合スコア21052

uky, ryu_wtd.👍を押しています
ukyを押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

ryu_wtd.

2022/11/16 06:09

大変詳しいご回答ありがとうございました。 webhookについては詳しく調べてみようと思います。 頂いた回答について2点質問があります。 1. 回答内でご提示いただいたノンベアリポジトリマシンという言葉について、 今回の質問におけるローカルリポジトリのある場所ともGitサーバーとも異なるハードウェアを指しているということで間違いないでしょうか。 2. 例えばgitのサーバー内にリモートリポジトリとそれをプルするだけのノンベアリポジトリがあったとしても、post-receiveを駆使するだけではローカルからどのブランチへのプッシュがあったかを伝える手段はないという認識で間違いないでしょうか。 初学者のため、頂いた回答の意図を汲みきれていない可能性があるため質問させていただきました。
miyabi-sun

2022/11/16 07:38

問題はそれが「同じマシン」か「別のマシン」かです。 この回答は「同じマシン」である事を想定していなかったので回答文を加筆・修正しました。 かなりの遠回りになりましたが、 同じマシンだったのであればかなり簡単な問題となります。
ryu_wtd.

2022/11/16 08:07

ご丁寧にありがとうございます。 私の説明不足でお手を煩わせてしまい、申し訳ありません。 同じマシンだった場合はgit rev-parse --abbrev-ref HEADなどで取得して、それと同じものをプルするように記述すればいいということですね。 両方のパターンにおいて大変参考になりました。 ありがとうございました。

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Git

Gitはオープンソースの分散バージョン管理システム(DVCS)です。