個人開発環境にGithub Flowを適用する

Github、joinしたのは2013年で作ったものは軒並みちゃんと突っ込んではいるんだけど、単に一区切りついたらadd => commit => pushしているだけでちゃんと使っていなかったので、個人開発ではあるがGithub Flowを取り入れてみた。

What is Github flow ?

Githubを用いた開発作業を進めるにあたっての指針みたいなものです。基本的にはmasterブランチ上では作業せず、作業工程ごとにブランチ作って、終わったらプルリクしてmasterにマージしてもらうことでデプロイとしましょうね、というものだと理解している。至ってシンプルではあるけど、これを取り入れるだけで従来やっちゃってた「masterで作業してるのでデプロイしても動かないレポジトリがGithub上にある」みたいな状態が防げて良さそうだと思った。

ちなみにGit-flowというのもあるようだけど、こちらは全然別個のツールらしく理解していない。Git-flowの問題解決としてGithub Flowが提唱されたようだが、そもそも開発工程の制御のためだけにツールを追加したくはないなと思ったのでGithub Flowを採用した。

Github Flowの理解にはこの文章が良さそう。なお、dotfilesのような大した更新のないレポジトリにはさすがに適用していない。

GitHub Flow (Japanese translation)

実際の開発工程

あくまでGithub Flowに沿う形という程度なので、そのままそっくり適用できてはないとは思うが。

開発開始

ブランチを切る。ブランチ名は機能追加等の開発要件であればdev_hoge、バグフィックスであればhotfix_hogeとする。

1$ git checkout -b dev_hoge

開発中

普通であればレビューを依頼するタイミングなど、開発の切りがついたところでpushしていくのだろうが、分散して開発しているわけではないので、1日の開発が終わる段階でpushしている。そもそも開発に使っている環境が複数あるので、Github上のdevelopブランチも常に最新化していつどこでもfetch可能にしたいなという思いがある。従来はDropboxで各環境間の同期を取っていたが、プラグインの有無やbundleなどで度々不具合もあったので改めた。

1$ git add -A
2$ git commit -m "
3...
4$ git push origin dev_hoge

git add .ではなく-Aなのは、そちらじゃないとgit rmしたファイル等が含まれないとこちらの記事に書いてあったゆえ。

開発終了

開発が終わり、masterへのマージを必要とする段階に来たらプルリクを出す。プルリクって別のコミッターからしか不可なのかと思っていたが、自分のレポジトリに自分で出すことも可能だったのでそうしている。本来であればテストツール等走らせるべきではあるのだろうが、今のところはプルリクに対して特にレビュー等なく(自分のコードだし)そのままマージしている。

後述するがバグや開発課題の管理にはGithub issueを用いているので、マージの際はissueのナンバーをコメントに入れている。これでGithub上のリンクとして働いてくれるので便利。

スクリーンショット 2015-10-04 14.19.25

参考:Gitコミットメッセージの7大原則 - rochefort's blog

マージ後

作業ブランチを消して、ローカルのmasterを最新化する。

マージにはgit mergeを使用し、git rebaseは使わないことにしている。そもそもrebase完全に理解してないというのもあるが、要するに歴史改変にあたるような操作があまり好めないというのが強い。個人の開発においては作業ブランチの変更中にmasterに更新が入ることは少ないので、このやり方でおそらく不都合はしないと思っている。

1$ git checkout master
2$ git branch -a
3$ git branch -d dev_hoge
4$ git push --delete origin dev_hoge
5$ git fetch
6$ git marge origin/master

参考 GitのRebaseによるBranchの運用 | Developers.IO git pull と git pull –rebase の違いって?図を交えて説明します! | KRAY Inc

コンフリクトした場合

git ls-files -uでコンフリクトしたファイルが一覧化されるとのことなので、確認の上で開いて直す。もしローカルかリモートのいずれかを全面採用するのであれば、git checkout--ours--theirsオプションを使う。

git ls-files -u
git checkout --ours hoge
git checkout --theris hoge

参考:Gitでコンフリクトした時のための備忘録 - アジャイルSEを目指すブログ

リモートのmasterがローカルより先に行っている場合

ローカル環境が複数あるので、このような場合は多々ありえる。そういうときは基本的にはmergeすればいいだけではあるが。masterはリモートレポジトリの最新化が原則となるので、コンフリクトした場合は99%リモートを優先させる。

git show-branch --all --color
git fetch origin
git diff origin/master
git merge origin/master

参考:gitのリモートリポジトリの更新を確認する - Qiita

バグ、開発課題の発生

先に少し触れたが、開発すべきTODOはすべてGithub issueで管理することにした。今までどうしていたかというと特に管理はしておらず、思いつくままに開発してしまっていたのだが、これでGithubに開発に必要なものはすべて集約できるのではないかと思う。個人でのGithub issue運営には下記の記事を参考にさせてもらっているが、特に難しいことはせず、タスク管理ツールのような形で使っている。

参考:一人で使えるGithub Issue

覚えられない

Github Flowは便利なのだが、Gitのコマンド体系がどうにも覚えづらくて仕方がない。どうにもならんのでaliasを駆使してなるべく覚える内容を少なくしようと努めているが、あとは慣れるしかないのかなぁと。Githubのコマンドは本当に多い。体系自体を学ぶのであればPro Gitがわかりやすく、epubの配布もあるのでKindleでいつでも読めて最高なのだが、数多あるコマンドを網羅しようとか思うとこれだけではつらい。Qiitaでまとめ記事が上がるたびに覗いてみて、今の自分のキャパで使えそうなのをつまみ食いしていく形で覚えればいいのかなと思っている。

今のalias設定はこんなの。

[alias]
  a  = add
  aa = add --all
  br = branch
  bra = branch -a
  brd = branch -d
  co = checkout
  cob = checkout -b
  coo = checkout --ours
  cot = checkout --theirs
  cl = clone
  clr = clone --recursive
  cm = commit
  cmm = commit -m
  d  = diff
  f  = fetch
  lg = log
  lga = log --graph --decorate --online
  lgp = log -p
  mg = merge
  mgn = merge --no-ff
  ps = push
  psd = push --delete origin
  pso = push origin
  psm = push origin master
  pl = pull
  s  = status -s
  sb = status -s --branch
  ss = status
  sh = show
  sba = show-branch --all

今後

やりたいこととしてはCI。Circle CIとかと連動させて自動テストしたりというところまで組み込めたら、個人開発としてだいぶ理想的な状態かなと思う。そのままデプロイまで自動化できれば最高か。またGitの理解がやはりどうにも覚束ない部分があり、まだまだ使いこなせているとは言いがたいので、aliasをカンペ代わりに育てつつ、ガンガン覚えていきたい。特にミスったときのreset系コマンドがあまりに多くてなぁ……。

その他参考記事