Qtプロジェクトにコミットしようよ

この記事はQt Advent Calendar 2014 - Qiitaの22日目のエントリーです。

この記事を読んで君もQt Contributorだ!

さて、Git初心者、英語壊滅的な僕がとある理由でQtプロジェクトコミットした時のことを振り返りながら手順を紹介します。
Gitのことをよく知らないと人からこうやってあーやってこうするんだよとコマンドとか用語を言われてもバットの振り方を擬音で説明されているような感じです。コマンドなどを実行した結果や挙動がわからないし、やり直しが効くのかもよくわからないのでドキドキしながら作業してました。
なのでだいぶ丁寧目に説明をしたいと思います。Gitとか知ってる人にはかったるくなるかもしれませんがご容赦ください。

そう、難しくないんです。(パッチが簡単に受け入れられるとは言ってない。)

今回はQt本体ではなくQt Installer Frameworkにコミットしたときの作業を振り返って説明しますがやることは同じです。
(冬コミの本でQt Installer Frameworkを紹介するし変なところ直したかったの、それがとある理由)

わからないことあったら
日本Qtユーザー会のメーリングリストに投稿
日本Qtユーザー会の勉強会に参加
・Twitterに#qtjpでつぶやく
などです。

参考にしたサイト
Qtプロジェクトにコミットしてみた

やってみたらそんなに難しくないですよ!ってことではじまりはじまり。

/// 環境 ///
以下の環境で作業しました。
 ・Ubuntu 14.04(64bit) on VMWare


/// ユーザー登録 ///
Qt Bug Trackerのサイトでユーザー登録します。
https://bugreports.qt-project.org/secure/Dashboard.jspa
ソースコードを管理しているGerritやコードレビューを行うサイトは別ですが共通になっています。
バグ報告はここで行います。


/// sshの設定 ///
~/.ssh/configにホストの情報を追加します。

Host codereview.qt-project.org
Port 29418
User username

sshキーペアを作成します。

$ ssh-keygen


/// コードレビューサイトでの設定 ///
このサイトで最初に登録したユーザー情報を使用してログインします。
 https://codereview.qt-project.org/
画面右上の「Sign in」のリンクから行います。
設定画面への移動は画面右上のユーザー名をクリックして「Settings」を選択します。
 qt-commit-01.jpg


/// 連絡事項の登録 ///
「Settings」→「Contact Information」で登録します。
ここでコードレビューサイト上やコミットログに表示する情報(名前とメールアドレス)を登録します。
 qt-commit-02.jpg

ちゃんと登録できたかは「Settings」→「Profile」で確認できます。
 qt-commit-03.jpg


/// 同意事項の確認 ///
「Settings」→「Agreements」を選択します。
一般の人は「Individual」を選択して決定します。
 qt-commit-04.jpg


/// ssh公開鍵登録 ///
「Settings」→「SSH Public Keys」で鍵の登録をする。
設定ページへ移動すると登録用のフォームが表示されます。
既に1つ以上登録していると一覧が表示されるため「Add Key...」を選択します。
~/.ssh/id_rsa.pubの中身を全て貼り付けます。
ファイルの最後のusername@pcname見たいなところも一緒に貼ってOKで、登録が終わるとこうなります。
 qt-commit-05.jpg


/// Gitの設定 ///
gitのグローバル設定をします。
名前とアドレスはコードレビューサイトのプロフィールで登録した内容です。

$ git config --global core.autocrlf input
$ git config --global user.name "Full Name"
$ git config --global user.email "Email Address"

/// ソースのクローン ///
ソースコードをクローンします。
Qt Installer Frameworkなら

$ git clone ssh://ioriayane@codereview.qt-project.org:29418/installer-framework/installer-framework

Qt5なら
$ git clone ssh://ioriayane@codereview.qt-project.org:29418/qt/qt5

~/.ssh/configの設定をしていれば
$ git clone ssh://codereview.qt-project.org/installer-framework/installer-framework

Qt関連で開発が行われているリポジトリの一覧は以下で見れます。
 https://codereview.qt-project.org/#/admin/projects/
 qt-commit-06.jpg

Qt5はサブモジュールが独立したリポジトリになっているのでこの一覧に並んでいます。いきなりそのリポジトリをクローンする機会は少ないかもしれませんが。
「Filter」に入力すると絞り込みができます。
「Project Name」の項目をクリックするとリポジトリの情報が表示されクローンするためのコマンドなどを確認できます。
コマンドが表示されているところのヘッダ(緑の帯)の「SSH」を選択します。
 qt-commit-07.jpg


/// Change-Idの自動付与設定 ///
Change-Idをコミットメッセージに自動的に挿入する設定をします。
これはリポジトリをクローンしてきたフォルダで行う必要があります。

$ scp -p codereview.qt-project.org:hooks/commit-msg .git/hooks


/// ブランチ移動 ///
最終的に修正をプッシュしたいブランチに移動します。
自分はQt Installer Frameworkの2.0ブランチにプッシュしたのでこちらへ移動します。

$ git checkout 2.0

ちなみに、作業用のブランチを別で作成する必要はないです。
お好みで作成してください。


/// コードの修正 ///
いじります。いろいろいじります。
修正したらステージ登録します。

$ git add src/libs/installer/observer.cpp


/// コミット ///
コミットします。

$ git commit

コミットメッセージは、最初の有効な1行がタイトルになります。
2行目からが詳細説明になるのですが、タイトルと説明の間に空行を1行入れます。
コミットすると以下のようにChange-Idが自動的に入ります。
$ git log
commit 93436a89cc4bb9bc7ae0072c7651d7d018c7f496
Author: Takayuki ORITO
Date: Sat Dec 13 16:34:03 2014 +0900

Updated the method of assembling a message for a better translation.

It was easier to read by adding a space.

Change-Id: Id9a28ffb33e56ea42cef44b00c4cea36d4e04007
...略

/// プッシュ ///
コミットが終わって準備OKならプッシュします。
最後がプッシュ先のブランチ名です。

$ git push ssh://codereview.qt-project.org/installer-framework/installer-framework HEAD:refs/for/2.0
Counting objects: 47, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 785 bytes | 0 bytes/s, done.
Total 6 (delta 3), reused 0 (delta 0)
remote: Resolving deltas: 100% (3/3)
remote: Processing changes: updated: 1, refs: 1, done
remote:
remote: New Changes:
remote: https://codereview.qt-project.org/#/c/102033/
remote:
To ssh://codereview.qt-project.org/installer-framework/installer-framework
* [new branch] HEAD -> refs/for/2.0

masterブランチなら

$ git push ssh://codereview.qt-project.org/installer-framework/installer-framework HEAD:refs/for/master


/// レビューの確認 ///
プッシュするとコードレビューサイトで確認できます。
ログインした状態で「My」→「Changes」で一覧が表示されます。
 qt-commit-08.jpg

項目をクリックすると以下のようなレビューページが確認できます。
レビューに対するやりとりはそれぞれのページで行います。
(画像はすでにある程度レビューが進んだ状態ですが・・・)
 qt-commit-09.jpg

「Patch Set n」のところでパッチの変更内容を確認したりできます。
今回はレビューを受ける側なのでレビューの評価方法は割愛です。


/// パッチの機械チェック ///
パッチが登録されるとレビュアーに「Qt Sanity Bot」が自動的に追加されます。
何か機械判断でマズイところがあるとこのBotに-1されます。例えば、コミットメッセージの2行目に空行がないと-1されます。
OKだと緑のチェックマークになります。


/// レビュアーの追加 ///
レビューをしてほしい人をレビュアーに追加します。
自分はQt Installer Frameworkのパッチを上げたので普段このリポジトリにコミットしている人を選んで追加しました。
また、このパッチを作る発端になった@task_jpさんも追加しました。
たすくさんを追加したい場合は、画像のように「Need Code-Review」の欄に「tas」と入力するとインクリメンタルサーチで候補を表示してくれますので適切なアカウントを選択します。選んだら「Add Reviewer」ボタンをクリックします。
 qt-commit-10.jpg
たまに、レビュアーにあえて追加しなくても自ら参加してくれる人もいます。


/// パッチへのコメント ///
レビュアーが問題箇所にコメントを入れてくれることがあります。
 qt-commit-11.jpg

コミットメッセージにツッコミが入ることもあります。
(英語がおかしいよって事らしいです。おかしいこともわからなくてゴメンナサイ)
 qt-commit-12.jpg


/// コミットメッセージの修正 ///
コミットメッセージの修正はコードレビューサイト上でできます。
コミットメッセージの枠の右上にあるノートと鉛筆マークをクリックして行います。
 qt-commit-13.jpg


/// パッチの修正(一度プッシュしたものの更新) ///
ツッコミが入ったらそれに反論して相手を納得させて我を通すかコードを修正して再度パッチをプッシュする必要があります。
コミットの修正方法というか、レビューサイト的にはパッチが増えていくので追加パッチのような感じです。
最初にプッシュした状態からコードを修正して「git commit」までやります。手順は同じです。
この状態でログの状態はこんな感じになります。

$ git log
commit 93436a89cc4bb9bc7ae0072c7651d7d018c7f496
Author: Takayuki ORITO
Date: Sat Dec 13 16:34:03 2014 +0900

Updated the method of assembling a message for a better translation.

It was easier to read by adding a space.

Change-Id: Id9a28ffb33e56ea42cef44b00c4cea36d4e04007

commit 3a6d0fd1037f84e250dd0c58eaadc79eee85f555
Author: Takayuki ORITO
Date: Fri Dec 12 22:52:19 2014 +0900

Updated the method of assembling a message for a better translation.

Change-Id: Ibcd9b10ea093426eac53ddbd3cf8c8a190dcf294

commit fb29c6c6ca89129109131d6c1a889cebcf48fc11
Author: Niels Weber
Date: Fri Dec 12 12:59:26 2014 +0100

tr() -> translate()

Change-Id: I805926a241d31f3ae6846a7429b99af4f68169fe
Reviewed-by: Kai Koehne


当然ですが最初のコミットと修正後のコミットで2つ分あります。
これを1つに合体します。
$ git rebase -i HEAD~2

このコマンドを実行するとエディタが起動して以下の内容が表示されます。
「#」で始まるコメント行に説明があります。
ここでは、どのコミットを使用するか捨てるか的な設定をします。
下に行くほど新しいコミットです。コミットログの「commit 0000~」の数字の羅列がリビジョン番号ですが。リビジョン番号の先頭7桁がpickの次に書かれてますのでこれで判別できます。
今回は新しいコミットを1つ前に合体したいので、2行目の「pick」を「s」もしくは「squash」に変更します。
変更後にCtrl+O→Enter→Ctrl+X(保存→保存先にOK→終了)をしてエディタを閉じます。
pick 3a6d0fd Updated the method of assembling a message for a better translation.
pick 93436a8 Updated the method of assembling a message for a better translation.

# Rebase fb29c6c..93436a8 onto fb29c6c
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out


エディタが閉じるとさらに次のエディタが起動してきます。
ここではコミットメッセージを合体します。2つ分のメッセージを表示してくれますので採用する内容だけ残します。
この時のポイントとして新しい方のChange-Idを消して古い方を残します。
コードレビューサイトでは、Change-Idの一致を見ています。
今回はタイトルが同じで詳細説明を追加したのでそれ以外を消します。(コメントアウトでもOK)
# This is a combination of 2 commits.
# The first commit's message is:

Updated the method of assembling a message for a better translation.

Change-Id: Ibcd9b10ea093426eac53ddbd3cf8c8a190dcf294

# This is the 2nd commit message:

Updated the method of assembling a message for a better translation.

It was easier to read by adding a space.

Change-Id: Id9a28ffb33e56ea42cef44b00c4cea36d4e04007

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# rebase in progress; onto fb29c6c
# You are currently editing a commit while rebasing branch '2.0' on 'fb29c6c'.
#
# Changes to be committed:
# modified: src/libs/installer/observer.cpp
#


こんな感じに直したら、Ctrl+O→Enter→Ctrl+X(保存→保存先にOK→終了)をしてエディタを閉じます。
# This is a combination of 2 commits.
# The first commit's message is:

Updated the method of assembling a message for a better translation.

It was easier to read by adding a space.

Change-Id: Ibcd9b10ea093426eac53ddbd3cf8c8a190dcf294

# This is the 2nd commit message:

# Updated the method of assembling a message for a better translation.

# It was easier to read by adding a space.

# Change-Id: Id9a28ffb33e56ea42cef44b00c4cea36d4e04007

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# rebase in progress; onto fb29c6c
# You are currently editing a commit while rebasing branch '2.0' on 'fb29c6c'.
#
# Changes to be committed:
# modified: src/libs/installer/observer.cpp
#


エディタを閉じたら結果として以下のように出力されればOKです。
[detached HEAD 38b8889] Updated the method of assembling a message for a better translation.
1 file changed, 8 insertions(+), 9 deletions(-)
Successfully rebased and updated refs/heads/2.0.

変更後のログは以下のように1つになっています。

$ git log
commit 38b88897db93bbc050682f70bc88a36d572c435e
Author: Takayuki ORITO
Date: Fri Dec 12 22:52:19 2014 +0900

Updated the method of assembling a message for a better translation.

It was easier to read by adding a space.

Change-Id: Ibcd9b10ea093426eac53ddbd3cf8c8a190dcf294

commit fb29c6c6ca89129109131d6c1a889cebcf48fc11
Author: Niels Weber
Date: Fri Dec 12 12:59:26 2014 +0100

tr() -> translate()

Change-Id: I805926a241d31f3ae6846a7429b99af4f68169fe
Reviewed-by: Kai Koehne


合体を確認したらプッシュします。
プッシュのコマンドはさっきと同じ。
$ git push ssh://codereview.qt-project.org/installer-framework/installer-framework HEAD:refs/for/2.0


/// レビューの完了 ///
権限のあるレビュアーさんにOKしてもらって無事に終了です。
ステータスが「Merged」になってたらお疲れ様です。
さらにツッコミ入ってたら少し戻って繰り返しです。
 qt-commit-14.jpg


/// コミットの取り消し ///
何らかの理由でコミットを取り下げてレビューを終了させたい場合は、個々のレビューのページで「Abandon Change」ボタンを押します。
理由を入力します。
たとえば、masterじゃなくて別のブランチにコミットしてくれと言われた場合などは

pushed to new hoge branch
<新しいレビューのURL>

と、入力します。


/// おわりに ///
さて、長くなりましたがひと通り説明しました。
これでみなさんもQtプロジェクトにコミットできます。
新機能の追加とかは難しいと思いますが、このクラスにこんな機能があればとか、このバグ直ってくれないと困るとかに是非チャレンジしてみてください。