QAチームのいさな(@isanasan_)です。今回は筆者のお気に入りのツールをご紹介します。
モチベーション
先週コードレビューについての記事を書きました。
ジョインから1ヶ月経ちコードレビューで気を付けていることをまとめた
こちらの記事の中でrebaseを使ってコミットログを整形することがレビューコストの低下に繋がると書きました。
しかし筆者はgitをcli上で使いこなすのはそれなりに難しいものだと感じており、特にinteractive rebaseは初学者にとって非常にとっつきにくい機能だと思っています。
そこで、今回は筆者が愛用しているgitのクライアントツールであるlazygitを紹介します。本稿ではハンズオン形式でgitの歴史改変の操作を説明していきます。尚、ハンズオンの題材に使ったコードは動作確認などはしていません。本題とは関係ないので細かいツッコミは無しでお願いします。
##環境
尚、筆者の環境は以下の通りです。
lazygitとは
goで書かれたgitのTUIクライアントです。2021年11月現在のスター数は21.9kとかなりの人気OSSです。
GitHubリポジトリはこちら
インストール
早速インストールしてみましょう。基本的にメジャーなパッケージ管理ツールでinstall可能となっております。個人的には最新版のバイナリがすぐ取得できるgo install
で入れるのが楽だと思います。
readmeを参考にお手元の環境に合わせた方法をご利用ください。
尚、本稿で扱うlazygitのバージョンは0.30.1です。
設定
windowsの場合、デフォルトだと選択中のカーソルにハイライトされなくて操作しようが無いので%APPDATA%\lazygit\config.yml
に下記設定をしておきます。
gui:
theme:
selectedLineBgColor:
- reverse
selectedRangeBgColor:
- reverse
設定ファイルは下記の手順でlazygitから開くことが出来ます。
- Statusパネルに移動
-
o
を押下
最低限の操作方法
まずは最低限の操作方法を確認します。
コンソールを開いてlazygit
と打てばlazygitが起動します。
適当なリポジトリで起動してみましょう。
移動に使うキーはh
,j
,k
,l
,[
,]
の6つです。
※ こちらの例ではlazygit自体のリポジトリでlazygitを起動しています
ハンズオン
それでは早速実際の作業を通してlazygitの使い方を見ていきましょう。
適当なディレクトリを切ってgit init
しておきます。
まずはPeople.php
を作りましょう。
<?php
declare(strict_types=1);
class People
{
public function hallo()
{
echo "hallo";
}
}
ステージングとコミット
作成したファイルを下記の手順でステージングしてコミットします。
- 対象のファイルを選択
space
を押下してファイルをステージングc
を押下してコミットメッセージの入力プロンプトを表示- コミットメッセージを入力
enter
を押下してコミット
まずはファイルをコミットすることが出来ました。
typoを修正してamend commitする
コミットした後にタイポに気がついたので修正します。
- public function hallo()
+ public function hello()
ここで
fix: typo
なんていうコミットは積みたくないので下記の手順でamend commitします。
- 対象ファイルをステージング
A
を押下してamend commit
これで無事不要なコミットを積むことなく修正を行うことが出来ました。
引き続き実装を進めていく
新しい仕様を思いついたので追加します。
- public function hello()
+ public function hello_to_name($name)
普通にステージングしてコミットします。
さらに先程のクラスを利用する側のコードを実装します。
index.php
require_once(dirname(__FILE__)."/People.php");
$mike = new People();
$mike->hello_to_name('john');
これで2つのファイルと3つのコミットが出来ました。
coding styleを修正してfixup commitする
index.phpをコミットした後にPeopleクラスのメソッド名がcamel caseになっていないことが気になったので修正します。
- public function hello_to_name($name)
+ public function helloToName($name)
ここでも
fix: coding style
みたいなコミットを積みたくは無いので下記の手順でfixup
コミットを作ります。
- 変更内容をステージング
commits
パネルに移動- 修正対象のコミットにカーソルを合わせる
F
を押下してfixup commit
を作成
fixup
コミットを作ることが出来たので下記の手順でsquash
して対象のコミットに変更を混ぜ込みます。
commits
パネルに移動- 対象のコミットにカーソルを合わせる
S
を押下してsquash
を実行
履歴を遡ってコミットを修正することが出来ました。
remoteリポジトリを登録してpush
ここでリモートブランチにpushしてみましょう。
まずは下記の手順でリモートリポジトリを登録してpushします。今回はorigin git@github.com:isanasan/lazygit-tutorial.git
を登録します。
※ 事前にgithub上にリポジトリを作った上でremote urlをクリップボードからctrl-v
でペーストしています
- Local Branchesパネルに移動
- Remoteタブに移動
n
を押下- リモートの名称を入力して
enter
- リモートのURLを入力して
enter
P
を押下してpush
リモートリポジトリを登録してpushすることが出来ました。
interactive rebaseを使って履歴を修正する
pushしてからこのままでは動かないことに素で気がついたので修正を加えます。
まずはindex.php
を編集します。
- $mike->hello_to_name('john');
+ $mike->helloToName('john');
ついでにhelloToName
メソッドの引数に型を付けます。
People.php
- public function helloToName($name)
+ public function helloToName(string $name)
先ほどと同様にfixupしても良いのですが、折角なのでinteractive rebaseを使ってコミットを整形してみます。
- それぞれのファイルを個別にコミットする
- rebaseの起点になるcommitを選択して
e
を押下 - 混ぜ込みたいコミットを選択し
s
を押下 - 混ぜ込みたいコミットを選択し
ctrl-j
で対象のコミットの上に移動 m
を押下してrebase optionを表示しcontinue
を選択
とても簡単にinteractive rebaseすることが出来ました。
コミットメッセージを改変する
しかし、squashしたままだとコミットメッセージがおかしなことになっているので、下記の手順で修正していきます。
- 修正対象のコミットを選択して
R
を押下 - editorが起動するのでコミットメッセージを修正して
enter
を押下
コミットメッセージを改変することが出来ました。
隣り合うコミットを一手でsquashする
履歴としてはこれでも問題ないのですが、コミットの粒度が細かすぎる気がするので
ec26f1d5
と054b303b
をsquashでまとめてしまいましょう。
squashしたいコミット同士が既に隣り合っている時はinteracrive rebaseを使うまでもなく下記の一手でsquashできます。
- 混ぜ込みたいcommitにカーソルを合わせて
s
を押下
おっと、
You can not squash/fixup onto the second commit
と怒られてしまいました。最初のコミットにrebaseは実行できないのでした。
CustomCommandsを定義して更に高度な歴史改変をしてみる
仕方ないので更に歴史を改変してfirst commitを作りましょう。
first commitを後から追加するにはgit checkout --orphan
コマンドを実行してorphanブランチを作る必要があるのですが、lazygitの標準の機能ではorphanブランチを作れないのでcustomCommands
を定義してやります。
%APPDATA%\lazygit\config.yml
に以下の定義を追加しlazygitを再起動します。
customCommands:
- key: "N"
prompts:
- type: "input"
title: "What is the new orphan branch name?"
initialValue: ""
command: "git checkout --orphan {{index .PromptResponses 0}}"
context: "localBranches"
loadingText: "creating orphan branch"
以下簡単に説明します。
key
custom commandを呼び出すkey bind。今回はorphanブランチを作成するコマンドを定義するので、通常のブランチ作成のkeyであるn
に合わせてN
としておく。
prompts
custom command実行時に表示するインターフェースの設定項目です。1つのcustom commandに対して複数のpromptを設定することが出来ます。
type
promptの種類をinputもしくはmenuから選べます。今回はgit checkout --orphan
の引数にブランチ名を入力したいのでinput
を指定します。
title
promptの表示名称です。
initialValue
promptの初期値です。
command
呼び出したいコマンド。今回はgit checkout --orphan {{index .PromptResponses 0}}
としてpromptの入力内容を引数として設定する。{{index .PromptResponses 0}}
で何番目のpromptなのかを指定してやれば値を取れる仕組みとなっています。
context
custom commandを定義するpanelを指定する。今回はbranch操作に関連した設定なのでlocalBranches
を設定します。
loadingText
読み込み中の出力文字列。creating orphan branch
とでもしておきます。
customCommandsの詳しい解説はこちらで確認できます。
定義したCustomCommandを使ってorphanブランチを作る
CustomCommandでgit chackout --orphan
を使えるように設定したので下記の手順でorphanブランチを作成します。
- Local Branchesに移動
N
を押下- ブランチ名を入力して
enter
を押下
これで履歴を無視したブランチを作ることが出来ました。
orphanブランチでgit cleanを実行
リポジトリ内に存在しているファイルがステージング状態になっているので、下記の手順で全て削除します。
a
を押下して全てのファイルのステージングを解除D
を押下してreset option
を表示git clean -fd
を選択してuntracked filesを全て削除
これで真っ新なブランチが手に入りました。
orphanブランチにfirst commitを作る
真っ新なブランチが手に入ったのでfirst commitを作ります。readmeの追加とかでも良いのですが、このリポジトリはGitHubでpublicに公開するつもりなのでLISENCEファイルを作成してコミットすることにします。お好きなエディタでLICENSEファイルを作成してコミットします。
これでLICENSEファイルを追加するfirst commitを作ることが出来ました。
orphanブランチをリベースして取り込む
下記の手順でfirst commitを作ったorphanブランチをmainブランチに取り込みます。
- mainブランチにカーソルを合わせて
space
を押下してswitch - Local Branchesパネルで対象のブランチにカーソルを合わせる
r
を押下enter
を押下してrebaseを実行
歴史を改変していとも簡単にfirst commitまで作成することが出来ました。
改めてsquashする
気をとりなおしてもう一度コミットの粒度を調整するためにsquashを実行します。対象同士が隣り合っているので下記の一手で出来ます。デモのgifではついでにR
を使ってコミットメッセージの修正も行っています。
- 混ぜ込みたいコミットにカーソルを合わせて
s
を押下
一手でsquashを実行し、コミットをまとめることが出来ました。
force pushする
禁じ手ですがforce pushして今までの作業を無かったことにします。
これで一通りの歴史改変作業は完了です。
マージして不要になったブランチを削除
ローカルに不要なブランチが残っているので下記の手順で削除しておきます。
- 対象のブランチにカーソルを合わせる
d
を押下
これにて作業完了です。
まとめ
lazygitを使えばかなり簡単にgitの歴史改変が出来ることが分かって頂けたかと思います。
git操作苦手だよーっていう人は是非試してみてください。
参考
git コミットログを綺麗にしたい。fixupとsquash