Upgrade to Pro — share decks privately, control downloads, hide ads and more …

detached HEADを理解して脱Git初心者を目指す方のためのGit入門勉強会 @サポーターズCoLab

detached HEADを理解して脱Git初心者を目指す方のためのGit入門勉強会 @サポーターズCoLab

ソースコード管理システムの定番となったGit。
初心者が覚える基本的なGitの概念のうち、最初のハードルの1つと言えるのがbranchです。
特に作業中 "detached HEAD" という文字列が現れて慌ててしまった経験はどなたにもあるかと思われます。
実はdetached HEADを正しく理解できれば、ブランチに縛られない自由な開発ができるようになります。
またそのためにはbranchとHEADの正しい理解が不可欠です。
独学やネットからの情報からでは誤った理解をしてしまうこともあるため、今一度branchとHEADの真の姿を解説した上で、detached HEADとは何かをやさしく紐解きます。

Tomohiro Imaizumi

February 06, 2018
Tweet

More Decks by Tomohiro Imaizumi

Other Decks in Programming

Transcript

  1. detached HEADを理解して
    脱Git初⼼者を⽬指す⽅のための
    Git⼊⾨勉強会
    @サポーターズCoLab
    ミクシィグループ 株式会社Diverse
    新規サービス事業部 Poiboyグループ
    今泉智博 (2018/02/06)

    View Slide

  2. INDEX
    自己紹介
    プロローグ
    本日のゴール
    Git の基礎コマンド復習
    Git branch を理解しよう
    Git HEAD を理解しよう
    Detached HEAD を理解しよう
    事例紹介 & 演習時間
    本日のまとめ
    参考リンク & お知らせ
    質問コーナー

    View Slide

  3. INDEX
    自己紹介
    プロローグ
    本日のゴール
    Git の基礎コマンド復習
    Git branch を理解しよう
    Git HEAD を理解しよう
    Detached HEAD を理解しよう
    事例紹介 & 演習時間
    本日のまとめ
    参考リンク & お知らせ
    質問コーナー

    View Slide

  4. 自己紹介
    今泉智博 (@imaizume )
    株式会社 in
    iOS版の開発を担当
    よく使うコマンドはrebase -i & add -p
    今年はノーラーメン&COMPで-5kgを達成
    2/20に学生向けLT会出ます(&もあるよ❗)
    (https://mixi-recruit.snar.jp/jobboard/detail.aspx?id=fuEGYRyWOsM)

    View Slide

  5. INDEX
    自己紹介
    プロローグ
    本日のゴール
    Git の基礎コマンド復習
    Git branch を理解しよう
    Git HEAD を理解しよう
    Detached HEAD を理解しよう
    事例紹介 & 演習時間
    本日のまとめ
    参考リンク & お知らせ
    質問コーナー

    View Slide

  6. 本題の前に
    みなさんに質問です

    View Slide


  7. ❓ Git を不自由なく使えていますか
    ❓ Gitコマンドをいくつ知っていますか
    ❓Git を仕事/プロジェクトで使っていますか

    View Slide

  8. Gitを便利にするツールたち
    (ただしGUIツールを除く)

    View Slide

  9. tig (コマンドラインツール)
    addとcommitが j/k/u/1/Enter のみで完結

    View Slide

  10. git alias (ショートカット設定)
    @imaizumeは166 alias設定していました

    View Slide

  11. gitignore with gibo
    さらに”git” は “g” にaliasできる! (参考記事)

    View Slide

  12. 正しく便利設定をして
    操作量とミスを減らしましょう

    View Slide

  13. でも今日は
    これらの便利設定
    あえて使いません
    (コマンドを理解してもらいたいので)

    View Slide

  14. では本題

    View Slide

  15. ⬇ Gitの操作に慣れてきたあなた
    gitなんて楽勝だわー
    branch切ってaddしてcommitして
    pushするだけだもんね〜

    View Slide

  16. …しかしある日

    View Slide

  17. そのメッセージは突然現れた

    View Slide

  18. View Slide

  19. View Slide

  20. _人人人人人人人人人人人人_
    > 突然の detached HEAD <
     ̄YYYYYYYYYYYY ̄
    \(^o^)/

    View Slide

  21. ウッ…
    どうすればいいんだっけ…

    View Slide

  22. ネットで調べて
    その場では解決する

    View Slide

  23. でも
    ちゃんと本質理解してますか❓

    View Slide

  24. ggrks
    面倒だけど
    検索するか…
    その場しのぎの
    知識を得ます
    一時的に万能感を
    覚えます
    すぐに
    忘れます
    前にググったはずなのに
    思い出せない!!
    もう一回
    検索だ!!
    テンプレ以外の対応が
    できなくなります

    View Slide

  25. こうならないように
    今日しっかり覚えましょう

    View Slide

  26. 実は
    detached HEADを理解すると
    Gitとより仲良くなれる

    View Slide

  27. ブランチに縛られないで
    commit間を自由に移動できる❗

    View Slide

  28. INDEX
    自己紹介
    プロローグ
    本日のゴール
    Git の基礎コマンド復習
    Git branch を理解しよう
    Git HEAD を理解しよう
    Detached HEAD を理解しよう
    事例紹介 & 演習時間
    本日のまとめ
    参考リンク & お知らせ
    質問コーナー

    View Slide

  29. 本日のゴール
    Detached HEADを恐れない
    detached HEADを理解する

    View Slide

  30. 本日のサブゴール
    そのため必要なこと…
    branchとHEADの正しい理解

    View Slide

  31. INDEX
    自己紹介
    プロローグ
    本日のゴール
    Git の基礎コマンド復習
    Git branch を理解しよう
    Git HEAD を理解しよう
    Detached HEAD を理解しよう
    事例紹介 & 演習時間
    本日のまとめ
    参考リンク & お知らせ
    質問コーナー

    View Slide

  32. 基礎的なGitコマンド
    ⭐git init
    ⭐git status
    ⭐git add
    git commit [-m]
    git checkout [-b]
    git branch
    今日の講義でよく使います‼

    View Slide

  33. INDEX
    自己紹介
    プロローグ
    本日のゴール
    Git の基礎コマンド復習
    Git branch を理解しよう
    Git HEAD を理解しよう
    Detached HEAD を理解しよう
    事例紹介 & 演習時間
    本日のまとめ
    参考リンク & お知らせ
    質問コーナー

    View Slide

  34. git branchについて
    正しく理解していますか❓

    View Slide

  35. よくあるbranchの説明
    001
    002
    master
    > git init && git commit
    > git commit
    003
    > git branch dev && git checkout dev
    > git commit
    dev
    004
    > git checkout master
    005
    > git commit
    > git checkout dev
    > git commit
    branch is コレ

    View Slide

  36. ではこんな場合は❓

    View Slide

  37. 分岐前の部分
    001
    002
    master
    003
    dev
    004
    005
    branch is … アレ ❓
    分岐前の部分を
    図的に入れ替えてみた
    (履歴は前の図と同じ)

    View Slide

  38. 同一commitで複数branch作成
    001
    master dev
    > git checkout master
    > git checkout -b dev
    > git checkout -b test
    > git checkout -b feature
    feature test
    branch is ドレ❓

    View Slide

  39. マージした/されたブランチ
    001
    002
    master
    003
    004
    005
    > git merge dev
    dev
    > git checkout master
    006
    master branch is コレ❓

    View Slide

  40. Q: 結局branchって何なの❓

    View Slide

  41. A: commitを指すポインタ

    View Slide

  42. 「ポインタ」と聞いて連想するものは❓

    View Slide

  43. C言語ですよね
    (他言語での「参照渡し」も同様)
    char型のポインタpを作成
    > char *p = “clang”
    c l a n g \0
    p

    View Slide

  44. 002
    master
    branch=commitへのϙΠϯλ
    001
    実はgitの「ポインタ」も本質は同じ
    > git branch master

    View Slide

  45. git branch の正体
    ⭐ さらにざっくり言えば
    「branch = commitの別名」
    (⾠コマンドの実行結果は異なるので注意)
    よくある勘違いの原因
    「branch ≠ コミット群」

    左の例では
    • master は004を指すポインタ
    • devは 005を指すポインタ
    001
    002
    master
    003
    dev
    004
    005
    ここを詳しく深掘り

    View Slide

  46. branchへcommitを積んだ時のgit内部の動き
    master
    001

    002
    > git checkout master
    (操作対象をmasterに切り替え)
    > git commit -m “fix bugs”
    (masterが指しているcommit 001に新しいcommitを積むよ)
    (新しいcommit 002を作るね、親は001だよ)
    > [master 002] fix bugs
    (masterの指す先を002に更新するよ) ポイント
    branchが指すcommitは
    自動で更新される

    View Slide

  47. commitへcommitを積んだ時のgit内部の動き

    002
    001
    > git checkout 001
    (操作対象を001に切り替え)
    > git commit -m “fix bugs”
    (commit 001に新しいcommitを積むよ)
    (新しいcommit 002を作るね、親は001だよ)
    > [HEAD 002] fix bugs
    (操作対象を002に更新するよ) ポイント
    branchが指すcommitは
    自動で更新されない ❌
    ※同じIDのbranchとcommitへの操作結果
    コードの状態は同じ
    git上の状態は異なる
    master

    View Slide

  48. branchを無事に攻略
    カンタンでしたね‼
    「branchはcommitへのポインタ」
    と覚えておきましょう

    View Slide

  49. INDEX
    自己紹介
    プロローグ
    本日のゴール
    Git の基礎コマンド復習
    Git branch を理解しよう
    Git HEAD を理解しよう
    Detached HEAD を理解しよう
    事例紹介 & 演習時間
    本日のまとめ
    参考リンク & お知らせ
    質問コーナー

    View Slide

  50. ところでみなさん
    お気づきですか❓

    View Slide

  51. master
    001

    002
    master

    002
    001
    ⬅ こいつは一体何者⁉

    View Slide

  52. Q: 「自分が今見ているcommit」
    をGitではどう表現するの❓

    View Slide

  53. A: HEADͱ͍͏ϙΠϯλͰදݱ

    View Slide

  54. git HEAD の正体
    ⭐ HEAD=「自分が今見ている
    commit/branchを指すポインタ」
    ⭐ gitでは特殊な存在
    左の例では
    • HEADはmasterを指す
    • masterはcommit 004を指す
    • devはcommit 005を指す
    001
    002
    master
    003
    dev
    004
    005
    (HEADのN commit前を ”HEAD~N” のように表現)
    HEAD

    View Slide

  55. 改めてgit commitで起きること
    > git checkout master
    [NEW] (操作対象HEADをmasterに切り替え)
    > git commit -m “fix bugs”
    (masterが指しているcommit 001に新しいcommitを積むよ)
    (新しいcommit 002を作るね、親は001だよ)
    > [master 002] fix bugs
    (masterの指す先を002に更新するよ)
    [NEW] (HEADが指している先はmasterだな)
    master
    001
    002
    HEAD
    [NEW] (HEADが指している先は変えないよ)
    commitを含む
    全てのgitコマンドは
    HEADを通じて実行されている

    View Slide

  56. HEADも攻略
    これもカンタンでしたね‼
    「HEAD = 今見ているcommit/branchへのポインタ」
    と覚えておきましょう

    View Slide

  57. INDEX
    自己紹介
    プロローグ
    本日のゴール
    Git の基礎コマンド復習
    Git branch を理解しよう
    Git HEAD を理解しよう
    Detached HEAD を理解しよう
    事例紹介 & 演習時間
    本日のまとめ
    参考リンク & お知らせ
    質問コーナー

    View Slide

  58. Git branch の正体
    ついに…本日のテーマである
    detached HEADの解説です⚔

    View Slide

  59. Q: ズバリdetached HEADとは❓

    View Slide

  60. A: HEADが
    branchを指していない状態

    View Slide

  61. お疲れ様でした
    detached HEADの解説
    以上❗

    View Slide

  62. あっさりすぎるので一応補足
    • branchをcheckoutしている間はdetached HEADしない
    • commitをcheckout (or rebase途中等)でdetached HEADする
    • detached ➡ attached へ戻りたければ
    1.ブランチをcheckoutする (e.g. git checkout master)
    2.その場でブランチ作る (e.g. git checkout -b new-branch)
    001
    HEAD
    ➖detached HEAD
    master
    001
    HEAD
    ➕attached HEAD

    View Slide

  63. もっと詳しく:.gitディレクトリ
    “HEAD” と
    “refs/heads/xxxx”
    の中身は?

    View Slide

  64. imaizume@mac ~/dots (master) $ git checkout HEAD~1
    Note: checking out 'HEAD~1'.
    You are in 'detached HEAD' state. You can look around, make experimental
    changes and commit them, and you can discard any commits you make in this
    state without impacting any branches by performing another checkout.
    If you want to create a new branch to retain commits you create, you may
    do so (now or later) by using -b with the checkout command again. Example:
    git checkout -b
    HEAD is now at 8952c2c... Update Readme
    imaizume@mac ~/dots (cdc8446) $ cd .git
    imaizume@mac ~/dots/.git (cdc8446) $ ls -a
    . COMMIT_EDITMSG HEAD branches description index
    logs packed-refs tags.lock
    .. FETCH_HEAD ORIG_HEAD config hooks info
    objects refs
    imaizume@mac ~/dots/.git (cdc8446) $ cat HEAD
    cdc84468952c2cb2c8cebe819cbea64f0654eae4
    imaizume@mac ~/dots/.git (cdc8446) $ cat refs/heads/master
    40f1d950027fd7d2efbba17576402610adf1e6cc
    commit を checkout した状態
    (detached HEAD)
    HEAD =/=> master

    View Slide

  65. imaizume@mac ~/dots (master) $ git checkout master
    Already on 'master'
    Your branch is up-to-date with 'origin/master'.
    imaizume@mac ~/dots (master) $ cd .git
    imaizume@mac ~/dots/.git (master) $ ls -a
    . COMMIT_EDITMSG HEAD branches description index
    logs packed-refs tags.lock
    .. FETCH_HEAD ORIG_HEAD config hooks info
    objects refs
    imaizume@mac ~/dots/.git (master) $ cat HEAD
    ref: refs/heads/master
    imaizume@mac ~/dots/.git (master) $ cat refs/heads/master
    027fd7d2efbba17576402610adf1e6cc40f1d950
    branch を checkout した状態
    (attached HEAD)
    HEAD => master
    内部構造をもっと詳しく知りたい方は
    ”Pro Git 第10章”をご参照ください

    View Slide

  66. INDEX
    自己紹介
    プロローグ
    本日のゴール
    Git の基礎コマンド復習
    Git branch を理解しよう
    Git HEAD を理解しよう
    Detached HEAD を理解しよう
    事例紹介 & 演習時間
    本日のまとめ
    参考リンク & お知らせ
    質問コーナー

    View Slide

  67. 事例1: 差分の影響を調べる
    • HEADでバグが発生
    • ちょっと(1commit)前に戻りたい
    • 問題なかったら元のcommit (branch)へ戻りたい
    • よってgit resetするのは嫌
    • 直前のコミットをcheckout(してビルド)する
    • 一時的にdetached HEAD状態になる
    • 手軽に差分の影響を調べられる
    C1
    a
    C2
    C1
    a
    C2
    HEAD HEAD
    少し前に戻って
    状態を再現したい

    View Slide

  68. 事例2: branchの再作成
    • 作業中誤ってブランチ(a)を消してしまった‼
    • 既に違うブランチ(b)に移動済み
    • しかもgithubにもpushしていない…
    • お助けコマンド: git reflog
    • HEADが指していたcommitの履歴を表示
    • 一旦HEADをdetach
    • C2へ移動後にbranch再作成!!
    b
    C3
    C2
    a
    C1
    HEAD
    C3
    C2
    C1
    b
    C2に戻りたい!

    View Slide

  69. 事例3: ブランチの強制移動
    • 今のブランチ(a)を一旦破棄したい
    • その際既存ブランチ(b)にそのまま(a)を移動したい
    • git branch -f を使う
    • 強制的にブランチをHEADへポイント
    • リモートへpush済みの場合conflictに注意
    • 「ブランチ=ポインタ」の構造を知っていれば簡単
    • 再びC2に戻りたい時は事例2の手順でOK
    C1
    a
    b
    C3
    C2
    C1
    a
    C3
    C2
    b
    C2を破棄して
    bに合わせたい!
    HEAD

    View Slide

  70. INDEX
    自己紹介
    プロローグ
    本日のゴール
    Git の基礎コマンド復習
    Git branch を理解しよう
    Git HEAD を理解しよう
    Detached HEAD を理解しよう
    事例紹介 & 演習時間
    本日のまとめ
    参考リンク & お知らせ
    質問コーナー

    View Slide

  71. 本日のまとめ
    branch = commitを指すポインタ
    HEAD = 自分が見ている
    commit/branchを指すポインタ
    detached HEAD =
    HEADがbranchを指していない状態
    detached HEADは怖くない!
    branchから解放されてcommitを自由に飛び回ろう

    View Slide

  72. INDEX
    自己紹介
    プロローグ
    本日のゴール
    Git の基礎コマンド復習
    Git branch を理解しよう
    Git HEAD を理解しよう
    Detached HEAD を理解しよう
    事例紹介 & 演習時間
    本日のまとめ
    参考リンク & お知らせ
    質問コーナー

    View Slide

  73. 関連記事/参考資料
    jonas/tig
    simonwhitaker/gibo
    peco と alias -g で git に便利革命おきた -
    Qiita
    detached HEAD から脱出する方法を git の
    内部構造から探る - Qiita
    Pro Git

    View Slide

  74. イベント告知: mixi GROUP Tech Meet !
    ミクシィグループ17新卒5名によるLT&交流会
    入社経緯や仕事、技術等を語ります
    美味しいご飯とお酒も提供予定
    採用ページにて告知中 (2月18日応募締切り)

    View Slide

  75. イベント予告: git challenge
    毎回「現場あるある」なGitの問題を出題
    実際にコマンドを叩いて解答、獲得点数を競う
    第2回からGitHub Japanさんが公式スポンサーに ❗
    次回は未定です...が決まり次第弊社採用ページで告知予定

    View Slide

  76. INDEX
    自己紹介
    プロローグ
    本日のゴール
    Git の基礎コマンド復習
    Git branch を理解しよう
    Git HEAD を理解しよう
    Detached HEAD を理解しよう
    事例紹介 & 演習時間
    本日のまとめ
    参考リンク & お知らせ
    質問コーナー

    View Slide

  77. 当日頂いた質問と回答 (1)
    Q: branch ではなくcommitにcommitを積む場面はあるのか❓
    A: 正直あまりないです(解説したのにすみません…)
    HEADの少し手前から試行錯誤で別のcommit系列を積んで
    確信が得られたらブランチにするとかはあるかもしれません。
    Q: gitを上達したいです❗…がどうすればよいですか
    A: 自分の経験では以下の3つを意識すると良いかもです。
    1. 何よりも実務/プロジェクトで触る (必要性があると覚える)
    2. コマンドを覚えたらオプションも調べましょう (結構有益)
    3. 近くにgitのメンターを(直接対面で聞いた方が良いことも多い)

    View Slide

  78. 当日頂いた質問と回答 (2)
    Q: gitのコミットはファイルを保存しているの入っていない❓
    A: gitが管理しているのは「差分だけ」です。
    内部的に差分はcommit単位で.git/objects以下に保存されます。
    gitコマンドを叩くと裏では.git/objectsから
    差分情報を読み出したり保存したりしているのです。
    Q:”fix bugs” というコメントはなぜダメなのでしょうか❓
    A: 読み手に親切な表現ではないのです。
    コミットメッセージは他人(or 未来の自分)が読んで
    差分を見ずに変更の概要を把握できるべきです。
    なので「具体性のあるメッセージが望ましい」という意味でした

    View Slide

  79. 当日頂いた質問と回答 (3)
    Q: きれいなコミットメッセージを書くコツは❓
    A: 粒度の小さなコミットを積むと良いでしょう。
    1000行の差分を一言で表すのは難しいですが
    2,3行なら自分が何をしたかすぐ説明できるはずです。
    あとは変更の内容に理由を合わせて書くのが良いでしょう。
    おすすめは git add -p で小さな commit を作り
    その後 git rebase -i で意味ごとに整列/結合する方法です。

    View Slide

  80. View Slide