本当は怖い軽量チェックアウトの話

前回は、作業ツリー上でコミットすると、別の場所にあるブランチに新しいリビジョンが追加されるチェックアウトについて説明しました。
今回はチェックアウトの別の仕組みである軽量チェックアウト (lightweight checkout) について説明します。

軽量チェックアウトの使い方

軽量チェックアウトを使う方法は、通常のチェックアウトをするときに --lightweight というオプションを付けるだけです。

$ # /path/to/branch にあるブランチの軽量チェックアウトを workingtree に作成する
$ bzr checkout --lightweight /path/to/branch workingtree

軽量チェックアウトを使うときは、チェックアウト元のブランチは同じマシン上のものにしてください。
その理由と、軽量チェックアウトのメリットをこれから説明していきます。

軽量チェックアウトを理解するために、まずは、通常のチェックアウトの仕組みから理解していきましょう。

チェックアウトの仕組み

(軽量でない)チェックアウトの実体は、通常の(作業ツリー付きの)ブランチです。ただし、このブランチは、チェックアウト元のブランチに bind されています。 (bound branch)

bind されたブランチにコミットなどの操作を行うときは、先に bind 先のブランチにその操作を行い、それに成功したらローカルのブランチを bind 先のブランチに同期します。

このように自動的に同期が保たれるので、まるでSubversionのような、チェックアウト元のブランチから直接チェックアウトしているように見える挙動をするのです。

また、ローカルにブランチがあるので、最新版のコピーしか持たないSubversionのチェックアウトと異なり、オフラインでも log や annotate などの履歴閲覧操作ができます。

bind, unbind コマンドを使って、ブランチを他のブランチに bind したりそれを解除することができます。つまり、チェックアウトは unbind すると通常のブランチになり、通常のブランチを bind するとチェックアウトになるのです。

軽量チェックアウトの仕組み

軽量チェックアウトは、通常のチェックアウトと違いローカルのブランチを持ちません。チェックアウト元のブランチから直接のチェックアウトになっています。

   チェックアウト: 作業ツリー <-- ローカルブランチ --(bind)--> チェックアウト元ブランチ
   軽量チェックアウト: 作業ツリー <-- チェックアウト元ブランチ

作業ツリー上で作業するために絶対に必要な最新リビジョンの情報はブランチにあります。なので、過去の履歴の確認どころか、ファイルが変更されているかどうかの確認のためにもチェックアウト元ブランチを参照しなければなりません。

軽量チェックアウトにはブランチが無いので、 bind, unbind は利用できません。ただし、 switch コマンドでブランチ元を切り替えることは可能です。

軽量チェックアウトのメリット

軽量チェックアウトのメリットは、その名の通り、ブランチを持たない分容量が軽いことです。

ただし、 Bazaar で重いのはブランチではなくてリポジトリです。実際のリビジョンはリポジトリに圧縮されて格納されていて、ブランチはリポジトリの場所と最新リビジョンのIDを記録しているだけだからです。

なので、軽量チェックアウトは、ブランチそれぞれがリポジトリを持つ(standalone branch)の場合は通常のチェックアウトより軽量ですが、チェックアウト元ブランチとチェックアウトのブランチが同じ共有リポジトリを利用している場合はメリットがありません。

軽量チェックアウトが役に立つユースケースとして、ある1つのサーバーがbzrのブランチ管理とCIサーバーやデプロイ用サーバーになっている場面を考えてみましょう。

ビルドしてテストを実行するために、管理しているブランチの作業ツリーが必要です。テスト後のクリーンアップで間違ってbzrブランチを削除したりしないように、CIサーバーが動くユーザーとbzr用のユーザーは分けましょう。ディレクトリ構成は次のようになるでしょう。

  /home
  /home/proj_bzr            - bzr 用ユーザーのホーム
  /home/proj_bzr/repo         - 共有リポジトリ
  /home/proj_bzr/repo/main      - main ブランチ(作業ツリーなし)
  /home/proj_bzr/repo/1.0       - メンテナンスブランチ(作業ツリー無し)
  /home/proj_ci             - CI サーバーユーザーのホーム
  /home/proj_ci/work          - 軽量チェックアウト

ユーザーをまたいで共有リポジトリを使うのは難しいですが、軽量チェックアウトを使うことでリポジトリ内のデータをコピーすること無く作業ツリーを構築することが可能です。

軽量チェックアウトが便利な他のユースケースとして、 colo-checkout があります。通常は bzr-colo を使っていて1つの作業ツリーで作業していたのに、一時的に別の作業を始めたい場合に colo-checkout を使って別の作業ツリーを作ることができるのですが、これが軽量チェックアウトになっているので、最低限の容量だけで作業ツリーを作ることができます。

軽量チェックアウトの問題点

最初に、「軽量チェックアウトを使うときは、チェックアウト元のブランチは同じマシン上のものにしてください。」と言った理由を説明します。

http や bzr+ssh などで接続するリモートのブランチから軽量チェックアウトをした場合、 bzr info や bzr status なども含めてほぼすべての操作がリモートブランチを参照するために、 http サーバーや ssh サーバーに接続するので、サーバーに大きな負荷をかけてしまいます。

実際に私の会社であった例として、TortoiseBZR をインストールしたPCでbzr+sshからの軽量チェックアウトを作成してしまい、TortoiseBZR が頻繁に ssh 接続しにいくという事がありました。接続に成功する場合は単に重くなるだけで済むのですが、 pageant を常駐して鍵を登録していないために ssh 認証が失敗する状況で認証エラーが頻発したためにsshサーバーが新規接続を一時的に受け付けなくなり、多くの人の作業に支障が出てしまいました。

Bazaar Explorer が提供しているチェックアウトダイアログ(qbzr とは別のもの) がオプションも表示も無しに軽量チェックアウトを作ってしまうため、通常のチェックアウトを作るつもりで軽量チェックアウトを作ってしまう場合があります。GUIで軽量ではないチェックアウトを作成するときは、チェックアウトのダイアログではなくブランチのダイアログを利用し、 bind オプションを有効にしたほうが安全です。

このブログに乗せているコードは引用を除き CC0 1.0 で提供します。