LoginSignup
1

追放された portsnap、変わりに git が入ってくはずだったのに、気がつけば got がいる

Last updated at Posted at 2023-12-01

はじめに

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 clonegit 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 clonegot 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

一応オプション指定による容量の変化を確認しています。また gitgot 間での違いも大きく、この差違が何故発生するかは不明です。
何かしらのオーバーヘッドと思われますが…。

ワークツリーの更新

$ cd /usr/ports && git pull

上記コマンド実行に相当する got コマンドは下記の通りとなります。

$ cd /usr/ports && got fetch && got update

本ケースにおけるおおよその使い方はこんな所です。開発フローで必要になる使い方についてはコマンド対応表他、参考文献を参照ください。

オマケの tog コマンド

ncursesベースのログビュワーです。1行ログを表示しつつ、そのログを選択(リターンキー)を押すと、詳細ログと修正内容が表示されるという便利なツールです。
Gitのサードパーティツールにある tig コマンド相当とのことです。

インフォメーション

Gotではリポジトリとワークツリーとで使うべきコマンドが違います。具体的にはこれらは gotadmingot となります。
とは言え安全に使えそうなサブコマンドは 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 updategot mergegot rebasegot 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.ちゃんと使ってレポートしましょう。ベースシステムに入れても十分な品質かまでは現時点では言及できないはずです。
少なくとも自分が触った範疇ではまだその品質に達してないように見えます。

参考文献

  1. Game of Trees Goalsより

  2. Ports Collection のインストール

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1