One Step Ahead

プログラミングやエンジニアリング全般について書いていきます

ちゃんとGitを使おうか。-squash編-

はじめに


今回、Git初導入の現場で、設計書という名の『Git指南書』を作ることになったので、その予行練習。

squashとは?


「squash」は『押しつぶす』『押し込める』の意味があり、Gitでは複数のコミットをまとめる行為を指す。

どうして「squash」を使うのか?


squashを使用する大きな理由の一つはコミット粒度・単位の調整。
コミット粒度・単位は運用に大きく関わり、Gitの安定運用を支える1要素になりえる。
Localリポジトリへのコミットは、自身の作業履歴であるためコミット粒度・単位に明確なルールを求められないことが多い。
しかし、統合ブランチへのコミットはプロジェクトそのものの履歴になるため、厳格なルールをもって運用されることが望ましい。

『squash』の実行方法(コマンド)


今回の画面は下記のような状態のリポジトリを使って、squashを実行していく。

f:id:EaE:20190701155836p:plain
test_repo_base

git rebase -i

まずはまとめるコミットの数を確認する。
今回の場合では、3つのコミットを1つにまとめるのでコマンドは下記のようになる。

git rebase -i HEAD~~~
or 
git rebase -i HEAD~3

チルダを3つ続けるか、チルダを1つ打った後にコミット数を指定する。

// ①squashしたいブランチへ移動しコマンドを実行する。
$ git rebase -i HEAD~3
hint: Waiting for your editor to close the file...
hint: Waiting for your editor to close the file...
[detached HEAD 5e9cdfd] [modify] commit No1
 Date: Mon Jul 1 11:58:22 2019 +0900
 1 file changed, 4 insertions(+), 1 deletion(-)
Successfully rebased and updated refs/heads/feature/#001_YYYYMMDD.

出力されるログだけ見てしまうと簡単そうに見えるがこの間に編集を2回行っている。
1度目はsquash対象の決定。

f:id:EaE:20190701160217p:plain
squash_check
左図のようにEditorが開くので、右図の形へ変更を加える。 今回は3つのコミットを対象としているが、その中でrootに当たるものだけを残し、その他のcommitをsquash対象にしている。 この状態でEditorを閉じれば、次の編集画面が開く。

次の編集画面はcommitメッセージの変更になる。

f:id:EaE:20190701160441p:plain
edit_msg
初期状態(右図)では、スカッシュの対象となった3つのコミットが表示されているので、No1のコミットメッセージのみを残す形へ修正する。
後は先ほどの同じようにEditorを閉じれば、作業が再開する。
f:id:EaE:20190701160611p:plain
rebase_complete

git merge --squash

まずは直接開発ブランチへmergeし、pushを行うパターン。 mergeを行うブランチ(develop)へチェックアウト後、対象の作業ブランチ(feature/#001_YYYYMMDD)をmergeする。

// ①developブランチへチェックアウト
$ git checkout develop
Switched to branch 'develop'
Your branch is up to date with 'origin/develop'.

// ②merge対象のブランチを指定
$ git merge --squash feature/#001_YYYYMMDD
Updating 8435359..4385ba2
Fast-forward
Squash commit -- not updating HEAD
 Program.cs | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

// ③squashされた変更をCommitする
$ git commit
hint: Waiting for your editor to close the file...
[develop 9d439b8] Squashed commit of the following:
 1 file changed, 4 insertions(+), 1 deletion(-)

$ git push origin develop

②の時点でグラフを確認すると下のような状態になっており、commitは実施されていない。

f:id:EaE:20190701160757p:plain
index_stage
この状態ではIndexに対して、ステージされた状態にすぎないため、最後にCommitを必要としている。
f:id:EaE:20190701160914p:plain
merge_complete

『squash』の実行方法(SourceTree)


先ほどと同じリポジトリを使用して、今度はSourceTreeからsquashを実施する。
今回は、3つのコミットをまとめて1つのコミットを作成するので、下記の位置で『インタラクティブなリベース』を指定する。

f:id:EaE:20190702094310p:plain
interactive_rebase
コミット選択画面が開くので、まとめたいコミットを上から指定していく。 コミットを選択すると『前のコミットとスカッシュ』ボタンが活性化するので、これをクリックする。
f:id:EaE:20190702094425p:plain
interactive_squash
すべてのコミットをまとめると最終的には1つのコミットだけが残るので、後はメッセージの編集を行うか、その必要がなければ『OK』を押下してsquashを完了する。
f:id:EaE:20190702094737p:plain
squash_after
コミットツリーからコミットがまとまっていることを確認できれば、squashは成功。
f:id:EaE:20190702094927p:plain
squash_complete