🔗

git の ref 入門

に公開

はじめに

こんにちは!
最近は就活から逃げてニッチな技術系イベントに参加し、企業の方に「学生なのにこんなイベントに来ていて偉いね」と褒められることが生きがいの 27 卒学生エンジニアの yossuli です。
本記事は #Progate_Bar での発表内容を記事にしたものです。
今回は git の ref について解説し、この知識が具体的にどのような場面に役に立つのかを紹介します。

git の ref とは?

git の ref とは、git のオブジェクトを参照するための名前のことです。
git では、コミットやブランチ、タグなどのオブジェクトを一意に識別するために、ref を使用します。
ref は、git の内部でオブジェクトを管理するための重要な概念です。

git の ref とは?

git の ref(リファレンス)とは、コミットなどの Git オブジェクトを指し示すための「名前付きのポインタ」です。
コミットのハッシュ値は人間にとって扱いづらいため特定の重要なハッシュ値に対して、mainv1.0.0 のような読みやすい名前を付けて、オブジェクトを参照できるようにする仕組みです。
多くの ref は .git/refs ディレクトリ内のファイルとして保存されており、そこには対応するコミットのハッシュ値が記録されています。

ref の種類

git には、以下のような ref の種類があります。

ブランチ(branch)

ブランチは、あるコミットを指す ref で、新しいコミットが追加されるたびに自動的に更新されていく「動くポインタ」です。
機能追加や修正などの作業を分岐させることで、他の作業と独立して開発できます。

  • ブランチの作成と切り替え:git checkout -b <branch-name>
  • ブランチのマージ:git merge <branch-name>

リモート追跡ブランチ(remote-tracking branch)

リモートリポジトリの状態をローカルで追跡するための読み取り専用の ref です。origin/main のように <remote-name>/<branch-name> の形式で表されます。

  • リモートの状態取得:git fetch origin <branch-name>
    取得したブランチの最新のコミットは FETCH_HEAD という特別な ref に保存されます。
    git merge FETCH_HEAD を行うことで、リモートの変更をローカルブランチに統合できます。
    ローカルブランチとリモート追跡ブランチは別ものです。
  • リモートの変更を取り込む:git pull origin <branch-name>fetch + merge

タグ(tag)

タグは、特定のコミットを固定的に参照する「動かないポインタ」です。主にリリースポイントを示すのに使われます。

  • 軽量タグの作成:git tag <tag-name>
  • 注釈付きタグの作成:git tag -a <tag-name> -m "message"

HEAD は、現在チェックアウトしているブランチまたはコミットを指す特別な ref です。
通常はブランチを指しており、これを「シンボリック参照」と呼びます。
一時的に特定のコミット(タグやハッシュ)を直接チェックアウトすると、HEAD はそのコミット自体を指す「分離 HEAD(detached HEAD)」状態になります。

  • 最新の状態に戻す:git reset --hard HEAD
  • 以前の状態に戻す:git reset --hard HEAD~n

ref の保存

git の ref は、git reflog コマンドで動きを追跡することができます。
これは、ブランチや HEAD の変更履歴を表示し、過去の状態に戻すのに役立ちます。
特に、誤ってコミットを消してしまった場合でも、reflog を使えばその状態に戻すことが可能です。

reflog を使った例

例えば誤ってコミットを --hard で消してしまった場合でも、以下のようにして reflog を使って元の状態に戻すことができます。

# reflog の表示
$ git reflog
1a2b3c4d HEAD@{0}: reset: moving to HEAD
2a3b4c5d HEAD@{1}: reset: moving to HEAD^
3a4b5c6d HEAD@{2}: commit: hoge # 間違えて消してしまったコミット
# 元のコミットに戻す
$ git reset --hard HEAD@{2}

個人開発だと、チーム開発に比べ影響範囲が小さく自己責任が強くなるため、結構雑に git コマンドを叩いてしまいがちかなと思います。
その際に勢い余って余計なコミットを消してしまうこともあるかなと思います。
そのようなときに reflog を使って HEAD の履歴を確認し、元の状態に戻すために必要な情報を得ることができます。
これで、少なくともコミットさえしていれば、間違えた git 操作をしてしまってもおおむね何とかなりそうですね!

個人開発だからってテストの実行を忘れたり、適当にコミットを重ねたりしなければこんなことにはならんのですがね...;

まとめ

git の ref は、コミットやブランチ、タグなどのオブジェクトを参照するための名前であり、git の内部でオブジェクトを管理するための重要な概念です。
git の ref を追跡することで、過去の状態に戻すことができ、特に reflog を使うことで誤ってコミットを消してしまった場合でも元の状態に戻すことが可能です。
しかし、個人開発での気の緩んだ git 操作は、間違えてチーム開発で行ってしまった場合に非常に面倒な事態を引き起こしがちですので、取り返しがつかなくなる前に、常日頃から git のコマンドを慎重に使うことが大切です。

ちなみに、本記事以外にも 4 本、今回の LT に関連して記事を挙げていますのでそちらも併せてご覧いただけると幸いです。
xのフォローもよろしくお願いします!

Discussion