読者です 読者をやめる 読者になる 読者になる

Gitのコミット指定時に使うキャレット(^)とチルダ(~)の違い

Git

例えばgit-resetなどをする時などにHEADの2世代前のコミットにHEADを移す場合は
HEAD^^としたりHEAD~2としたり。でもHEAD^2という指定もあります。そのへんのまとめ


題材としてアイドルマスターシンデレラガールズ(以下モバマス)で考えます。
まず、適当にリモートリポジトリを作った後git-cloneして最初のgit-commitを行います。
その後、運営の犬であるちひろさんを追加します。ここまでは共通作業ですのでm@sterブランチで行います


モバマスはキュート、クール、パッションの3属性があるので3属性分のブランチを作ります。
次に、いわゆる2コスと呼ばれている各属性のコスト2アイドルを追加していきましょう。

  • キュート:島村卯月
  • クール:渋谷凛
  • パッション:本多未央

キュートブランチ

$ git co master
$ git co -b cute

島村卯月はノーマルとニュージェネレーションを追加しておきましょう。
キュートブランチのログはこんな感じ

島村さんの追加が終わったらm@sterブランチにNon-Fast-Forwordマージを行います。
キュートブランチに含まれていないコミットがm@sterブランチにはないので
no-ffオプションを付けて強制的にNon-Fast-Forwordマージを行います。

$ git co master
$ git merge --no-ff cute

結果はこのようになります。

クールブランチ

$ git co master
$ git co -b cool

同じように渋谷ちゃんをニュージェネレーションまで追加しておきましょう。
クールブランチのログはこんな。

同じようにm@sterにNon-Fast-Forwordマージを行います。

$ git co master
$ git merge --no-ff cool

パッションブランチ

$ git co master
$ git co -b passion

パッションでは本多未央(ちゃんみお)を追加していきましょう。
でもあれ?ちゃんみおにはSRがありません。どうしましょう。
大丈夫パッションの2コスには高森藍子がいます。彼女のブランチを作って追加しましょう。
高森ちゃんの追加が終わったらパッションブランチにNon-Fast-Forwordマージを行います。

# passionブランチから
$ git co -b takamori
# 高森ちゃんのコミット後
$ git co passion
$ git merge --no-ff takamori

ログはこんな。

パッションの戦力も揃いました。m@sterブランチにNon-Fast-Forwordマージを行います

$ git co master
$ git merge --no-ff passion


マージを行った状態はこうなります。

本題

キャレット(^)

指定したコミットの親を指す

  • HEAD^
    • HEADの1番目の親
  • HEAD^^
    • HEADの1番目の親の1番目の親
  • HEAD^2
    • HEADの2番めの親
チルダ(~)

指定したコミットの前世代を指す

  • HEAD~
    • HEADの1世代前
  • HEAD~~
  • HEAD~2
    • HEADの2世代前


では実際にやってみましょう。高森ちゃんが追加されたcommit: a3cc66fをHEADから参照するにはどのような指定が必要でしょうか。
A. git show HEAD^2^2^
(いやまあhash値指定しろっていうのがごもっともなんですけれども)


解説
m@sterのHEADcommit: は3e9a73bです。
HEAD^2で2番めの親であるcommit: 06c8d18。
さらにその2番めの親であるcommit: 5c17eeeを参照しその親をみるみたいなことをしています。


HEAD^2とHEAD~2の違いはここにあります。チルダではどうなるでしょうか?
git show HEAD~2をするとcommit: 704e75cが参照されます。
1番目の親の2世代前を参照するのです。

結論

マージコミットがありその2番目以降の親を示す場合にはキャレットを使い、1番目の親についてはチルダでしていするとよさそうです。
git-logを見ればハッシュ値がわかるのであんまり使いませんので普段はgit show hash。git reset hashをお使い下さい(Σ(゚Д゚;エーッ!


理解さえ出来ればいろいろ指定はできますね。HEAD~8^2~3^3^^^^^^^^^^^^^^^^^^^^^^^^みたいなことも(ひどい)



ちなみに、このスクリーンショットのような画面は下記コマンドででます。alias設定しておきましょう

$ git log --graph --pretty='format:%C(yellow)%h%Creset %s %Cgreen(%an)%Creset %Cred%d%Creset'


また、Non-Fast-ForwordとかFast-Forwordとかは、僕の考えたマージコミットを作らない最強の運用法()に書いたのでそっちを見て下さい。