はじめに
私はgitのコマンドオプションについて、例えばgit resetならHEAD~指定、git rebaseはハッシュ指定と決まった形で覚えていました。
しかし、こちらの記事で自分の知らないgit rebase
の使い方が紹介されており、その流れでコミット指定方法が理解でき、今まで不便に感じていたコマンドの使い方が解消されました。
最初にこの辺りの仕様を理解していればな~と思ったので、記事にまとめておこうと思います。
gitのコミットを指定する方法は色々ある
先に結論から。以下のような方法でコミットを指定することが出来ます。
指定方法 | 意味 | 備考 |
---|---|---|
ハッシュ値 | 対応するコミットを直接指定 | |
HEAD | 最新のコミット | |
HEAD~n | 最新のコミットのn個前 | HEAD~だと最新の1個前 |
ハッシュ値~n | 対応するコミットのn個前 | ハッシュ値~だと最新の1個前 |
また、どれもその意味に該当するハッシュ値を指定しています。以下詳細です。
ハッシュ値を指定
コミット指定の基本はハッシュ値で行います。
ハッシュ値はgit log
等で確認出来るcommit d7aab0dec8e026f64cb6fae75d7ca05b5ec50b05
のような長い16進数の値です。
この値はコミットを一意に表すものになっているため、この値を利用してコミットの指定が可能となります。
また、実際コマンドで指定する際は前の7桁だけ指定すれば十分だったりもします。(下記は指定したハッシュ値のコミット内容を表示するgit show
の例です)
$ git show d7aab0d
commit d7aab0dec8e026f64cb6fae75d7ca05b5ec50b05
Author: developer-kikikaikai <kikikaikaikai@gmail.com>
Date: Sat Aug 11 03:33:18 2018 +0900
<threadpool> Clean help option
diff --git a/Makefile.in b/Makefile.in
index 88f7cd2..93af2f8 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -170,8 +170,8 @@ DIST_SUBDIRS = design_pattern_util flyweight builder publisher \
threadpool state chain_of_responsibility memorypool prototype \
...
HEAD(最新のコミット)を指定
最新コミットのハッシュ値は、別名としてHEADが設定されています。
例えば最新のコミットが以下なら、HEAD=d7aab0dと同じ意味になります。
$git log --oneline
d7aab0d <threadpool> Clean help option
cebf87d <threadpool> Update readme to up fd size
5248829 <mement> Remove extra definition
...
実際にコマンドを実行してみても同じ。
$ git show HEAD
commit d7aab0dec8e026f64cb6fae75d7ca05b5ec50b05
Author: developer-kikikaikai <kikikaikaikai@gmail.com>
Date: Sat Aug 11 03:33:18 2018 +0900
毎回ハッシュ値を調べるのは面倒なので便利ですね。
また、手元で確認したところ、どのコマンドもコマンドオプションでハッシュを指定しない場合、基本デフォルトでHEADが指定されるようです。
なのでgit logやgit showでは最新コミットの内容が確認出来るんですね。
HEAD~n: 最新のコミットのn個前を指定する
HEADだけではなく、HEADからn個前のコミットを指定するという方法も用意されています。それがHEAD~n
指定。
例えば先ほどgit log --oneline
で表示していたコミットの例だと、先頭の2個前は5248829 <mement> Remove extra definition
になります。
$ git show HEAD~2
commit 52488293662d11e7d30ab445a68b17c344daba78
Author: developer-kikikaikai <kikikaikaikai@gmail.com>
Date: Fri Aug 3 08:12:15 2018 +0900
<mement> Remove extra definition
ハッシュ値~n: 対応するコミットのn個前を指定する
HEADは最新コミットに対するハッシュ値の別名です。ということは、HEAD~2は最新ハッシュ値の2個前という意味。
なので、5248829~2
のような特定のコミットからn番目という指定方法も可能だったりします。
gitコマンドの用途に合わせて指定方法を活用しよう
指定の仕方が色々あるんですよ~、と書かれてもピンとこないと思うので、私自身不便に感じていたコマンドの利用ケースを例にあげて説明したいと思います。
例1: git reset: 指定したコミットの1つ前までのコミットを削除する
直近いくつかのコミットを削除したい⇒HEAD~指定が便利
やっちゃった、間違えて変なものをコミットしちゃった!消さないと!
こんなケースではHEADが便利ですね。例えば2個分のコミットを削除するなら以下のような指定。
git reset --hard HEAD~2
コンフリクトが発生した履歴を削除したい⇒ハッシュ値~が便利
例えば以下のケースでd86c069 <builder> Set stack size, fixed #48
がコンフリクトしたため、一旦コンフリクトした履歴まで削除したいとします。
$ git log --oneline
7ab9110 <mement> Add new library
e1bd739 <common> Add CHANGES to remember changing external spec
c8999f5 <Common> Remove sample code
7659ba1 <command> add sample...
ec6ae98 <common> Add extern C option for C++, fix #45
d86c069 <builder> Set stack size, fixed #48
cadff15 <builder> Change constructor interface to sync constructor, fix #47
890acaa <builder> Fix to fail to load lib, fix #46
ここでgit reset HEADの使い方だけしか知らないと、「コンフリクトする直前のcadff15
まであと何個だっけ?」なんて数えながら地道にコミットを削除することになります。
今までの私がそうでした(-_-;)
そんな時にはハッシュ値~ 指定で、コンフリクトしたコミットの1個前まで削除する指定方法を知っていれば1発です。
$ git reset --hard d86c069~
Unstaged changes after reset:
M Makefile.am
M Makefile.in
...
#削除されたかコミットを確認。ちゃんと1個前のcadff15が先頭に来ている!
$ git log --oneline
cadff15 <builder> Change constructor interface to sync constructor, fix #47
890acaa <builder> Fix to fail to load lib, fix #46
...
例2: git log -pでコミットの詳細を確認する。
最新のログが見たい⇒HEAD or 指定なしで十分
通常の使い方はこれで問題ないですね。
とある修正より前のログが見たい⇒ハッシュ値指定が便利
例えば発生したバグの解析をする際に、問題発生時期したアプリケーションのバージョン的にこのコミットより前のどこかだ!その前のログが確認したい!
なんてケースがあったりします。
こちらも今までの私は愚直にgit log -p
の後ハッシュ値で検索なんてことをしていました。。。
こちらもこれで一発でしたね。
git log -p ハッシュ値
コミット指定を利用するgitコマンド × コミット指定方法には種類がある = 用途に合わせた使い方が選べる
というわけで、いくつか例をあげてコミット指定方法について紹介しました。
gitには沢山のコマンドがあり(チートシート載せておきます)、その中にはコミットを指定するコマンドも多くあります。
このコマンドと指定方法とをかけ合わせれば、基本的な使い方だけではなく色々な工夫が出来るはず。
実際「コミット指定の仕組みを理解していれば、あの時やってたあれがすぐ終わったのに~」という小さな記憶がふつふつと湧きあがっています。
この記事がそんなちょっとした作業効率化につながれば幸いです。
参考
git rebase -iでgitのコミットをまとめる
GitのHEAD, ORIG_HEAD, FETCH_HEAD, MERGE_HEADとは?
gitコマンドチートシート