Help us understand the problem. What is going on with this article?

Pijul という VCS を体験した

More than 1 year has passed since last update.

まえがき

今年は色々あって、時間も取れずアドベントカレンダーにいまいち乗り切れないまま11月となってしまった。
とはいえ、せっかくの機会なので、前年の様に手を動かすことにこだわらず、気軽に今年気になったツールの体験記や情報まとめでも記して行こうと思う。

Pijul とは

https://pijul.org/

分散型バージョン管理システム (distributed version control system) 。 Git や Mercurial の仲間。
プロジェクト自体は約 3年前にスタートしていて、今年の 11月に 0.11 がリリースされた。まだまだ若い VSC。

特徴

その最大の特徴としては、カテゴリー理論 (パッチ理論) をベースとしたデータモデルを採用している事 らしい。

カテゴリー理論 (パッチ理論)

カテゴリー理論 (パッチ理論) について深掘りする心の余裕が無かったので、とにかく情報だけ集めた。

https://jneem.github.io/merging/
https://jneem.github.io/pijul/
https://arxiv.org/pdf/1311.3903.pdf
https://pijul.org/faq/
https://pijul.org/model/
http://darcs.net/Using/Model
https://news.ycombinator.com/item?id=13643025
https://news.ycombinator.com/item?id=18235798

何となく分かったことは、

  • Git はスナップショットの履歴で、Pijul は変更差分 (パッチ) の集合
    • Git の Diff は、スナップショット同士の比較
    • Pijul の Diff は、お互いのパッチサブセットの差分の比較
  • 各パッチ間の依存関係を自動判別・保存しておき、チェリーピッキングの際に自動解決される
    • Pijul のチェリーピッキングは、Git のブランチ同士のマージに近い?
    • Hunk レベルでの依存関係はこれで良いが、関数呼び出しなどの依存関係は結局のところ破綻する?
      • それらは一つのパッチに一緒に含めるべき、というルールを守れば起こらないのか

気軽にやろうと決意した前書きとは大きくかけ離れた難しさだ。。。
深掘りは来年やろう。

Darcs との関係性

Pijul を語る上で欠かせないのが、この Darcs という VCS。
そもそも、Pijul は Darcs のパフォーマンス問題を解決するために実装されたコードがそのまま別ツールとしてリリースされたものらしい。
その為、Pijul はパッチ理論がベースにあるという点をはじめ多くの特徴を引き継いている。

http://darcs.net/

Darcs について調べると、

  • チェリーピッキングが簡単で正しく適用される
  • データモデルが直感的なので、操作も直感的

など他にない利点があったとの評価が多かったが、以下のような指摘もあった。

  • パフォーマンス問題。プロジェクトが大きくなると重い
  • Svn や Git とは違うコマンド体型
  • Git や Mercurial のようなブランチ機能を持たない

特にパフォーマンス問題が大きかったようで、対策をとっている間に Git や Mercurial などの VCS や Github を中心としたエコシステムが発達してしまったので、広く人気を得ることができなかった ( Haskeller には人気のようだ )。

Git との関係性

Pujul ドキュメント内でも Git は強く意識され、その対比で自身の特徴を説明するシーンが多い。

馴染んだコマンド体型

Pijul では、Git のコマンド体型に寄せてきていて、Git 経験者でも導入しやすいように心がけているように見える。
それでいて、非直感的なコマンドは変わってたり。
git branch -dpijul delete-branch とか個人的に Pijul の方が分かりやすい。

Git like なブランチ機能

元々、Darcs では『ブランチ=別リポジトリ (=別フォルダ )』のような考え方があったようだが、Pijul では一つのリポジトリ内でも状態を切り替えられる Git Likeなブランチ機能が導入されている。

Git のブランチは歴史の枝分かれといったイメージだが、Pijul のブランチは全パッチから抜き出したサブセットというイメージだ。

インストール

とりあえず、使ってみないことには分からないのでインストールする。

  • Windows 10 pro October 2018 Update

Install - pijul

Cargo で導入する方法もあるが、おすすめはしない。自分は引っかかりまくって時間をロスした。

おとなしく、PreBuild されたバイナリをインストールする。一緒に vcruntime140.dll も必要なので、そっちも落として pijul-0.11.0.exe と一緒に配置する。
pijul.org/downloads

2018-11-26_14h06_10.png

起動するも上手く動かないが、どうやら libssl-1_1-x64.dlllibcrypto-1_1-x64.dll が必要なようだ。
自分は scoop を使って openssl を導入していたので、その中の lib から拝借した。ちなみに、バージョンによっては含まれていないケースもあるらしい。1.1.0h には含まれていなかった。

これで、

$ pijul -V
pijul 0.10.1

上手くいった。 0.11.0 を入れたのに 0.10.1 なのはご愛嬌。

実践

ということで、実践しながら操作感を確かめていく。
最近お気に入りの nim プロジェクトを構築しながら Pijul でバージョン管理していく。

1. 初期化

まずは、プロジェクトを作成し、Pijul で管理するための初期化を行う。

pijul init

https://pijul.org/manual/reference/init.html

$ nimble init.

$ tree
# ├── sample_1202.nimble
# └── src
#    └── sample_1202.nim

$ pijul init

$ tree
# .
# ├── .pijul
# │  ├── hooks
# │  ├── id
# │  ├── local
# │  │  └── ignore
# │  ├── patches
# │  ├── pristine
# │  │  ├── db
# │  │  └── db.lock
# │  └── version
# ├── sample_1202.nimble
# └── src
#    └── sample_1202.nim

Git の .git フォルダに対応するのが、 .pijul フォルダかな。

2. 変更の追跡・記録・破棄

pijul status

https://pijul.org/manual/reference/status.html

現在のリポジトリの状態を把握するには、pijul status が使える。

$ pijul status
# On branch master
# 
# Untracked files:
#   (use "pijul add <file>..." to track them)
# 
#         src
#         sample_1202.nimble
#         src\sample_1202.nim

pijul add

https://pijul.org/manual/reference/add.html

ファイルの変更を追跡するためには、pijul add をする必要がある。

$ pijul add src\sample_1202.nim sample_1202.nimble

$ pijul status
# On branch master
# 
# Changes not yet recorded:
#   (use "pijul record ..." to record a new patch)
# 
#         new file:  sample_1202.nimble
#         new file:  src
#         new file:  src\sample_1202.nim

追跡が始まったが、まだ記録はされていない状態。

pijul record

https://pijul.org/manual/reference/record.html

Git であれば、 commit コマンドを使うところだが、Pijul では pijul record で変更を記録する。

$ pijul record
# added file sample_1202.nimble
# 
# Shall I record this change? (1/5) [ynkadi?] y
# 
# In file "sample_1202.nimble"
# 
# + # Package
# +
# + version       = "0.1.0"
# + author        = "username"
# + description   = "A new awesome nimble package"
# + license       = "MIT"
# + srcDir        = "src"
# + bin           = @["sample_1202"]
# +
# +
# + # Dependencies
# +
# + requires "nim >= 0.19.0"
# 
# Shall I record this change? (2/5) [ynkad?] y
# 
# added file src
# 
# Shall I record this change? (3/5) [ynkadi?] y
# 
# added file src\sample_1202.nim
# 
# Shall I record this change? (4/5) [ynkadi?] y
# 
# In file "src\\sample_1202.nim"
# 
# + # This is just an example to get you started. A typical binary package
# + # uses this file as the main entry point of the application.
# +
# + when isMainModule:
# +   echo("Hello, World!")
# 
# Shall I record this change? (5/5) [ynkad?] y
# 
# first commit
# What is the name of this patch? Recorded patch 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi

$ pijul status
# On branch master
# Nothing to record, working tree clean

変更は一つづつ [ynkadi] を聞かれ、このパッチに含めるかどうかを判断する必要がある。

y: record this change
n: don't record this change
k: go back to the previous change
a: record all remaining changes
d: skip all remaining changes

一つ注意する点として、すべての Yes or No を判断した後、キャレットが左端で点滅しているので『処理待ちかな?』と思っていたら、どうやらコミットメッセージを待っているようなのだ。これは気が付かない

2018-11-23_12h19_41.png
↑ この部分

pijul record -m "first commit" とメッセージをオプションで渡すこともできる。こっちのほうがびっくりしないのでオススメ。
また、すべての追跡対象の変更をパッチ化する場合には、pijul record -a で一発。

pijul log

https://pijul.org/manual/reference/log.html

パッチの履歴を見る場合は pijul log

$ pijul log
# Hash: 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi
# Internal id: JA4E96crMn8
# Authors:
# 
# Timestamp: 2018-11-23 03:19:14.245532200 UTC
# 
#     first commit

pijul ls

https://pijul.org/manual/reference/ls.html

追跡中のファイル一覧を確認する場合は pijul ls

$ pijul ls
# sample_1202.nimble
# src
# src\sample_1202.nim

pijul patch

https://pijul.org/manual/reference/patch.html

パッチの内容を確認する場合は pijul patch <<Patch Hash>>

$ pijul patch 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi
# In "["sample_1202.nimble"]":
# From line 1:
# + # Package
# +
# + version       = "0.1.0"
# + author        = "username"
# + description   = "A new awesome nimble package"
# + license       = "MIT"
# + srcDir        = "src"
# + bin           = @["sample_1202"]
# +
# +
# + # Dependencies
# +
# + requires "nim >= 0.19.0"
# In "["src", "sample_1202.nim"]":
# From line 1:
# + # This is just an example to get you started. A typical binary package
# + # uses this file as the main entry point of the application.
# +
# + when isMainModule:
# +   echo("Hello, World!")

pijul diff

https://pijul.org/manual/reference/diff.html

まだパッチ化されていないローカル変更の差分を確認する場合は pijul diff で可能。

まずは、src\sample_1202.nim ファイルを以下のように変更して

when isMainModule:
+   echo("Good Morning, World!")
  echo("Hello, World!")
+   echo("Good Night, World!")

差分を確認すると、

$ pijul diff
# In file "src\\sample_1202.nim"
# 
# +   echo("Good Morning, World!")
# 
# +   echo("Good Night, World!")

もう一度、pijul record

上記変更をした上で、もう一度パッチを作成する。
ポイントとしては、Pijul は Git でいうインデックスが無いので、追跡対象ファイルの差分はすべて record の対象となる

$ pijul status
# On branch master
# 
# Changes not yet recorded:
#   (use "pijul record ..." to record a new patch)
# 
#         modified:  src\sample_1202.nim

$ pijul record
# In file "src\\sample_1202.nim"
# 
# +   echo("Good Morning, World!")
# 
# Shall I record this change? (1/2) [ynkad?] y
# 
# +   echo("Good Night, World!")
# 
# Shall I record this change? (2/2) [ynkad?] y
# 
# second commit
# What is the name of this patch? Recorded patch 6mLyhM75oVJpzDBTkhBxPC3zjSztDCXE2PuSDsQHQiuHb2vXNLNDipbVBRTpeYfMgK9B1puQMgLfqgvD57SeH7xK

ここで一つ気がつくことは、パッチは Hunk 単位で選択可能 ということ。
これは、git add -p と同様の機能が標準であるということ。賢く Hunk 化してくれるなら便利。

pijul unrecord

https://pijul.org/manual/reference/unrecord.html

一度記録したパッチを無かったことにする場合、pijul unrecord <<Patch Hash>> を使う。

$ pijul log
# Hash: 6mLyhM75oVJpzDBTkhBxPC3zjSztDCXE2PuSDsQHQiuHb2vXNLNDipbVBRTpeYfMgK9B1puQMgLfqgvD57SeH7xK
# Internal id: 6Qbvwo8Xm7Z
# Authors:
# 
# Timestamp: 2018-11-23 03:43:08.077835100 UTC
# 
#     second commit
# 
# 
# Hash: 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi
# Internal id: JA4E96crMn8
# Authors:
# 
# Timestamp: 2018-11-23 03:19:14.245532200 UTC
# 
#     first commit
# 

$ pijul unrecord 6mLyhM75oVJpzDBTkhBxPC3zjSztDCXE2PuSDsQHQiuHb2vXNLNDipbVBRTpeYfMgK9B1puQMgLfqgvD57SeH7xK

$ pijul log
# Hash: 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi
# Internal id: JA4E96crMn8
# Authors:
# 
# Timestamp: 2018-11-23 03:19:14.245532200 UTC
# 
#     first commit
# 

$ pijul diff
# In file "src\\sample_1202.nim"
# 
# +   echo("Good Morning, World!")
# 
# +   echo("Good Night, World!")

確かにパッチが記録されたという事実は削除されたが、ファイルの変更はそのままだった。
Git のようにインデックスが無いため完全に同等ではないが、 git reset --mixed/--soft 相当の機能と思われる。

pijul revert

https://pijul.org/manual/reference/revert.html

記録されていない変更を無かったことにする場合は、pujul revert を使う。

$ pijul diff
# In file "src\\sample_1202.nim"
# 
# +   echo("Good Morning, World!")
# 
# +   echo("Good Night, World!")

$ pijul revert
# In file "src\\sample_1202.nim"
# 
# +   echo("Good Morning, World!")
# 
# Shall I revert this change? (1/2) [ynkad?] y
# 
# +   echo("Good Night, World!")
# 
# Shall I revert this change? (2/2) [ynkad?] y

$ pijul diff
# 

git reset --hard HEAD みたいな感じだろうか。

pijul remove

https://pijul.org/manual/reference/remove.html

追跡をやめたいファイルがある場合は、pujul remove <<ファイル>> を使う。

$ nimble build
#   Verifying dependencies for sample_1202@0.1.0               
#   Building sample_1202/sample_1202.exe using c backend      

$ pijul status
# On branch master
# 
# Untracked files:
#   (use "pijul add <file>..." to track them)
# 
#         sample_1202.exe

$ pijul add sample_1202.exe

$ pijul status
# On branch master
# 
# Changes not yet recorded:
#   (use "pijul record ..." to record a new patch)
# 
#         new file:  sample_1202.exe

$ pijul remove sample_1202.exe

$ pijul status
# On branch master
# 
# Untracked files:
#   (use "pijul add <file>..." to track them)
# 
#         sample_1202.exe

ちなみに、いつも Untrackd files に出てくるのが邪魔だったら、明示的に無視することもできる。
.ignore.pijulignore ファイルを置いて、その中に無視したいファイルを追加する。

$ pijul status
# On branch master
# 
# Untracked files:
#   (use "pijul add <file>..." to track them)
# 
#         sample_1202.exe

$ echo "sample_1202.exe" > .pijulignore

$ pijul status
# On branch master
# 
# Untracked files:
#   (use "pijul add <file>..." to track them)
# 
#         .pijulignore

.gitignore の様にワイルドカードの指定も可能。

2. ブランチ操作

pijul fork

https://pijul.org/manual/reference/fork.html

ブランチを作成するには、pijul fork を使う。

$ pijul status
# On branch master
# Nothing to record, working tree clean

master ブランチをフォーク元として、新しく newbranch を作成する。

$ pijul log
# Hash: 6XBqejgpKyKETHqYuoEGdMmqJkJ6Lj1ZNrhaez9cbKJrCeyRdhbKPjPJX9nLFaKA7jUC24NjZZQgGqU61JEEXLvV
# Internal id: 4NAHqDtPyoj
# Authors:
# 
# Timestamp: 2018-11-23 04:14:36.624109200 UTC
# 
#     add ignore file
# 
# Hash: 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi
# Internal id: JA4E96crMn8
# Authors:
# 
# Timestamp: 2018-11-23 03:19:14.245532200 UTC
# 
#     first commit
# 

$ pijul fork newbranch

$ pijul status
# On branch newbranch
# Nothing to record, working tree clean

試しに、newbranchsrc\sample_1202.nim を修正してみる。

$ pijul diff
# In file "src\\sample_1202.nim"  
#                                 
# -   echo("Hello, World!")       
# +   echo("Hello, Mars!")        

$ pijul record
# In file "src\\sample_1202.nim"
# 
# -   echo("Hello, World!")
# +   echo("Hello, Mars!")
# 
# Shall I record this change? (1/1) [ynkad?] y
# 
# go to mars
# What is the name of this patch? Recorded patch 7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZC

$ pijul log
# Hash: 7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZC
# Internal id: Bve1Gm9QMuB
# Authors:
# 
# Timestamp: 2018-11-23 04:21:05.123480300 UTC
# 
#     go to mars
# 
# 
# Hash: 6XBqejgpKyKETHqYuoEGdMmqJkJ6Lj1ZNrhaez9cbKJrCeyRdhbKPjPJX9nLFaKA7jUC24NjZZQgGqU61JEEXLvV
# Internal id: 4NAHqDtPyoj
# Authors:
# 
# Timestamp: 2018-11-23 04:14:36.624109200 UTC
# 
#     add ignore file
# 
# Hash: 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi
# Internal id: JA4E96crMn8
# Authors:
# 
# Timestamp: 2018-11-23 03:19:14.245532200 UTC
# 
#     first commit

これで、newbranch には 7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZC が追加されたが、

$ pijul log --branch master
# Hash: 6XBqejgpKyKETHqYuoEGdMmqJkJ6Lj1ZNrhaez9cbKJrCeyRdhbKPjPJX9nLFaKA7jUC24NjZZQgGqU61JEEXLvV
# Internal id: 4NAHqDtPyoj
# Authors:
# 
# Timestamp: 2018-11-23 04:14:36.624109200 UTC
# 
#     add ignore file
# 
# Hash: 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi
# Internal id: JA4E96crMn8
# Authors:
# 
# Timestamp: 2018-11-23 03:19:14.245532200 UTC
# 
#     first commit

master ブランチには、7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZC が存在していない事が分かる。

pijul branches

[公式ドキュメントに記載なし]

ブランチ一覧を表示するには、pijul branches を使う。

$ pijul branches
#   master
# * newbranch

pijul checkout

https://pijul.org/manual/reference/checkout.html

ブランチを変更するには、pijul checkout を使う。

$ pijul branches
#   master
# * newbranch

$ pijul checkout master
# Current branch: "master"

$ pijul branches
# * master
#   newbranch

pijul apply

https://pijul.org/manual/reference/apply.html

Pijul の醍醐味である、チェリーピッキングを行うには pijul apply を使う。

$ pijul log --branch master
# Hash: 6XBqejgpKyKETHqYuoEGdMmqJkJ6Lj1ZNrhaez9cbKJrCeyRdhbKPjPJX9nLFaKA7jUC24NjZZQgGqU61JEEXLvV
# Internal id: 4NAHqDtPyoj
# Authors:
# 
# Timestamp: 2018-11-23 04:14:36.624109200 UTC
# 
#     add ignore file
# 
# Hash: 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi
# Internal id: JA4E96crMn8
# Authors:
# 
# Timestamp: 2018-11-23 03:19:14.245532200 UTC
# 
#     first commit
# 

$ pijul log --branch newbranch
# Hash: 7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZC
# Internal id: Bve1Gm9QMuB
# Authors:
# 
# Timestamp: 2018-11-23 04:21:05.123480300 UTC
# 
#     go to mars
# 
# 
# Hash: 6XBqejgpKyKETHqYuoEGdMmqJkJ6Lj1ZNrhaez9cbKJrCeyRdhbKPjPJX9nLFaKA7jUC24NjZZQgGqU61JEEXLvV
# Internal id: 4NAHqDtPyoj
# Authors:
# 
# Timestamp: 2018-11-23 04:14:36.624109200 UTC
# 
#     add ignore file
# 
# Hash: 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi
# Internal id: JA4E96crMn8
# Authors:
# 
# Timestamp: 2018-11-23 03:19:14.245532200 UTC
# 
#     first commit
#

この、newbranch7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZCmaster にチェリーピッキングする。

$ pijul branches
# * master
#   newbranch

$ pijul apply 7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZC

$ pijul log
# Hash: 7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZC
# Internal id: Bve1Gm9QMuB
# Authors:
# 
# Timestamp: 2018-11-23 04:21:05.123480300 UTC
# 
#     go to mars
# 
# 
# Hash: 6XBqejgpKyKETHqYuoEGdMmqJkJ6Lj1ZNrhaez9cbKJrCeyRdhbKPjPJX9nLFaKA7jUC24NjZZQgGqU61JEEXLvV
# Internal id: 4NAHqDtPyoj
# Authors:
# 
# Timestamp: 2018-11-23 04:14:36.624109200 UTC
# 
#     add ignore file
# 
# Hash: 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi
# Internal id: JA4E96crMn8
# Authors:
# 
# Timestamp: 2018-11-23 03:19:14.245532200 UTC
# 
#     first commit
#

チェリーピッキングされたパッチのハッシュは変更されておらず、またマージコミットのようなものも作成されていない。
とても自然だ。
( Fast-Forward なので、驚くのもアレなんだけど。もっと良い例にすれば良かった )

pijul delete-branch

https://pijul.org/manual/reference/delete-branch.html

ブランチを削除するには pijul delete-branch を使う。

$ pijul delete-branch newbranch

$ pijul branches
# * master

3. チーム開発

Git に Github があるように、Pijul には Nest (2018/11/27 現在停止中) がある。
Nest を使ってリモートリポジトリを利用したチーム開発をやってみる。

pijul key

https://pijul.org/manual/reference/keys.html

Pijul では、2つの用途で SSH キーを利用する。

  1. パッチへの署名
  2. リモートリポジトリへのアクセス

● パッチへの署名

パッチへ署名するためのキーは、以下コマンドで作成できる。デフォルトで Ed25519 の鍵ペアが作られる。

# グローバルキー
$ pijul key gen --signing

# ローカルキー
$ pijul key gen --signing --local

グローバルキーは C:\Users\<<usename>>\.pijulconfigsig_ed25519sig_ed25519.pub が作成される。
ローカルキーは <<Project Root>>\.pijulsig_ed25519sig_ed25519.pub が作成される。
ローカルキーが優先される。

どちらかの鍵が作られると、以降はすべてのパッチに署名がつく。
それを Pijul CLI から確認する方法は分からなかったが、 <<Project Root>>\.pijul\patches 以下に <<Patch Hash>>.sig という JSON ファイルが作成されている。

<>.sig
{
  "hash":"<<パッチハッシュ>>",
  "signatures":{
    "<<公開鍵ハッシュ>>":"<<署名>>"
  }
}

● リモートリポジトリへの登録

# グローバルキー
$ pijul key gen --ssh

# ローカルキー
$ pijul key gen --ssh --local

グローバルキーは C:\Users\<<usename>>\.pijulconfig の中に、ローカルキーは <<Project Root>>\.pijul の中に id_ed25519id_ed25519.pub が作成される。

また、作成した鍵をリモートリポジトリに登録するためのコマンドも用意されている (サーバ落ちてるので使ったことはない)

# グローバルキー
$ pijul key upload <url>

# ローカルキー
$ pijul key upload --local <url>

pijul clone

https://pijul.org/manual/reference/clone.html

リポジトリを複製するためのコマンド。

$ pijul clone https://nest.pijul.com/pijul_org/pijul

また、このコマンドは必ずしもリモートを対象とする必要はなく、あくまで url or path で表現されたリポジトリをコピーするためのコマンドであるため、ローカルディレクトリでも実は問題ない。

$ pijul clone src_project copied_project

pijul push, pijul pull

https://pijul.org/manual/reference/push.html
https://pijul.org/manual/reference/pull.html

リモートリポジトリからパッチを取得 / パッチを送信する為のコマンド。
現在、nest が使えないので、ローカルディレクトリで仮想的にやってみる。

$ cd ..                                              

$ pijul clone sample_1202 other_sample_1202          
# Pulling patches: 100% (3/3), done.                    
# Applying patches: 100% (3/3), done.                   

$ pijul clone sample_1202 remote_sample_1202         
# Pulling patches: 100% (3/3), done.                    
# Applying patches: 100% (3/3), done.                   
remote_sample_1202 リモートリポジトリ
sample_1202 ローカルリポジトリ 1
other_sample_1202 ローカルリポジトリ 2

sample_1202 で変更して、push してみる。

$ cd sample_1202                                            

$ pijul log --hash-only  # 長いので Hash だけ
# 6eFvL0vf4228RZ4zIMl3QYNkvtkEPmdR8nMm4hKlvTpqgILTodkJh2ukXlUuMHtJEBswp00QD8VTSlgwnpPW2zPhzx9LY8Z3cDjL
# 7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZC:0
# 6XBqejgpKyKETHqYuoEGdMmqJkJ6Lj1ZNrhaez9cbKJrCeyRdhbKPjPJX9nLFaKA7jUC24NjZZQgGqU61JEEXLvV:1
# 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi:2

$ pijul diff
# In file "src\\sample_1202.nim"
# 
# -   echo("Hello, Mars!")
# +   echo("Hello, Jupiter!")

$ pijul record
# In file "src\\sample_1202.nim"
# 
# -   echo("Hello, Mars!")
# +   echo("Hello, Jupiter!")
# 
# Shall I record this change? (1/1) [ynkad?] y
# 
# go to jupiter
# What is the name of this patch? Recorded patch 6PQoiSFhwaVz6H78rpH4ewhrm9AgxsSKCbnqU9taS8nN6S4X8So8TPH2zvkhuCMJY79LDcL6dpWC196csGMMqDZj

$ pijul log --hash-only
# 6eFvL0vf4228RZ4zIMl3QYNkvtkEPmdR8nMm4hKlvTpqgILTodkJh2ukXlUuMHtJEBswp00QD8VTSlgwnpPW2zPhzx9LY8Z3cDjL
# 6PQoiSFhwaVz6H78rpH4ewhrm9AgxsSKCbnqU9taS8nN6S4X8So8TPH2zvkhuCMJY79LDcL6dpWC196csGMMqDZj:0  # ← 増えてる
# 7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZC:1
# 6XBqejgpKyKETHqYuoEGdMmqJkJ6Lj1ZNrhaez9cbKJrCeyRdhbKPjPJX9nLFaKA7jUC24NjZZQgGqU61JEEXLvV:2
# 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi:3

$ pijul push ..\remote_sample_1202
# Hash: 6PQoiSFhwaVz6H78rpH4ewhrm9AgxsSKCbnqU9taS8nN6S4X8So8TPH2zvkhuCMJY79LDcL6dpWC196csGMMqDZj
# Internal id: 3F6x1mrWp6A
# Authors:
# 
# Timestamp: 2018-11-23 05:16:17.734130100 UTC
# 
#     go to jupiter
# 
# 
# Shall I push this patch? [ynkad?] y

remote_sample_1202 を確認してみると、

$ cd ..\remote_sample_1202

$ pijul log --hash-only
# gxrv4obMWGn54OFKHVx6542FWbKzz88yRvyxsAP24w5agr7JRBauQF79PHK2DlBa75noy5IG0IKh0eHkJWumbzEZStFWKx6tdFgd
# 6PQoiSFhwaVz6H78rpH4ewhrm9AgxsSKCbnqU9taS8nN6S4X8So8TPH2zvkhuCMJY79LDcL6dpWC196csGMMqDZj:0  # ← 増えてる
# 6XBqejgpKyKETHqYuoEGdMmqJkJ6Lj1ZNrhaez9cbKJrCeyRdhbKPjPJX9nLFaKA7jUC24NjZZQgGqU61JEEXLvV:1
# 7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZC:2
# 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi:3

other_sample_1202 で pull してみる。

$ cd ..\other_sample_1202

$ pijul log --hash-only
# jYdKkshCFAs1KFN27Te9oW3VzUQaCtF4l25VTAUuUmOi5lLpNthrS8ibdfKx3npjHylZOmCEhbyKwSv1fhAhKQSNQcBQKMhbMWPY
# 6XBqejgpKyKETHqYuoEGdMmqJkJ6Lj1ZNrhaez9cbKJrCeyRdhbKPjPJX9nLFaKA7jUC24NjZZQgGqU61JEEXLvV:0
# 7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZC:1
# 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi:2

$ pijul pull ..\remote_sample_1202
# Pulling patches: 100% (1/1), done.
# Hash: 6PQoiSFhwaVz6H78rpH4ewhrm9AgxsSKCbnqU9taS8nN6S4X8So8TPH2zvkhuCMJY79LDcL6dpWC196csGMMqDZj
# Authors:
# 
# Timestamp: 2018-11-23 05:16:17.734130100 UTC
# 
#     go to jupiter
# 
# 
# Shall I pull this patch? [ynkad?] y
# Applying patches: 100% (1/1), done.

$ pijul log --hash-only
# jYdKkshCFAs1KFN27Te9oW3VzUQaCtF4l25VTAUuUmOi5lLpNthrS8ibdfKx3npjHylZOmCEhbyKwSv1fhAhKQSNQcBQKMhbMWPY
# 6PQoiSFhwaVz6H78rpH4ewhrm9AgxsSKCbnqU9taS8nN6S4X8So8TPH2zvkhuCMJY79LDcL6dpWC196csGMMqDZj:0
# 6XBqejgpKyKETHqYuoEGdMmqJkJ6Lj1ZNrhaez9cbKJrCeyRdhbKPjPJX9nLFaKA7jUC24NjZZQgGqU61JEEXLvV:1
# 7RbjQKRMXL7MaC8naU29bGV1obYudvntGSVfEuDmpf9JAChhcbwb944hFQtdVcaujtcc4KCa1z3A8fPHNLpzNaZC:2
# 8AoNvRnRvhnTyMCZmdQbpdwqBr6Ax4WNsHYL7f55iHkGw7bttoUuoiDetQmmK7iWq53tecQwRTn1wFqMy7BpL7Pi:3

$ cat src\sample_1202.nim
# # This is just an example to get you started. A typical binary package
# # uses this file as the main entry point of the application.
# 
# when isMainModule:
#   echo("Hello, Jupiter!")

共有できている。

Git と違い、追跡ブランチが無いため git fetch して git merge みたいな操作はできない。そもそも、マージが起こらないということであれば、その必要もないのか。

感覚としては、リモートリポジトリも一つのブランチで、pull はリモートリポジトリの未取得パッチを apply しているような。

と、こんな感じで大体の動きが確認できた。
あとは気になるのが、衝突したときの挙動 だ。

衝突と解決

とても気になるのが、衝突をどう解決するのか。
Pijul のドキュメントを見ていると、様々な場面で

  • Pijul はパッチの集合
  • パッチは基本前後を入れ替えても問題ない
  • 過去に適用したパッチを非適用しても問題ない

みたいな説明を見た。
けど、衝突と解決を行ったら、それらは崩れてしまいそうに思う。

多分、答えは以下等を読むと分かりそうだが、そこそこ難しい。

https://jneem.github.io/merging/
https://jneem.github.io/pijul/
https://arxiv.org/pdf/1311.3903.pdf

今はそっとしておく。

もっとこうして欲しい

そっけない態度

レスポンスが結構簡素で、 pijul add しても pijul apply しても「しました!」みたいな反応をくれない。

HEAD がない

Git の HEAD みたいなのがあると、pijul unrecord HEAD みたいにできるんだけど。
時系列的な意味合いを含む HEAD (先頭) は Pijul 的には正しくないのかもしれないが。

あとがき

※ この記事は個人の見解であり、所属する組織を代表するものではありません。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away