gitでbareリポジトリを同期する方法

  • 投稿日:
  • by

以前調べたネタですが、ここにメモしておきます。 (最近ブログの更新が滞っていたため)

gitには普通のリポジトリとbareリポジトリがあります。普通のリポジトリは、チェックアウトされたファイルを含むリポジトリで、bareリポジトリは.gitディレクトリの中身のみを含むリポジトリです。

bareリポジトリは、

% git init --bare hoge

のように作ります。サーバにbareリポジトリを作って、そこにみんなでpushするような使い方は一般的でしょう。ちなみに、push先がbareリポジトリではなかったりすると、ワーニングがでたりします。

さて、例えば2つのチームがそれぞれ別々のリモートサーバを使って別のbareリポジトリにpushしていたとします。その2つのbareリポジトリを同期したいとします。bareリポジトリにはチェックアウトという概念がないので、git mergeは使えません。

マニュアルには直接的な説明は見つからなかったのですが、結局次のようにすればできることが分かりました。

% git fetch origin 'refs/heads/*:refs/heads/*'

これを一方のbareリポジトリで実行すると、originで指定された他方のリポジトリの差分を取り込むことになります。上記例では全てのブランチを取得していますが、例えばmasterのみを同期するには、

% git fetch origin 'refs/heads/master:refs/heads/master'

とします。同期と書きましたが、双方向に同期する場合はpushする必要があります。

もう一つの注意点は、マージをするわけではないので、fast-forwardが基本です。fast-forwardできない場合は失敗するでしょう。マニュアルによると'+'を先頭につけておくとマージしてくれるようですが、コンフリクトした場合にどうなるかはよく分かりません。

ご参考まで


追記。

双方がpushし合う場合は、この方法は必要ではありません。この方法が必要になるのは、一方のbareリポジトリがファイアウォールの内側にあるなど、双方にpushできない場合です。