GitBucketではバックエンドの実装にJGitを使っているのですが、gitリポジトリをzipファイルとしてダウンロードした際に、同じコミットでもダウンロードしたzipファイルのハッシュが同じ値にならないというレポートがあり、調べたところJGitのarchiveコマンド部分の実装に問題があることがわかったため*1、JGitにフィードバックを行ってみました。
こちらがGitBucketのユーザさんからいただいたレポートです。
JGitへのコントリビューション方法
さて、JGitはオープンソースプロジェクトではありますが、Eclipse Foundationで開発されているものなので、Apache Software Foundationと同じくコントリビューションは面倒そうな予感がします。GitHubにリポジトリがあるのですがどうやらこちらはミラーのようで、プルリクエストを送っても受け付けてもらえないようです。
調べてみたところ、コントリビューター向けのガイドがありました。どうやらGerritでコードレビューの依頼をする必要があるようです。もちろん事前にアカウントを作成してCLAへの同意などを行っておく必要があります。*2
Gerritによるコードレビュー
Gerritは1コミット=1プルリクエストのような感じでレビューを行います。以下のようにrefs/for/master
にpushすることでレビュー依頼が登録されます。
git push ssh://username@git.eclipse.org:29418/jgit/jgit.git HEAD:refs/for/master
レビューを受けて修正する場合は元のコミットにamendするなどして新しいコミットをpushするわけですが、以前のコミットと紐づけるためにコミットメッセージにChange-Id
を含めておく必要があります。また、修正者を明示するためにアカウントの情報をSigned-off-by
に含めておく必要もあります。JGitのGerritではこれらのフィールドが含まれていないとpushがリジェクトされました。
実際にpushしたコメントはこんな感じです。
Set commit time to ZipArchiveEntry Archived zip files for a same commit have different MD5 hash because mdate and mdate in the header of zip entries are not specified. In this case, Commons Compress sets an archived time. In the original git implementation, it's set a commit time: https://github.com/git/git/blob/e2b2d6a172b76d44cb7b1ddb12ea5bfac9613a44/archive.c#L378 By this fix, archive command sets the commit time to ZipArchiveEntry when RevCommit is given as an archiving target. Change-Id: I30dd8710e910cdf42d57742f8709e9803930a123 Signed-off-by: Naoki Takezoe <takezoe@gmail.com>
Change-Id
はコミットフックで自動的に付与することができます。フックスクリプトは通常Gerritサーバで提供されており、JGitの場合は以下のようにしてローカルリポジトリにインストールすることができました。
scp -p -P 29418 username@git.eclipse.org:hooks/commit-msg .git/hooks/
これで修正をローカルリポジトリにコミットした時点でコミットメッセージにChange-Id
が自動的に追加されます(修正時など、すでにChange-Id
が付与されている場合は何も行いません)。
レビューで指摘があった場合は修正して再度pushすると新しいpatch setが作成されます。前述の通り、Gerritは1コミットが1プルリクエストに相当するのですが、patch setによって1コミット内のレビューや変更の履歴を管理することができます。もちろん途中のpatch setからやり直したりということもできます。
ちなみに以下が今回フィードバックした修正のレビューです。JGit 4.7でマージしていただけるようです。
https://git.eclipse.org/r/#/c/91116/
感想
JGitは目立たないライブラリではありますが、JVMベースの様々な開発者向けツールで使用されており、もちろんGitBucketでも活用させていただいているので、ちょっとした修正ではありますが貢献できて嬉しいところです。
また、Gerritは初めて使ったのですが、綺麗なコミット履歴を保ちつつ、その過程も管理できるという点はメリットだと感じました。ただ、Gitの操作が複雑なだけでなく*3、Web UIも非常にわかりづらく初見だと何をしていいのかさっぱりわからないという敷居の高さがあります。
最近は企業が主体となって開発しているOSSや、ASFのプロダクトなどでもGitHubでのプルリクエストを受け付けてくれるものが増えてきていますが、golangなどGerritを使ってレビューを行っているプロジェクトもあります。今回の作業はGerritの使い方も含め勉強になりました。
Gerritの使い方を手取り足取り教えてくれた弊社ターミナル部部長である@tanacasinoに感謝の意を表したいと思います。ありがとうありがとう。