はじめに
Got というOpenBSDプロジェクト由来の Git の代替品について紹介します。
いわゆる git
コマンドの代替品なのですが、git
コマンドの使用および、そのライセンスについて疑問が無い人には全く不要なツールです。開発元が開発元なので、そのユースケースは独特なものとなります。
Gitのベアリポジトリ互換1を目指しているとのことです。ベアリポジトリに対する操作に関しては互換性はあります。その代わりいわゆるワークツリー(インデックスも)レベルでは互換性がありません。ワークフローとしてはコマンドの使い分けが必要です。
とまぁ一般論的な導入で書き始めたのでありますが、ぶっちゃけると最近のFreeBSDから portsnap
コマンドが無くなったので、Gitを使え2という案内を見て、portsnap
の代わりに git
の導入はちょっと勘弁…という向けの話となります。
GotはOpenBSD開発におけるワークフローの実現に絞って、実装することを目標としているため、そのコード量は極めて少なく、依存もほとんどありません。軽量コンパクトと、頭痛が痛いレベルで、謳ってしまって問題無いレベルのツールとなります。ただし動作が軽いか…という評価についてはノーコメントで。
また独特の使用感を要求されるため、ガチガチにGitしたいケースでは使わない方がいいと思います。
以後のユースケースは portsnap
の代わりを目標として記述します。
インストールしてみる
$ pkg install got
この辺りは git
も変わらないです。依存が無いので他にインストールされるパッケージはありません。
なお動作検証したGotのバージョンは 0.93
となります。バージョンアップによりここに書かれた内容が合わない可能性があります。
まずはクローンしてみる
got clone
と git clone
との差違は以下の通りとなります。
- ベアリポジトリのクローンのみ(
git clone --bare
相当) - オリジンの指定ができない(ベアリポジトリにオリジンの指定は無意味?)
- ブランチの指定ができて、デフォルトでシングルブランチっぽい
- ただシャロークローンはできないみたい
- ミラーモードがある(クローンしたリポジトリへのコミットができないモード)
- 対応しているスキーマが少ない ※後述
- とにかく遅い(マルチスレッドで Resolving deltas しない) 後述
クローン事例
$ git clone https://git.freebsd.org/ports.git /usr/ports
上記コマンド実行に相当する got
コマンドは下記の通りとなります。いったんベアリポジトリを展開する領域が必要です。
またこの処理が非常に重たい(後述)ため、余裕があるなら git
コマンドを使ってしまった方がいいかもしれません。
$ got clone -am ssh://anongit@git.freebsd.org/ports.git /home/ports.git
$ got checkout /home/ports.git /usr/ports
対応しているスキーマ
git://
-
git+ssh://
(またはssh://
)
対応してないスキーマ
-
git+http://
(またはhttp://
) ※エラー(ポリシー的に対応予定無し) -
https://
※未実装エラー(TODO) -
ftp://
※なにそれ?(存在を認識してるかどうか) -
ftps://
※なにそれ?(存在を認識してるかどうか)
クローンにかかる時間の計測
git clone
した場合のメッセージ
$ git clone --bare --single-branch ssh://anongit@git.freebsd.org/ports.git
Cloning into bare repository 'ports.git'...
remote: Enumerating objects: 5942473, done.
remote: Counting objects: 100% (171767/171767), done.
remote: Compressing objects: 100% (16358/16358), done.
remote: Total 5942473 (delta 167421), reused 155423 (delta 155409), pack-reused 5770706
Receiving objects: 100% (5942473/5942473), 1.12 GiB | 11.01 MiB/s, done.
Resolving deltas: 100% (3577978/3577978), done.
got clone
した場合のメッセージ
$ got clone ssh://anongit@git.freebsd.org/ports.git
Connecting to ssh://anongit@git.freebsd.org/ports.git
server: Enumerating objects: 5963414, done.
server: Counting objects: 100% (133228/133228), done.
server: Compressing objects: 100% (13237/13237), done.
server: Total 5963414 (delta 129757), reused 119991 (delta 119991), pack-reused 5830186
1157M fetched; indexing 100%; resolving deltas 100%
Fetched 0d39a9d41ecbf5cd111bcc9ae9f2cfcf7e30a616.pack
Created cloned repository 'ports.git'
git clone
と got clone
の実行時間
git clone --bare --single-branch ssh://anongit@git.freebsd.org/ports.git
511.72s user 40.21s system 163% cpu 5:36.76 total
got clone ssh://anongit@git.freebsd.org/ports.git
660.88s user 75.82s system 87% cpu 14:00.91 total
- 実行環境おおよそ5分37秒 v.s. 14分1秒の差違と2.5倍の差がある。
- またGitの方がCPU使用率が高く、処理効率がCPUバンドに偏っていることがわかる(マルチスレッド処理による効果)。
- 逆にGotはシステム使用率が高く、ボトルネックがI/Oバンドに偏りがちなのがわかる。
クローン時のオプション指定による容量差について
コマンド | シングルブランチ※ | マルチブランチ※ |
---|---|---|
got |
1,306,944KB | 1,326,872KB |
git |
1,322,480KB | 1,350,344KB |
※シングルブランチ: git clone --single-branch
または got clone
※マルチブランチ: git clone
または got clone -a
一応オプション指定による容量の変化を確認しています。また git
と got
間での違いも大きく、この差違が何故発生するかは不明です。
何かしらのオーバーヘッドと思われますが…。
ワークツリーの更新
$ cd /usr/ports && git pull
上記コマンド実行に相当する got
コマンドは下記の通りとなります。
$ cd /usr/ports && got fetch && got update
本ケースにおけるおおよその使い方はこんな所です。開発フローで必要になる使い方についてはコマンド対応表他、参考文献を参照ください。
オマケの tog
コマンド
ncursesベースのログビュワーです。1行ログを表示しつつ、そのログを選択(リターンキー)を押すと、詳細ログと修正内容が表示されるという便利なツールです。
Gitのサードパーティツールにある tig
コマンド相当とのことです。
インフォメーション
Gotではリポジトリとワークツリーとで使うべきコマンドが違います。具体的にはこれらは gotadmin
と got
となります。
とは言え安全に使えそうなサブコマンドは info
くらいでしょうか。リポジトリまたはワークツリーの状態に応じて表示内容が変わります。
$ gotadmin info -r /home/ports.git
repository: /home/ports.git
remote "origin": ssh://anongit@git.freebsd.org/ports.git
pack files: 4
packed objects: 5963321
packed total size: 1318M
loose objects: 0
git clone --bare
したディレクトリ内で gotadmin info
を実行して比較すると remote
行の表示が増えています。
リポジトリ配下のファイルを見ると、config
ファイルにある remote "origin"
ではなく、got.conf
中の remote "origin"
設定を参照しているようでした。実際 got.conf
ファイルを作成したら remote
行が表示されるようになりました。
またワークツリー上で gotadmin info
を実行した場合、リポジトリの状態が表示されます。
また got info
の実行結果はワークツリーに関しての情報になります。
$ cd /usr/ports
$ gotadmin info
repository: /home/ports.git
remote "origin": ssh://anongit@git.freebsd.org/ports.git
pack files: 4
packed objects: 5963321
packed total size: 1318M
loose objects: 0
$ got info
work tree: /usr/ports
work tree base commit: 388fa384c1dab4774d4db755ec1089b57e6f9a97
work tree path prefix: /
work tree branch reference: refs/heads/main
work tree UUID: 0c2bbcf5-8a1d-11ee-8d56-9ca3ba01eed8
repository: /home/ports.git
よくある質問とその答え
Q.https
スキーマ使えねぇのかよ。
A.curl
に依存してないからかも。普通にHTTP通信する実装だとパラレル処理できない問題あったりするので…と愚考。
ssh://
ならそこら中に ssh
コマンドインストールされてるし安心だね【何が?要出典】。
Q.got update
/got merge
/got rebase
/got integrate
の違いは?
A.未調査。たぶんGitと同じ事情と思われ。
Q.got clone ... /usr/ports/.git
すれば git clone
と全く同じ状況を作れるじゃないか!
A.検証しました。got clone
は成功しますが、got checkout
は失敗します。
$ got clone -m ssh://anongit@git.freebsd.org/ports.git /usr/ports/.git
Connecting to ssh://anongit@git.freebsd.org/ports.git
:
Created mirrored repository '/usr/ports/.git'
$ got checkout /usr/ports/.git /usr/ports/
got: work tree and repository paths may not overlap: /usr/ports/.git: bad path
Q.え? /usr/ports/.git
ってどういうこと?
A.つまりベアリポジトリのディレクトリだった! git clone
したあとに gotadmin info
したら驚きの結果に…。
Q.git status
したら驚きの結果に!
A..gitignore
ファイルの処理に バグがあります 仕様です。本来 .gitignore
ファイルで指定されたディレクトリやファイルなどは表示されません。
軽く調べたところ .gitignore
ファイルを処理してないわけでもありません。というわけで バグ 仕様です。
Q.エイリアス機能は?
A.無いです。欲しいですねぇ。誰か実装してください。
Q.これだけ動いてるならベースシステムに入っててもいいのでは?
A.ちゃんと使ってレポートしましょう。ベースシステムに入れても十分な品質かまでは現時点では言及できないはずです。
少なくとも自分が触った範疇ではまだその品質に達してないように見えます。
参考文献
- git
- got
- got、cvs、svn、git との比較
- よくある質問とその答え
- FOSDEM 2023 での発表資料
- EuroBSDcon 2019 での発表資料
- FreeBSDの入手方法(Gitの利用)