2011年1月18日火曜日

【翻訳】Gitのコミットメッセージに関する注意点

Tim Popeさんの "A Note About Git Commit Messages" を翻訳しました。
元記事はこちら: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
(翻訳の公開は本人より許諾済みです)

翻訳の間違い等があればブログコメントやTwitter(@oshow)などで遠慮無くご指摘ください。

Gitのコミットメッセージ
に関する注意点


 良い形式のコミットメッセージを書くということについて、時間を取って説こうと思う。私が考えるに、コミットメッセージ形式に関するベストプラクティスは、Git を素晴らしくしてくれる小さなディティールの一つだ。rails.git への最初のコミットのいくつかは、(折り返しのない)長文による多様なコミットメッセージを含んでおり、なぜこれがはっきり言ってお粗末なプラクティスであるかを詳しく述べたいと思う。

ここにモデルとなるGitのコミットメッセージがある:
Short (50 chars or less) summary of changes

More detailed explanatory text, if necessary.  Wrap it to about 72
characters or so.  In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body.  The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.

Write your commit message in the present tense: "Fix bug" and not "Fixed
bug."  This convention matches up with commit messages generated by
commands like git merge and git revert.

Further paragraphs come after blank lines.

- Bullet points are okay, too

- Typically a hyphen or asterisk is used for the bullet, preceded by a
  single space, with blank lines in between, but conventions vary here

- Use a hanging indent
変更に対する短い(50文字以下の)要約

もし必要なら、より詳しい説明を述べる。約72文字ほどで折り返すようにせよ。
ある文脈では、最初の行はE-Mailの件名になり、残りのテキストが本文になる。
空行で本文と要約を分離するのは絶対に必要だ(本文を省略していない限り)。
もしも二つを繋げてしまうと、rebaseのようなツールが混乱する可能性がある。

現在時制でコミットメッセージを書くこと。"Fixed bug"ではなく"Fix bug"だ。
この慣習は git merge や git revert のようなコマンドが生成したコミット
メッセージと調和する。

さらなる段落があれば空行の後に続けられる。

- 箇条書きも問題ない

- 箇条書きにはハイフンかアスタリスクが使われ、一つスペースを空けてから
  書き始め、合間には空行が入るのが通常だが、この部分の慣習は多種多様だ

- ぶら下げインデント(一行目だけ飛び出して後はインデントする)を使うこと

 コミットメッセージを72文字で折り返すのがなぜ良い事なのかという理由の説明から始めよう。
  • git log はコミットメッセージに対して、なんらの折り返しもしてくれない。デフォルトのページャである less -S では、これは文章が画面外に飛び出してしまうことを意味し、読み辛くなってしまう。横幅80文字のターミナルでは左側のインデントのために4文字引き、右側も釣り合うよう4文字引くなら、残されたのは72文字だ。
  • 訳注: ちなみに、
    $ git config --global core.pager 'less -R'
    とすれば長くても折り返すようになります。もしダメなら以下で。
    $ git config --global core.pager 'LESS=-R less'
    (2014年10月23日追記):Git 2.1.0 からは、デフォルトで折り返しをするようになりました。なので上記のような設定変更は不要です。

  • git format-patch --stdout は一連のコミットをe-mailに変換し、メール本文にコミットメッセージを使用する。良いe-mailネチケットは、横幅80文字のターミナルにおいても溢れないよう、引用表示が何回かネストした時のための余裕を持たせるようにプレーンテキストのe-mailの折り返しを規定している(現在の rails.git のワークフローはe-mailではなく、未来的な何かを組み込んでいるのだろうが)。
Vim ユーザは私の vim-git プラグインをインストールするか、単にGitのコミットメッセージファイルに対して以下のオプションを設定することで、この要件を満たすことができる。
:set textwidth=72
Textmate では、view メニュー下の "Wrap Column" オプションを調節し、^Q を使って文章の折り返しを再適用できる(その後必ず、コメントが混ざるのを避けるために、空行があるか確認すること)。メニューに72文字折り返しを追加するシェルコマンドを以下に用意したので、選択するために何度もドラッグする必要はない。
$ defaults write com.macromates.textmate OakWrapColumns '( 40, 72, 78 )'

 本文の形式を整える方法よりも重要なのが、主題の行をつけるプラクティスだ。例で示したように、あなたは約50文字(これは厳しい限度ではない)を目指すべきだし、とにかく、常にその下に空行を作るべきだ。この最初の行は、そのコミットによって導入された変更への簡潔な要約でなければならない。このような厳しい文字数制限では表現できない技術的な詳細があるならば、代わりに本文の方へ書く。要約の行は Git 全体で使われ、もし長すぎるメッセージだったら端折られてしまうことがしばしばだ。以下はそういった物のうち少数の例を挙げている:
  • git log --pretty=oneline はコミットのハッシュIDと要約を含んだ簡単な履歴を表示する。
  • git rebase --interactive はそれが呼び出すエディタ内で各コミットの要約を提供する。
  • merge.summary オプションが設定されていれば、マージされる全てのコミットの要約が、マージコミットのコミットメッセージ内へ格納される。
  • git shortlog は ChangeLog 的な出力を生成し、その中で要約を使用する。
  • git format-patchgit send-email そして関連するツールは、e-mailの件名として要約を利用する。
  • git reflog によってアクセスできる reflog というローカルな履歴は、馬鹿な間違いからあなたを救ってくれる。そこでは要約の写しが使われる。
  • gitk は要約のためのカラムを持つ。
  • GitHub はそのインターフェース内の様々な場所で要約を利用する。
主題/本文という区別は重要ではないように見えるかもしれないが、それが Git の履歴を Subversion より遥かに快適にしてくれる多くの繊細な要素の一つだ。


2011年1月6日木曜日

【翻訳】アクターによる並列性、そしてRubyでGoroutine

Ilya Grigorikさんの "Concurrency with Actors, Goroutines & Ruby" を翻訳しました。
元記事はこちら: http://www.igvita.com/2010/12/02/concurrency-with-actors-goroutines-ruby/
(翻訳の公開と画像の利用は本人より許諾済みです)

翻訳の間違い等があればブログコメントやTwitter(@oshow)などで遠慮無くご指摘ください。

アクターによる並列性、
そしてRubyでGoroutine


ruby-go 並列コンピューティングの世界は複雑なものだ。私たちはハードウェアランタイム、そして半ダースもの異なるモデルとプリミティブから選択することを考えなければならない: fork / wait、スレッド、シェアードメモリ、メッセージパッシング、セマフォ、そしてトランザクションなど。ゆえに、Bruce Tate が彼の最近の本(Seven Languages in Seven Weeks)でのインタビューで Matz に、もし過去に戻れるならば Ruby にどんな機能変更を行いたいかと聞いた時、その答えに説得力があったのは驚くべきことではない: 「私はスレッドを取り除いて、アクターなどのより先進的な並列機構を追加するだろう。」

プロセス計算と先進的並列性


 Matz の言明から多くを読み取るのは簡単だが、追求すべき疑問はこうだ:より先進的な並列機構とは? 毎年何千人ものプログラマがスレッド、ミューテックス、セマフォについて教えられてから学校を卒業していく――それらは私たちがどう並列を行うかというものだ! 「先進的な並列機構」というトピックに関して私たち皆が逃している重要な講義があるのか?

答えはたぶん違って、シェアードメモリモデルの「成功」によるところが大きい。プロセス計算(Process calculi)は並列システムの振る舞いをモデリングするアプローチに関係する多くの研究のための正式名称で、多くの代替物を提供している: わずかな例をあげると、CCSCSPACP、そしてアクターモデルだ。しかしながら、そんなわずかな頭文字言葉たちしか私たちの辞書に届いていなかった。それらのほとんどのルーツは1970年代前半に遡るのだから驚きだ――まったく新しいものではないのだが、最近まで滅多に言及されなかった。

アクター、CSP、そしてπ計算


erlang-scala-go 現在 ErlangScala といった言語の最近の成功に牽引されているアクター並列モデルは、探索する価値のある「代替となる並列モデル」の良い例だ。しかし、これしかないというわけではない。
Google の Go 言語もまた関連する、しかしとても異なるモデルを持ち込んだ: トニー・ホーアのCSPπ計算のミックスだ。表面上では、上記の言語群に採用されたモデルはお互いに非常に異なったものだが、しかし全ては共通の中核原則に基づいている:


「状態を共有することによってコミュニケーションするな。
 コミュニケーションによって状態を共有するようにせよ」


少しの間、沈思してみよう。データ構造をロックによって守りそのロックを奪い合う代わりに、このモデルは明示的にプロセスからプロセスへ状態を渡すこと推奨する。これは、ある時点ではただ一つだけのプロセスがデータにアクセスできることを保証し、そして即座に並列性問題の全体を解決する。

アクター、Goroutine、Channnel と Ruby


 それで、類似性はわかったが、Erlang と Go のような言語の間の実際の違いは何なんだろう? 構文やVM実装の詳細はさておき、Erlang では 各プロセスに独自に与えられた名前を使ってコミュニケーションをとる――mailbox という考え方だ。対照的に Go では、全てのプロセスは無名であり、その代わりに "communication channel" を指定する――Unixのパイプの考え方だ。微妙な違いだが、これらが非常に異なるプログラミングモデルと能力をもたらす。

erlang-vs-go

理論的なことはわきにどけて、Go の並列モデルを注意深く見てみよう。Go runtime をインストールするかもしくは、実は Ruby ランタイム上で直接そのモデルのほとんどをエミュレートすることもできる(gem install agent)。:
c = Agent::Channel.new(name: 'incr', type: Integer)
 
go(c) do |c, i=0|
  loop { c << i+= 1 }
end
 
p c.receive # => 1
p c.receive # => 2
githubAgent (Go-like concurrency, in Ruby)
Downloads: 275 File Size: 0.0 KB

シンプルなジェネレータの例だが、多くの異なる機能をハイライトさせるものでもある。まず最初に、プロセス間でコミュニケーションを取るための名前('incr')のついた型付き channel を作成する。それから少し面白いことに "go" という、channel を一つと Ruby のコードブロックを取る関数を呼ぶ。

裏側では、"go" 関数は実際にはコードブロック(ここでは loop 命令)を実行するための新しいスレッドを作成し、元の channel で receive を呼ぶためにすぐさま復帰する。その channel は、今度は、producer が値を生成するまで receive 呼び出しをブロックする! 言い換えれば、マルチスレッドな producer-consumer を、シングルスレッドまたは mutex が見えないように書いたってことになる! また、よりおもしろいマルチワーカーの例エラトステネスのふるい、そして MRI と JRuby の間の非科学的な小競り合いの結果を見よ。

"先進的な並列性" の受け入れ


 シェアードメモリ、スレッドそしてロックにはそれらを使う場所と目的がある。実際、上で紹介した Agent の裏側か、"代替となる並列モデル" を持つランタイムのソースコードの中を見てみれば、間違いなくそれらが使われているのが見つかるだろう。だから、スレッドの存在が必要かどうかは疑問点ではなくむしろ、重要なのはランタイムに関わらず、並列性を必要とするコードを書き、テストし、管理するベストで高水準なインターフェースが実際になされているか、だ。

アクターや CSP/π計算モデルは最初は複雑に見えるが、ほとんどはそれに馴染みないせいだ。実際、一度いくつか例を経験してみれば、それらは著しくシンプルで、パワフルで、そしてどんなランタイムの中でも再現できる。Erlang を始めるか、Go を試してみるか、あるいは Ruby でアイデアをプロトタイピングするために Agent をインストールするかすれば、あなたは時間を有益に過ごせるだろう。


2011年1月2日日曜日

【翻訳】Rebaseは安全である

Gary Bernhardtさんの "Rebase Is Safe" を翻訳しました。
元記事はこちら: http://blog.extracheese.org/2010/12/rebase-is-safe.html
(翻訳の公開は本人より許諾済みです)

翻訳の間違い等があればブログコメントやTwitter(@oshow)などで遠慮無くご指摘ください。

Rebaseは安全である


 なにやら Git についての嘘がまかり通っているらしい: git rebase は安全ではない、という。push 済みの変更をあなたが rebase してしまい、皆がタチの悪いマージ大惨事に陥ってしまうという類の危険のことでは「ない」。そんなものは本当の、よく知られた危険であり、そんなことしちゃいけないってのは皆受け入れているはずだ。

私が言っている嘘というのは git rebase はそもそもあなたの履歴を不安定にするものであり、コンパイルできないまたはテストをパスしない変更を混入するから、これは深刻な問題だ、というものだ。主な症状としては git bisect が中断する。テストが壊れているリビジョンが存在する場合、慎重にやるなら bisect はそれをスキップするが、そうでないなら、本来突き止めるべきではないものを bisect が見つけてしまう(false positive)ことになる。

確かにそれは悪く聞こえる。しかし問題が、新しく rebase されたコミットがテストをパスするかわからないということならば、なぜテストを走らせないのか?

この例のように。:
(set -e;
  git rev-list --reverse origin/master..master |
    while read rev; do
      echo "Checking out: $(git log --oneline -1 $rev)";
      git checkout -q $rev;
      python runtests.py;
    done)
これは難しいことじゃない――シェルによるただの while ループだ。origin/master から master の間の全リビジョンをチェックアウトし、それぞれのリビジョンでテストを走らせる。Expector Gadget(訳注:著者の自作テストツール)の2つのリビジョンでそれを走らせたら、こう出力される:
Checking out: 4f56581 Split tests into many files
....................
-------------------------------------------------
Ran 20 tests in 0.019s

OK
Checking out: 44de2c2 pyflakes
....................
-------------------------------------------------
Ran 20 tests in 0.019s

OK
これはたった1.1秒しかかかってない。もし遅かったら、それはあなたのユニットテストが遅いからだ(Git のせいではない)。無論テストの遅さは bisect や継続的インテグレーション、開発フロー内の繰り返し作業、その他多くのものを遅くする。そこでは、rebase はボトルネックではない。

このコマンドはテストが失敗した時点で停止する――最初に set -e をしているためだ。だから、もしどれかのリビジョンがテストをパスしなかったら、あなたはそのテストの出力結果を見せられ、コマンドは停止し、そしてチェックアウトされたリビジョンがあなたの前に残される。あなたはおそらく git checkout master して、そのリビジョンを修正するために対話的リベースをしたいはずだ。私の場合、こういうことは実際には滅多に起こらない。rebase は変更なしでほとんどいつも働いているが、リポジトリ履歴を壊したくないならば、チェックはいまだ重要だ。

あなたは、チェックアウトがワーキングコピーを粉砕するか、さもなくばカオスな状況を引き起こすのではないかと心配するかもしれない。もう一度言うと set -e が我々を守ってくれる。もしワーキングコピーが汚かったら最初の git checkout が失敗し、サブシェルは終了するだろう:
Checking out: 4f56581 Split tests into many files
error: You have local changes [...]; cannot switch branches.
私はこのシェルコマンドを複数のプロジェクト、私一人のものと6人程度の小さなチームの両方で採用して大成功を収めた。これは元々 Mercurial の patch queue の中の全てのリビジョンに対してテストを走らせる、似たコマンドから来ている。patch queue は コミットを rebase する Mercurial における方法であり、Mercurial ユーザは本記事を Git 固有の問題だと思わないように。

過去に、私はコマンドをスクリプトに落としこむことさえ面倒臭がっていた。私には zsh の巨大なヒストリサイズ(100,000コマンド)があり、"rev-list" を履歴検索をするためにただ ^R を打つだけでよかった。でも今は私の dotfiles リポジトリにコマンドをスクリプト化したところなので、あなたも自身のプロジェクトで簡単にこれを使うことができる。

本記事の教訓は、あなたはツールに深く携わる必要があるということだ: Git を理解し、そしてまた Unix を理解せよ。それらをよく使うことを学び(例えば Unix では、私のスクリーンキャストの "Python to Shell to Ruby" や "A Raw View into My Unix Hackery" を見よ)、両方共の根本的なモデルを学び(例えばUnixでは、"The Tar Pipe" を見よ)、そしてそれらを一緒に使う方法を特に学ぼう。どちらかだけを学ぶとか、両方を中途半端にするとかして、問題が起こったときにそれらのツールに文句を言うのはやめよう。プログラムを書くのは難しい、だからって色んなものをとっ替えひっ替えするのはイクナイ。

(もしこの記事が楽しめたなら、"Why I Switched to Git From Mercurial" もいいかもしれない。)




フォロワー