自分流ローカルでのgitの使い方


2014年 06月 06日

他人の開発画面、覗いてみた事ありますか。

覗いてみた事が無い方は、是非見せてもらってください。意外と面白いですよ。
gitのコミットの仕方ひとつとっても、人によって全く違うんだなと思うはずです。

git使いが10人いれば、使い方も10通りなんだなと、他人のコンソール覗きこむたびに感じます。

私の場合、プロジェクトが数ヶ月から半年に一度変わる(または並行して複数のプロジェクトに入る)という事が多く、いろんなgit使いの方に触れる 機会が多いです。

コンソール上でgitを操作する人、SourceTreeやEclipseプラグイン等のGUIツールで操作する人、git rebaseを多様する人、全くしない人、コミットグラフが綺麗な人、汚い人(そもそもあんまりこだわりを持っていない人?)、コミットメッセージを日本語で書く人、英語で書く人。。。

私は、「git pull」というコマンドを使う事はほぼ無いのですが、たぶんそういう情報は私の開発画面じーっと覗き込んでないと知りえない事だと思います。
gitを長い間使っている方は、自分流のgitの使い方を持っているかと思います。

今回は私のローカルでのgitの使い方を晒してみます。

ちょっと記事が長くなってしまいました。以下、今回の要点を最初に書いておきます。

  • コマンドは短く
  • 必要な情報は常に表示する
  • とにかくcommit
  • コミットコメントは一行で、かつ自分が分かりやすいコメントを
  • hookを活用する
  • 余計なものは無視する、または消す

コマンドは短く

私は一日の大半を黒い画面(ターミナル)の前で過ごします。

一日の始まりはターミナルを立ち上げ、開発用マシンにmoshでログイン。その後、tmuxinatorを使ってrails, guard, vim等を立ち上げます(または昨日使っていたtmux sessionが残っていたら、そこにattach)。

後は大体ターミナルと格闘してます(時期によってはずっとexcel開いてるって事もありますが。。。)

開発中は「git」というコマンドを日に数十 – 数百と入力することになりますが、この「git」3文字打つのが辛い。

毎日入力するコマンドですからね。もっと短くしたいものです。
ということで、.zshrc に以下のエイリアスを追加しましょう。

alias g='git'

これで 「g」 で 「git」になり、2文字入力する手間が省けました。

余談ですが、以下のaliasも定義してます。
(zはz.sh のことです。参考までに。)

alias h='hg'  # mercurial の 「hg」2文字が辛い
alias c=z     #「z」でも「j」ではなく「c」なのは、Dvorak配列だとcが打ちやすい位置にあるため

git 内部のコマンドもaliasを設定しておきましょう。

「git status -s」なんて長くて入力していられません。「g s」でstatus表示しましょう。
ということで、私が設定しているaliasは以下の通りです。
(この設定を.gitconfig等に書いておきます)

[alias]
co = checkout
cob = checkout -b
ci = commit
b = branch
s = status -s
d = diff
g = log --graph --date=short --decorate=short --pretty=format:'%Cgreen%h %Creset%cd 
%Cblue%cn %Cred%d %Creset%s'
rb = rebase
mg = merge
mgm = merge origin/master
mgum = merge upstream/master
dc = diff --cached
i = issue
rbm = rebase upstream/master
rbdev = rebase upstream/develop
pop = stash pop
ls = stash list
tp = commit -a -m '@@ignore add'

# ここから下はプロジェクトによって変えてるので参考程度に
flow-clean-branch = !git branch --merged upstream/develop | grep xxx | xargs -n1 -t git branch -d
flow-clean-master = !git branch --merged upstream/master | grep xxxx | xargs -n1 -t git branch -d

これで以下のようにコマンド入力が短縮されます。

git01-49e8c9fe-6b23-224b-fd5f-cbeacb2cbbe6.png

必要な情報は常に表示する

以下情報は常にターミナル上に表示しています。

  • branch名
  • stash数
git02-d688eba8-975b-3347-e2ad-7af4f3d3a909.png

開発中は頻繁にbranchを切り替えたり、stashに色々コミット積んだりする事が多いです。
そんなとき、いちいち今いるブランチを「g b」(git branch)で確認したり、stashの数を「g ls」(git stash list)なんかで確認してたら面倒です。
こういった情報は常にターミナル上に表示しておくと、作業が捗ります。

表示の仕方? それはいろんな方が記事を書いてくれているので、そちらをご参照ください。例えば、こことか。

とにかくcommit

EclipseやIntelliJのローカルヒストリーという機能をご存知でしょうか。
下図のようなやつです。

git03-34f57eed-b10d-bf2f-8c9c-ffcd1df4b886.png

gitとかそういうバージョン管理を使っていなくても、IDE自身が変更履歴を持っています。
保存のたびに変更内容を記録してます。

これ、結構便利なんですよね。

昔Javaでプログラム書いてた頃の私は、gitなんか知らなくて、SVNもちゃんと活用していませんでした(思いついたときにcommitするスタイルだった)。そんな時代、「しまった、前の状態に戻したい!」 って思ったときに、このローカルヒストリーに救われたものです。

git + vimでプログラムを書いてる今、このローカルヒストリー機能欲しいなーって思うことがあります。

プログラムがうまくかけなくて試行錯誤しているとき、ああでもない、こうでもないってプログラムぐにゃぐにゃいじり回すことありますよね。
で、「ああやっぱりさっきの状態に戻したい、なんでもいいからコミットしておけば良かった」って思うことないですか? git初心者だった頃の私はよく思いました。

そんなあなたにオススメのコマンドは、「g tp」です。これは、以下のコマンドのaliasとして設定しています。

tp = commit -a -m '@@ignore add'
# tpはtempのつもり。git commit -a -m 'add' と同じです。
# @@ignoreについては、hookを活用する、の自作prepare-commit-msgスクリプトで使ってます

なんてことはない、git commitです。でも悩んでるときにはとりあえず「g tp」を入力する癖を付けてます。
(もう最近vimで保存したときに「g tp」走るようにしとこうかな。。。なんて思い始めてます。)

「g tp」繰り返してると、下図のようにグラフが残念なことになってきますが、そんなのPull Request出す前にcommitをrebaseして整理しなおせばいいんです。

git04-b26ddb31-5a17-c4d5-5899-6955b4bfd5e6.png

悩んでる時、なんでもいいからコミットしましょう。ローカルヒストリーのようにgitを活用しましょう!

rebaseでコミット整理の仕方が分からない? それはこのへんを見て勉強してください。

ちなみに自分一人で作ってるプログラムのcommitメッセージがずっと「add」ばかりなのは内緒の話。

コミットコメントは一行で、かつ自分が分かりやすいコメントを

コミットメッセージは1行で書きます。

プロジェクトによっては、コミットメッセージに仕様かいたりするため、何行(何十行?)もつらつらコメント書く事があります。
(オープンソースのプロダクトはそういうのが多いですよね)

でも、(色々怒られそうなの承知でいいますが)それって大変じゃないですか。
1コミットが凄く重いです。大抵最初の一行しか読まないです。ならばビシッと一行で要点を書きましょう。

仕事のプロジェクトのコミットメッセージ、私は日本語で書きます。
githubに公開するプロジェクトならば頑張って英語で書くかもしれませんが、私は日本人ですし、周りの開発者も大抵日本人です。
英語で書くにしても、「fix xxx function.」 とか「refactor xxx」とか、残念な感じのコミットメッセージになりがちです。
なので私は日本語で書きます。

私のコミットメッセージ、日本語で書いてるけど結構適当です。「A関数修正」とか書いてます。プロジェクトメンバーの皆さん、ごめんなさい。。。
直近の私のコミットメッセージをさらしておきます。(xxx処理追加、とか適当なコメント感満載です)

git05-4a16773a-9355-8510-04d0-f3dbe9f13073.png

今見返してみて、この適当な感じのコメントは反省してます。。。気をつけます。

コミットメッセージには、ブランチ番号(XXX-575の部分)を含めてます。(イシューの番号とブランチ番号は一対一で対応させています)

また、先頭にどの部分を修正したか(viewとかcontrollerとか)を書いてます。
このコメントスタイルには賛否両論ありそうですが、コミットメッセージみただけでどの部分の修正か分かるので私は好きです。

hookを活用する

gitのhookをもっと活用しましょう。

例えばデバッグ用のコードが含まれているソースのコミットを禁止する、というpre-commit hook を仕込んでおくと、うっかりbinding.pry(Rubyのブレイクポイント)を書いたままPullRequestだしたりしなくなります。
この辺は活用している方も多いかと思います。

設定方法もいろんなサイトで既に紹介されています。たとえば このへん に書いてあったりするので、参考にしてみてください。

masterへのpush -fを禁止するhookとか、pushしたら(herokuのように)デプロイまで行うhookとか、色々設定できます。

私がよく仕事で使っているものは、git commit時にブランチ名とか変更点等をコミットメッセージに書いてくれるhookです。
git06-6289f3a4-39dc-bf75-c68f-ddff761f2635.png

上記のコミットコメントは、「:」前までは自動生成です。
現在のブランチが「issue-575」で、app/views/xxx.html.erb を修正している場合に

$ g ci -m "XXX画面作成"  # git commit -m "XXX画面修正"

と書くと、上記の画像のようなコミットメッセージが生成されます。
こういう自動生成できそうな部分は、hookを活用して生成していきましょう。

上記コメントを生成する、自作prepare-commit-msg hookをこちらのgistにさらしておきます。
(公開することを想定してないので、とてもRubyistが書いたとは思えないような汚いスクリプトですが、勘弁してください)

余計なものは無視する、または消す

私が他人のコンソール覗いていて一番気になるのが、下図のような状態です。

git07-671bd075-1288-bae9-7606-8dd28cf011ea.png

untracked filesがいっぱい!
コミットもしてないし、.gitignoreにもいれてない!ずっとこの状態の人。

これめちゃくちゃ気になるので、なんとかしてください。。。
余計なファイルなら、消しちゃってください。
必要そうなら、別ブランチ切って、そこにコミットするなりしてください。

私はUntracked filesはできるだけ0の状態に保つようにしてます。

まとめ

今回は私のローカルでのgitの使い方を晒してみました。

自分と同じような使い方してるな、って思った方。いや使い方適当すぎだろ、って思った方。
賛否両論あるかと思います。

こういうローカルでのgitさばきは、なかなか他人に見えにくい部分かと思います。

みなさんのローカルでのgitの使い方、色々教えてください。