【Git 作業効率化 Tips】〜git addしてcommitしてpushするのが面倒な全ての人に捧ぐ〜


Githubが普及し、アジャイル開発やInfrastructure as Codeが当たり前になったいま
アプリ開発者・インフラ開発者にとってgitは最も多く使われるコマンドのひとつではないでしょうか?

私は仕事ではアプリ開発からインフラ管理まで多岐にわたっていろいろやってるんですが
アプリもインフラも当然gitを使い倒してます

先日、自分がgitコマンドを1日どれくらい叩いているか計測してみました。
どうも最低でも100回/日はgitコマンドを叩いているようです。
gitコマンドを打ち込む作業やgitを使った作業フローを効率化できないかと思い、このTipsに残しています。

※これは一例ですので、他の方がどのような工夫をしているのか気になります。「私はこんな風に効率化しています」などのコメントをいただければ幸いです。

本Tipsで紹介するテクニックは以下になります。

  • レベル1: 補完する
  • レベル2: エイリアスを設定する
  • レベル3: PullRequestはCLIで作る
  • レベル4: 一連の流れを自動化する

Gitを使った開発フロー

さて、gitを使ったチーム開発ではmaster, develop, featureのようにブランチを切り替えて作業を行うことが一般的でしょう。
そのなかでも必ずと言ってもいいほどやるのがこんなフローではありませんか?以下に私の具体的な作業をあげてみました。

本Tipsでは以下のようなgit flowを前提としています。
参考:一般的なgit flowで使用されるブランチ(master, develop, feature)

とある日の私の開発フロー

「さて、開発をするぞー!!
開発者である私はgit管理しているディレクトリにcdしました。

$ git branch
* hogehoge

「いまはhogehogeブランチだな。よしよし、まずはdevelopの最新から作業ブランチを切らなきゃな

$ git checkout develop
Switched to branch 'develop'

「developブランチに切り替えたぞ!とりあえずプルしてから作業ブランチ切ろう!」

$ git pull origin develop

最新をプルしてきたらブランチを切り替えます。

$ git checkout -b feature

「featureブランチも切ったし、これでやっとコーディングだ!

カタカタカタカタ…💻

--- コーディング完了 ---

コーディングが完了したので
ファイルの差分を確認します。

$ git status
On branch develop
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    a

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    foo.rb
    hello.py
    iam.json
    yammi.java

「今回はこれだけ開発したんだな。じゃあこの変更をステージに乗せて」

$ git add -A

「ちゃんとステージに乗ってるか確認しよう」

$ git status
On branch develop
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    a -> foo.rb
    new file:   hello.py
    new file:   iam.json
    new file:   yammi.java

「OKだな!よしコミットしよう!!

$ git commit -m “〇〇機能を作成”

「あとはプッシュして、、、」

$ git push origin ...あれ?なんて名前のブランチで作業してたっけ?

ここでブランチの名前をしょっちゅう忘れる私は作業ブランチの名前を確認します。

$ git branch
* feature

「あ〜そうだった、featureって名前のブランチで作業してたんだった
「じゃあ今度こそプッシュしよう!」

$ git push origin feature

「で、あとはgithub上でプルリクエストを出して…」
ブラウザを開いてPullRequestを作っていきます。

さて、以上がgit開発をする開発者の具体的な作業フローではないでしょうか。
PUSHする前にリベースしてコミットをまとめないとね!といった意見もあるかもしれませんが、
基本的にはターミナル上で開発作業を行なっていると必ずやらなければいけないコマンドがこんな感じですよね。
なんだかとても面倒です。この記事ではなるべく省力化できる策をいくつか考えてみます。

レベル1: 補完する

まずはgit-completionを入れましょう。
これを使えば<TAB>キーでgitコマンドの補完ができます。

gitコマンドの補完はもちろん

branch名の補完もやってくれるので便利ですね。

導入方法はgit-completion.bashのソースをコピーしてきて
bash_completionを導入している人は/usr/local/etc/bash_completion.d/git-completion.bashに保存しておけばOKです。
bash_completionがなくても/usr/bin配下に置いておいてPATHを通しておけばいいですね。

レベル2: エイリアスを設定する

次に良くやるのはこれでしょう。

git -> g
add -> a
status -> st
branch -> b
commit -> cm
checkout -> co
push -> ph
pull -> pl

エイリアスとしてこのようにしておけば、
例えばブランチの確認なら

$ g b

になりますし、差分ファイルの確認なら

$ g st

と打つだけで良くなるのです。
これでタイプする数を少しは削減できそうですね!

~/.gitconfigに以下のように記述することでgitコマンドの補完ができます。
ここは自由にカスタマイズしてみてください。

~/.gitconfig
[alias]
    st = status
    co = checkout
    gr = grep
    df = diff
    cm = commit
    b = branch
    rs = reset
    rsh = reset --hard HEAD
    ph = push
    pl = pull
    cob = !git checkout `git branch | peco`

ちなみに直接~/.gitconfigを編集しても良いですが、以下のようにコマンドでもエイリアスを登録することができます。

$ git config --global alias.st status

また、~/.bashrcにはgitコマンドをgとしてエイリアスを設定しましょう。

alias g='git'

実はこのようにエイリアスをはってしまうと
$ g <TAB>で補完がきかなくなってしまうので、git-completion.shの中身を少し編集しましょう。

git-completion.sh
# 以下を追記
__git_complete g __git_main

これを入れておけば$ gというコマンドに対してもきちんとTAB補完がきくようになります。

私の一番のオススメはcobというエイリアスを定義しているのですが
これはpecoと組み合わせているのでチェックアウトするブランチを選んで簡単に切り替えられるようになる代物です。

レベル3: PullRequestはCLIで作る

hubコマンドを導入してPullRequestをわざわざブラウザからではなく、ターミナルから作成しましょう。
これにより、作業時間が削減できそうです。

hubコマンドのインストール方法

macであればbrewでインストールできます。

$ brew install hub
$ hub --version
git version 2.9.3
hub version 2.3.0-pre10-ge39364d

使用方法

hubコマンドを使用することで、CLIを叩いてPullRequestを送ることができます。

$ hub pull-request
https://github.com/<REPOSITORY>/pull/2

また、githubのレポジトリがブラウザで開けたり

$ hub browse
<ブラウザが立ち上がって、リポジトリが表示される>

プルリクエストも開けます。

$ hub browse <REPOSITORY_NAME>/pull/2
<ブラウザが立ち上がって、プルリクエストが表示される>

hubコマンドをgitコマンドで叩けるようにする

.bashrcにこのように書いておきましょう。

~/.bashrc
eval "$(hub alias -s)"

これで、hubコマンドの内容をgitで置き換えることができます。

$ git browse
<ブラウザが立ち上がって、リポジトリが表示される>

hubコマンドをgitコマンドで置き換えることができたので、先ほどご紹介したgitのエイリアス機能が使えるようになります。

~/.gitconfig
[alias]
    pr = pull-request
    bw = browse

のようにしてやれば

$ g pr

でPullRequestが発行できるようになりました。シンプル!!

レベル4: 一連の流れを自動化する

さて、レベル3までできればコマンドを打つのはだいぶ楽になりましたが、

  1. developブランチに切り替える
  2. developの最新をpullする
  3. developから作業ブランチを切り替える
  4. 作業ブランチで開発を行う
  5. 開発をして作成したソースコードをgit addする
  6. git commitする
  7. git push origin <作業ブランチ名>
  8. githubでPullRequestを発行する

という一連の流れはひとつひとつgitコマンドを駆使して行なっていかなければなりません。
生産をするという観点で言えば「4.作業ブランチで開発を行う」だけができれば良いだけなのに・・・

そこで、この一連の作業フローをなるべく自動化・効率化するべく
自動化スクリプトを作ってみました。

1~3 作業ブランチを切り替える作業を自動化する

まずは新しく作業ブランチを切って開発ができる状態にするまでを自動化してみましょう。

シェルスクリプト

とりあえず、~/.bashrcに書いておけばいいでしょう。
このスクリプトを使えば上述の1〜3は自動化することができます。
girkというコマンドを叩けば開発準備が整えられますね。

このシェルスクリプトの自動化範囲

1. developブランチに切り替える
2. developの最新をpullする
3. developから作業ブランチを切り替える

~/.bashrc
# developブランチのHEADをPullしてきて、新しく作業ブランチを切り替える
girk() {
    # developブランチに切り替え
    git checkout develop;
    # 最新をpull
    git pull origin develop;
    # 作業ブランチを切る
    read -p "Input feature branch name: " BRANCH
    git checkout -b ${BRANCH}
}

※ちなみgirkという名前はgitworkの頭と尻尾をとってgirkとしています。

使い方

現在チェックアウトしているブランチはなんでもよいです。

$ git branch
* hogehoge

新しくdevelopからブランチを切って作業をしたいときはこのスクリプトを使用しましょう。
まずはhogehogeで作業をしていたとします。

$ g b
  develop
* hogehoge
  master

新しくdevelopからブランチを切って作業をしたいのでgirkコマンドを打ちます。
作業ブランチの名前を聞かれるので答えてください。
ここではfeatureという名前にしています。

aws$ girk
Switched to branch 'develop'
From https://github.com/daisuke-awaji/aws
 * branch            develop    -> FETCH_HEAD
Already up-to-date.
Input feature branch name: feature
Switched to a new branch 'feature'

最後に正常にチェックアウトされたか確認してみます。
featureブランチに切り替わったことがわかります。

aws$ g b
  develop
* feature
  hogehoge
  master

5~7 開発した内容をPUSHするまでを自動化する

開発が完了したら、githubにPUSHする必要がありますが、
git add, commit, pushの一連の流れが少し面倒な気がします。
今回はこれを自動化してみましょう。

このスクリプトの自動化範囲

5. 開発をして作成したソースコードをgit addする
6. git commitする
7. git push origin <作業ブランチ名>

シェルスクリプト

前述同様に~/.bashrcに書いておけばOKです。

~/.bashrc
# git add, commit, pushまで一度に行う
gish() {
    # 全てステージにのせる
    git add -A;
    # コミット対象のファイルを確認
    git status;
    read -p "Commit with this content. OK? (y/N): " yesno
    case "$yesno" in
    # yes
    [yY]*) read -p "Input Commit Message: " msg;
           git commit -m "$msg";
           CULLENT_BRANCH=`git rev-parse --abbrev-ref HEAD`;
           git push origin ${CULLENT_BRANCH};;
    # no
    *) echo "Quit." ;;
    esac
}

使い方

開発が一段落した段階でこのコマンドを実行してみましょう。

$ gish
On branch feature
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    foo.rb -> yeah.rb

Commit with this content. OK? (y/N): y
Input Commit Message: foo.rbをyeah.rbに変更した

この内容でコミットしても良いか(y/N)と聞かれます。
yと答えると、次にコミットメッセージの入力が求められますので答えてください。
あとは<Enter>を押せばコミット、プッシュまで自動で行なってくれます。

※ちなみにgishという名前はgitaddcommitpushの頭と尻尾をとってgishとしています。

最後に

いかがだったでしょうか?

以上を使えば開発フローが随分効率よく回せますね。
まとめるとこんな感じです。

  1. girkコマンドを使って作業ブランチに切り替える
  2. 開発をする
  3. gishコマンドを使ってリモートリポジトリに公開する

あとは必要に応じてエイリアスで登録されたgitコマンドを叩く。

もし使えるところがありそうでしたらぜひ活用してみてください。
まだまだgitコマンドは省力化できる部分が多くあるかもしれません。
毎日たくさんつかうものですからなるべく無駄は無くしていきたいですよね!