Hatena::ブログ(Diary)

=== SANDmark 19106 === beginning stress test このページをアンテナに追加 RSSフィード

2012年11月03日

git-flowで辿る開発の道

お久しぶり過ぎました、sandmarkです。
趣味プログラマもここまで来ると芸術だなと思いつつ、
最後に(自力で)書いた記事がいつですか、半年以上前ですか。
継続は力なりって言うけれど、僕のように継続できない人間は弱っていくばかりですねー。

挨拶もそこそこに git のお話。
これもかなり前に知って衝撃を受けつつ記事にはしていなかったのですが、
git-flow というものがあるんですね。

これは git のプラグインとして働き、
git の長所であるブランチを最大限に活かしつつ、
かつ分散型の弱点である「中央(みんなから参照されるところ)にあるリポジトリのログを汚さない」
という点において、抜群の効力を発揮してくれます。

そもそも git は「多機能すぎてどういうスタイルがいいのかわからん」というのが
僕のような詳しくない人にとっては結構よくある感触だと思うんですね。
何となく dev ブランチ作って、 master にマージして、 push なり何なりする。

それが『その人のスタイル』として確立されていればいいのだけれど、
そうじゃない場合、自信が持てない上に誰かと作業するときに困る。
というわけで、フローチャートが必要なわけです。テンプレというか。

git-flow の主な流れは明確で、「ルールに従っていればそれでいい」というところがお気に入り。

  1. git flow feature start hello ("hello"という機能の実装を開始。 feature/hello ブランチが作成される)
  2. git flow feature finish hello ("hello"実装完了。 feature/hello ブランチは削除され、developブランチにマージされる)
  3. git flow release start 1.0.0 (リリース版1.0.0の準備を開始。 release/1.0.0 ブランチが作成される)
  4. git flow release finish 1.0.0 (リリースすると同時にタグの入力を求められる)
  5. git flow hotfix start 1.0.1-somefix (バグ修正も死角無し)
  6. git flow hotfix finish 1.0.1-somefix
  7. git push

なにこれちょうべんり。
これは単にブランチを作成→削除するだけではなく、
gitのFastForwardや履歴の管理までやってくれている(らしい)ので、
リポジトリが無駄に肥大化するのを防いでくれる役目もあります。

もちろん、非常に強いルールの上で動くものなので、
独自路線を行っている人には却って邪魔になるかも知れませんが。

何よりも、プラグインとして動いてくれるのが嬉しいところですね。
また、コンソールで動かすのならTAB補完は欠かせない、という人のために
no titleなんてものまで用意されています。

とても有名なプラグインなので、Google先生にお頼み申し上げれば資料がざっくざく出てくると思います。
僕はそもそも git に関して詳しくないので「便利ダナー」ということくらいしか感じられませんが、
案ずるより産むが易し、実際に手を動かして使ってみれば、それだけで感覚が掴めると思います。

git-flow公式にはCygwin用なども用意されているので
今更感が物凄いですが、資料や派生版も豊富なので、どうでしょう、騙されたと思って使ってみては。

(github-flowというのもあるらしいので、良さそうなら近々試してみるつもりでいます。)

GitHubにpush,pullするときのパスワード認証が鬱陶しいのでzshで何とかする

皆さんお馴染み no title ですが、
パスワード付きの鍵を作ってしまうと、 push, pull のたびに認証を要求されてしまいます。

GitHub曰く「別にパスワード付けても凄くセキュアになるわけじゃないよ」だそうですが、
同時に「でもパスワード付ければちょっとはセキュアになるよ」とも言っています。
とても親切です。

でも認証が面倒くさいじゃん!!

という人が僕以外にも多数いたようで、公式のヘルプページスクリプトが載ってました。
以下抜粋:

SSH_ENV="$HOME/.ssh/environment"

# start the ssh-agent
function start_agent {
    echo "Initializing new SSH agent..."
    # spawn ssh-agent
    ssh-agent | sed 's/^echo/#echo/' > "$SSH_ENV"
    echo succeeded
    chmod 600 "$SSH_ENV"
    . "$SSH_ENV" > /dev/null
    ssh-add
}

# test for identities
function test_identities {
    # test whether standard identities have been added to the agent already
    ssh-add -l | grep "The agent has no identities" > /dev/null
    if [ $? -eq 0 ]; then
        ssh-add
        # $SSH_AUTH_SOCK broken so we start a new proper agent
        if [ $? -eq 2 ];then
            start_agent
        fi
    fi
}

# check for running ssh-agent with proper $SSH_AGENT_PID
if [ -n "$SSH_AGENT_PID" ]; then
    ps -ef | grep "$SSH_AGENT_PID" | grep ssh-agent > /dev/null
    if [ $? -eq 0 ]; then
  test_identities
    fi
# if $SSH_AGENT_PID is not properly set, we might be able to load one from
# $SSH_ENV
else
    if [ -f "$SSH_ENV" ]; then
  . "$SSH_ENV" > /dev/null
    fi
    ps -ef | grep "$SSH_AGENT_PID" | grep ssh-agent > /dev/null
    if [ $? -eq 0 ]; then
        test_identities
    else
        start_agent
    fi
fi

どうやらフォーラムに投稿されたものらしいです。
で、これを .bashrc なり .profile なりに書けば自動的に ssh-agent が立ち上がるぞと。
試してみたら愛用している zsh でも動きました。

しかし問題がありまして、既に立ち上がってるssh-agentがあるとコケるんですね。
端末を閉じる前に毎度毎度

$ ps aux | grep ssh-agent
$ kill $SSH_AGENT_PID
$ kill $SSH_AGENT_PID
$ kill ...

なんてやってたらパスワード認証よりも面倒くさい。
私は不精ですから(キリッ

というわけで zsh のコールバックを利用して、
「zshが終了するときに自動的にssh-agentを終了させる」
が実装できないかどうか調べてみたら、あっさり解決したのでメモメモ。

具体的には .zshrc の末尾(でもどこでもいいけど)に

TRAPEXIT() {
    ssh-agent -k
}

と書くだけでした。

Signalについては詳しくないので TRAPINT のほうが確実かも知れませんが、
とりあえずこれで動いてくれているのでとりあえず良し。

でもこれ、端末を複数立ち上げるとまた問題になりそうですね…。
screenを使う手もあるんですが、窓が沢山無いと落ち着かない私。
どうしたものかしら…。

2012年03月11日

herokuでRails3.2.1が動いたよ

というわけで

これらの記事のまとめというか、最終回になりますが、
何となく動きそうなので最後の報告です。

ただherokuにpushするときにPermission Deniedと言われたので*1
新たな公開鍵を登録してからになります。

$ heroku login
$ heroku keys:add ~/.ssh/id_rsa.pub

さて次に、気になるデータベースの使い方。
herokuではPostgreSQLですが、他にもMySQLを使ったり、
Add-onとしてAmazon RDS(クラウドでのリレーショナルデータベースサービス) | AWSを使ったりもできます。
それについてはno titleを参照してもらうとして、
今回はデフォルトのPostgreSQLのまま使っていきます。

といっても複雑なアプリケーションではなくて、とりあえず動く、というレベル。
要はscaffoldして、heroku側で動けばいいわけです。

$ rails g scaffold Person name:string age:integer
$ rake db:migrate
$ git commit -a -m "scaffolded Person"
$ git push heroku

しかしここで http://アプリケーション名.herokuapp.com/people にアクセスしても
heroku側でデータベーステーブルを作成していないのでエラーが出てしまいます。

$ heroku run rake db:migrate

とすると、heroku側で rake db:migrate が動き、テーブルが作成されます。
実際にアクセスしてみると問題なくデータの読み書きができるので、
「これなら行けそう」というわけで、なんとも適当ですが、おしまいです。

開発するのは今からなのでのんびりやっていきますが、
何か問題が出たらここに書いていこうかなと。

*1Ubuntu@VMwareから開発するようになったのでそのせい。

2012年03月05日

ブランチのマージと削除

さて、開発中のライブラリでは、不必要になったクラスの完全削除が完了しました。
テストも通して、実際に使ってみて、問題なしと判断。
というわけで、masterブランチにマージしてみようと思います。

といっても実は簡単で、およそ3行のコマンドで事が終わります。*1
僕はgit初心者丸出しちゃんなので、ローカルブランチでのコミットは
すべて終えた状態でのマージになります。
コミットせずにマージしなきゃいけないケースも出てくるだろうけど、
コンフリクトとかいろいろ考えると、趣味の範囲でそこまで試す度胸はないんです(キリッ

まずはブランチのマージ。

$ git checkout master
$ git branch
* master
  box-deletion
$ git merge box-deletion
Updating 4075c86..98d9fe5
Fast-forward
 lib/box.rb            |  177 -------------
 lib/cell.rb           |   40 +---
 lib/npsolver.rb       |  102 +++++---
 spec/box_spec.rb      |  261 -------------------
 spec/cell_spec.rb     |   16 +-
 spec/npsolver_spec.rb |  686 ++++++++++++++++++++++++++++---------------------
 6 files changed, 453 insertions(+), 829 deletions(-)
 delete mode 100755 lib/box.rb
 delete mode 100755 spec/box_spec.rb

lib/box.rb と spec/box_spec.rb が不必要になったクラスとスペックファイルなので、
綺麗に削除されていることがわかります。
ls コマンドで確かめてみると、確かに影も形もない。
どうやら無事マージされたようです。あーよかった。

ここで出力の2行目に Fast-forward という文字列がありますが、
リポジトリがポインタを進めた証拠」という今の僕には理解出来ない説明が
ぐぐったらヒットしたので、誰か親切な人、教えてください。

さらにこの時点で稼働させっぱなしにしていた autotest がテストを開始して
失敗も無かったので、マージをするという点に関してまったく労せず完了したことになります。

続いて、 box-deletion ブランチではもう作業することはないので、削除します。
このブランチをこの世から消し去るためには、

$ git branch
* master
  box-deletion
$ git branch -d box-deletion
Deleted branch box-deletion (was 98d9fe5).
$ git branch
* master
$ git push origin

と、branchコマンドに -d オプションを付けてやります。
ありがとうローカルブランチ、そしてさようなら。

しかしこの状態でgithubにpushしても、ローカルブランチは削除されていません。
リモートにあるリポジトリからローカルブランチを削除するためには

$ git push origin :box-deletion
To git@github.com:sandmark/libnpsolver.git
 - [deleted]         box-deletion

のように、 :(コロン)を頭に付けてやる必要があるようです。
pushがローカルリポジトリの状態をリモートリポジトリに
完全に反映するわけではない、ということなんでしょうね。
わざと手間をかけさせて「本当に消していいの?」と聞かれている気がします。

なぜかpendingのテストが増えていますが、少なくとも一歩前進しました。
あとはRSpecの中身を整頓して、新たな機能を実装していくだけです。*2

*1:が、今回はわかりやすくするために git branch などでいちいち状態を確認してます。

*2:Enumerable? あ、やります。でももうちょっと待ってね。

2012年03月04日

既に修正を加えてしまった状態でブランチを作る

いま製作中のライブラリ構築練習台であるナンプレ解決器は、
もともと「人間の解き方」を実装すべくクラスを構築していたので
確定探索と背理法のみを使うとなると、却って邪魔になるクラスがあるんですね。
それを思い切って削除してしまおうと。使わないだろうし、何よりも気持ち悪い。

ただそれで動かなくなって頓挫したら笑い話にもならないので、
こういうときの定石としてブランチを作成してみました。

git ブランチ」みたいなワードでGoogle検索すると
もちろんたくさんヒットするんですが、
僕の見つけた範囲では、いずれも「編集する前にブランチを作る」が前提でした。

そして僕はやらかしたんですね。
不必要なライブラリファイルとspecファイルを削除してしまい、
しかもある程度他のライブラリを修正を加えてしまい、
その時点で初めて「あれ、ブランチ作ったほうがよくね……?」と思いました。

今更masterのheadをcheckoutして修正し直すのもしんどいし、
かといって、既に修正を加えた状態でブランチを作成したらどうなるのか
バージョン管理システムを使っている割には理解度も高くないし。
考えていても仕方が無いので特攻しました。

$ cd my_app
$ rm somefile
$ git branch something-deletion
$ git checkout something-deletion
$ ls

あれ……なんか良きにはからってくれました。
削除したファイルは削除されているし、
修正を加えたファイルにも変更はなく、
もちろんmasterブランチにも影響無し。

gitは初心者にもやさしい!

あとはある程度の段階まで修正、コミットを繰り返し、githubにpushしてみます。

$ git push origin something-deletion

ここでブランチの名前を省略したらどうなるのか、ガクブルが止まりません。
もしかしたら先ほどのように「良きにはからってくれる」のかも知れないけど、
初心者の僕には確証が持てないので昼も眠れない毎日です。

ともあれ、githubにブランチをpushできました。
あとはこの要領で好き勝手に変更していくだけですね。

2012年03月03日

Gitコマンドのエイリアス

かつてsvnを使っていた身としては

$ git checkout

とかでさえ長く感じる。
ので、エイリアスしようと思います。

git config --global alias.co checkout
git config --global alias.st 'status'
git config --global alias.ci 'commit -a'
git config --global alias.di 'diff'
git config --global alias.br 'branch'

git/コマンドの省略(alias)設定をする方法 - TOBY SOFT wiki

これで

$ git st
$ git co master

とかできちゃうわけですね。