search
LoginSignup
18

More than 3 years have passed since last update.

posted at

updated at

gitのコミット指定方法(ハッシュ値、HEAD、HEAD~)を理解して、コマンドを有効活用しよう!

はじめに

私は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コマンドチートシート

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
18