Category Archives: Git

先週の社内勉強会にてGitの便利なコマンドや関連するGUI/CUIツールについて発表しました。

スライドにリンクなどはまとまっています。

git bisectについては言葉だと分かりにくいので、Test’emを使いながらデモをしました。
適当に実装を進めてgit bisect run “testem ci” で壊れたコミットを探すという感じのと、git hookでtestem ciを動かしてテストが通らないとコミット出来ないようにする等。

発表したは結構前ですが、資料を置いておきます。

内容的には大きく分けて

という感じになっています。

結構曖昧な部分もありますが、結構参考リンクを詰め込んだので、そちらを見ていただくと面白いのではないかと思います。

以前書いた、TiDDとgit-flowを合わせた開発手法について | Technology-GymのRedmineとgit-flowを使ったチケットドリブンな開発手法は相変わらず続けていますが、少し使ってるツールが変わりました。

まずはgit-flow自体はそのまま使い続けています。
後述しますが、git-flowのhooksが正式に実装されれば、TiDDな開発はもっとスムーズに進むような気がします。

コマンドラインからredmineを操作するツールを以前は複数使っていましたが、
現在はgit-issueに統一してあります。

この記事で使用してるバージョンはgit-issue 0.8.0です

git-issueはチケットの作成(git issue add)、gitチケットのアップデート(git issue update <ticket_number>)やチケット一覧の表示(git issue list)等、
一通りredmineのチケット操作はできるので便利です。

自分の場合、上記のあげたチケットの作成、アップデート、一覧表示があれば大体事足りてしまうので、そこに絞って使い方を書いてみます。

まずは、git-issue+Redmineのセットアップ方法について。
Configurationに書いてあるように

$ git config issue.apikey xxx
# 自分は他の用途で使ってないので、$ git config -g で定義してます。
$ git config issue.type redmine
$ git config issue.url http://redmine.example.com/projects/IDENTIFIER/
# issue.urlの末尾は/を含める必要があります

この状態で、git issue listなどを実行してエラーが出なければセットアップは終了です。

チケットの作成

git-issueではコマンドラインからチケットの作成も行えます。
自分の場合チケットの追加だけはWebから行う事も多いですが、かなり小さなチケットを立てるようなときはgit issue addを使ったりします。

単純にgit issue addと入力すると訳わからん状態になるので、自分はzshにチケット作成関数を書いて置いて、
Subjectとdescriptionをインタラクティブに入力するだけで済むようにしています。

NewImage

git issue addはassigned_to_idとproject_idを指定しないとそもそも作成時にエラーになるので、
関数と言ってもgit issue add –assigned_to_id=xx –project_id=yy を自動で入れるような感じものです。

function giAddIssue(){
  # redmineの自分のUserIDを入れる
  MY_REDMINE_ID=XXX
  ISSUE_URL=$(git config issue.url)
  PROJECT_ID=$(echo "$ISSUE_URL" | sed -e "s/^.*\/\(.*\)\/$/\1/")
  git issue add --assigned_to_id=$MY_REDMINE_ID --project_id=$PROJECT_ID
}

MY_REDMINE_ID(–assigned_to_idに渡す)部分は人によって違うので、書き換えるかgit-issueと同じようにgit configに設定値を持たせて読み込むようにすると良い気がします。
project_idはredmineのプロジェクト識別子でもいいみたいなので、issue.urlで設定した値を再利用して設定を増やさなくても済むようにしてます。

何かもっとまともな方法がありそうですが、これで$giAddIssueとやるとチケットの作成が簡単にできます。

NewImage

チケットのアップデート

これが一番よく使うもので、git issue update <チケット番号> でそのチケットを開いてエディタで編集できます。
また、id/<チケット番号> が含まれるgitブランチにいる場合なら、チケット番号を省略できてgit issue updateだけでよくなります。
自分はgit-flowでブランチを作成してるので、git flow feature start id/<チケット番号> という感じでfeature/id/<チケット番号>というブランチを作って作業します。
(git issueにもbranchを作る機能などがありますが、使い方がよくわからないので使ってない)

この省略が結構便利で、ブランチで作業が終わってチケットを終了だけ(コメントなどを付けないで)したいときは
git isssue update –status=5とやるだけでチケットを終了できます。

チケット一覧の表示(git issue list)はそのままなのですが、終了したチケットの表示とかgit log –pretty=format:みたいのができると便利そう。

まとめ

大まかにやってることをまとめてみると

$ giAddIssue
# もしくはWebでチケットを作成
$ git issue list
# チケット番号を確認 xxxとする
$ git flow feature start id/xxx
$ git issue update --status=2
# ステータスを作業中にする(あんまりやらないけど)
…
開発&gitにコミット
…
$ git isssue update --status=5
# もしくはgit isssue updateでnoteを書く
$ git flow feature finish id/xxx
# ブランチをマージ
# 最初に戻る

のような感じです。

おまけ

git-flowのhooksとgit isssueの連携について。
まだ、不完全でちょっと使えてないのですが、

$ git clone --recursive https://github.com/petervanderdoes/gitflow.git
$ cd gitflow
$ git checkout origin/feature/implement-hooks
$ make install

という感じで、gitflowにhooksを実装したものをインストールして、先ほどの流れででてきたgit issue update –status=の部分を自動化できないかなとやっていました。

*このスクリプトは不完全なので使わないほうが良い気がします。

git-flow hooksはgitのhooksと同じで、各レポジトリの.git/hooksに入れておけばgit-flowに対応したコマンドにhookしてシェルスクリプトを動作させることができます。
上記のスクリプトは、git flow feature start/finish の後にhookするスクリプト(ファイル名で判断される)です。

git  hookを自動で.git/hooksに移動させる方法がよくわからなかったので、

# git hooks install
function gitHooksInstall(){
  MY_HOOK_DIR="~/.git_flow/hooks"
  DOT_GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
  if [ "$DOT_GIT_DIR" != "" ]; then
    echo "cp -upR $MY_HOOK_DIR $DOT_GIT_DIR"
    cp -pR $MY_HOOK_DIR $DOT_GIT_DIR
  fi
}

自動で入れたりhookスクリプトを~/.git_flow/hooks/ディレクトリにまとめておいて、gitHooksInstallを実行するとコピーするようなものをかいてました。
これで、git flow feature start/finish id/xx をすると自動で、ステータスを進行中/終了にできて、 git isssue update –status=5みたいのを手動で実行しなくて済むと思ったのですが、
上記のスクリプトが何かおかしいのか原因がよくわかってませんが、git isssue updateの挙動がおかしくなって上手く出来ませんでした。

多分、上記のスクリプトがおかしいのだと思いますが解決できませんでしたが、手動でやってもgit-issueはとても便利なのでredmineとgitをあわせて使う人は触ってみると良い気がします。

git flow feature start/finish

Redmineを使ったTiDD(チケット駆動開発)と バージョン管理システムのGitを組み合わせて、どうやって開発していくのが上手い流れを作れるのかということを考えてみました。

まずはTiDDとは何か

気になるところを取り出すと

  • コードに触る前にチケットを切る
    • Ticket First
  • タスクチケットは細分化して、放置されるようなタスクのサイズにしない
    • チケットで親子関係を作ってまとめるといい
    • 親チケット = ストーリーカード
    • 子チケット = タスクカード
  • コードとチケットを関係付ける(コミットコメントにチケット番号の付加など)
    • No Ticket, No Commit

katsumic.info – WorkNote » TiDD(チケット駆動開発)でいこう と大体同じです。

次はGitとチケットについて

元々、RedmineのチケットとGitをどう連携させるのがいいのだろう? というところからTiDDを知ったため、
チケットとコミットをどう関係付けるかと言う所に焦点がありました。

そこで、調べた所RedmineとGitを連携させるスクリプトなどはいくつかあって

などがあって、この辺のものを実際に試していてどうやるのがいいのかと大まかな流れを考えると以下のようになった。
(コミットの所にテストやレビューなどが入ると思いますが)

チケットワークフローA

(id/チケット番号 という用にid/と付けるのは、そうしないと認識しない拡張コマンドがあるため)

  1. チケット番号でGitのブランチを切る
    $ git branch id/TICKET_ID
  2. ブランチ内でチケットのタスク(コミット)をする
    Git-Redmineを使えば、Redmine上のステータスもcommitと一緒に変更できる
    $ git redmine commit TICKET_ID
  3. タスクが完了したら、メインのブランチ(ここではmasterとする)にマージする
    $ git checkout master && git merge –no-ff id/TICKET_ID && git branch -D id/TICKET_ID

細かい単位(チケット)でブランチを切って、コミットして、
終わったらmasterにマージするという流れはA successful Git branching modelとよく似ていることがわかると思います。

A successful Git branching modelがどういうものかは以下の記事がとても良くできているので、説明は省きます。

簡単に説明するならば

  • 常にリリース可能なブランチを持っておく(master)
  • 代わりに開発の主体になるブランチを持つ(devlop)
  • 機能開発やホットフィックス(チケットがまさにそれっぽい)などは、それぞれブランチを切って開発する
  • ブランチのマージは–no-ffフラグを使い、どのブランチで開発してたのかを履歴に残す

ものすごくブランチを切りまくるワークフローなわけですが、GitはSVNとは違い、
ブランチを作成するときにコピーではなくラベルを付けるだけなので、ブランチの作成やマージが高速です。
この辺の話についてはモデルから知るGitを読むと各コマンドの動きがわかりやすいです。

そのため、先ほどのワークフローとGitは相性がよいのと、A successful Git branching modelを補助するためのgit-flowという拡張コマンドが存在するためこの流れを取り入れやすいです。

git-flowはHomebrewなどで簡単にインストールすることができます

$ brew install git-flow

インストールするとgit flowというコマンドが使えるようになりますが、補完がないとちょっと面倒なのでgit-flow-completionを使えば、bash, zshでコマンドの補完ができるようになります。
oh-my-zshの場合は元からgit-flow-completionプラグインが含まれているので、

plugins=(git brew gem git-flow)

という感じで、git-flow-completionをインストールしなくてもプラグイン指定するだけで動作します。(git flowコマンド自体は必要)

git-flowの使い方やコマンドの意味はGetting Started – Git-Flow « Some thoughts, ideas and fun!!!がとてもわかりやすいですが、
開発するときにstartして、開発し終わったらfinishするという感じで、動作自体はそこまで複雑ではないと思います。

実際に先ほどのチケットワークフローAにgit-flowを適応してみる。
(途中からgit-flowを導入しています。またgit:(master)の括弧内が今いるブランチを示しています。)

という感じで、git-flowを適応できました。

最初はnode.jsでこのワークフローを作るようなCLIツールを書こうとしていましたが、既存のツールを組み合わせて十分使える感じになりました。

あくまで、TiDDとGitでの開発を組み合わせた一つの例ですが、これからも模索していく必要がありそうです。

こんにちは。甘いお菓子が大好きなイッシーです(´〜`)mgmg。世は既にバニラアイスの季節ですね!

今回はバニラアイスとは関係がありませんが、Gitでのバージョン管理をほんの少しだけ掘り下げてブランチを使ってみることにします。ブランチとはmasterから派生し枝分かれした部分です。木の枝と違うのは枝分かれした部分が幹に融合する事があることでしょうか。ブランチを使えばビジネス的な承認が得られていないバージョンをそのままにしておき、次のバージョンに向けた作業を始めることが簡単にできます。効率化万歳\(^o^)/

では早速、以下のようにしてhogeという名前のブランチを作ります。

[cc lang="bash"]
git branch hoge
[/cc]

コレでおしまいです。簡単ですね。以下のコマンドで作ったブランチを確認しましょう。

[cc lang="bash"]
git branch hoge
[/cc]

以下のように表示されます。

[cc lang="bash"]
* master
hoge
[/cc]

アスタリスクがついているものが現在選択されているブランチです。新しく作ったブランチに変更を加えるには、ブランチを切り替える必要があります。

[cc lang="bash"]
git checkout hoge
git branch
[/cc]

以下のように表示されると思います。

[cc lang="bash"]
master
* hoge
[/cc]

以後の作業は全てhogeブランチに反映されるとこになり、何もしなければmasterに変更を及ぼすことはありません。checkoutをすることによってmasterと並行して作業をすすめることができます。

■マージ

枝分かれした方の変更点をmasterブランチに反映させたい時があります。そんな時に使うのがマージです。

説明のための作業

以下のコマンドでmasterブランチに切り替えたあと、ファイルを追加しコミットします。

[cc lang="bash"]
git checkout master
touch public_html/gomi.html
git add .
git commit -a -m “add trash file for the test”
[master 94cf4d1] add trash file for the test
1 files changed, 35 insertions(+), 0 deletions(-)
create mode 100644 public_html/trash.html
[/cc]

以下のコマンドでhogeブランチに切り替えたあと、ファイルを追加しコミットします。

[cc lang="bash"]
git checkout hoge
touch public_html/gomi.html
git add .
git commit -a -m “add gomi file for the test”
[hoge b6e5b56] add gomi file for the test
1 files changed, 35 insertions(+), 0 deletions(-)
create mode 100644 public_html/gomi.html
[/cc]

お待たせしました。マージです。以下のコマンドでhogeブランチで行った変更をmasterにマージします。

[cc lang="bash"]
git checkout master
git merge hoge
Merge made by recursive.
public_html/gomi.html | 35 +++++++++++++++++++++++++++++++++++
1 files changed, 35 insertions(+), 0 deletions(-)
create mode 100644 public_html/gomi.html
[/cc]

圧縮コミット

バグフィックスなどの際にブランチを作りまとめてコミットしたい場合、変更履歴をまとめて1つにしコミットしたいですよね。そんな時は以下のようにマージします。

[cc lang="bash"]
git checkout master
git merge –squash hoge
[/cc]

チェリーピック

別ブランチの特定の1コミットをマージしたい場合は以下のようにします。

[cc lang="bash"]
git checkout master
git cherry-pick b6e5b56
[/cc]

別ブランチで作業をしてくれている人がバグを潰してくれた場合もコミット名が分かれば簡単にマージできます。

■タグ

目印のようなものでリリースなどの際にはタグをつけておいた方が分かりやすいと思います。

[cc lang="bash"]
git tag 1.0 hoge
[/cc]

いかがでしょうか?ブランチを作っておけば良かったかもとか思う今日この頃です。ちなみにですが以下のコマンドで特定のコミットを元にブランチを作ることができます。

[cc lang="bash"]
git branch hoge b6e5b56
[/cc]

とまぁできるのですが、その時にやるのがやっぱり一番なのかなと・・・そんなこんなでバージョン管理は慣れが凄く大切だと思います。(。・ω・)ノ゙