$30 off During Our Annual Pro Sale. View Details »

git branchを自由に操れるようになろう / Let's Play with Git branch!

git branchを自由に操れるようになろう / Let's Play with Git branch!

2020/01/07にSupporterZ CoLabでのオンライン勉強会「git branchを自由に操れるようになろう」での発表資料です。

https://supporterzcolab.com/event/1033/

演習用リポジトリ

* branch -f 用 : https://github.com/imaizume/2020-01-07_SupporterZ_branch-f
* rebase -i 用 : https://github.com/imaizume/2020-01-07_SupporterZ_rebase-i
* rebase --onto 用: https://github.com/imaizume/2020-01-07_SupporterZ_rebase--onto

参考リンク

* Sublime Merge - Git Client, done Sublime : https://www.sublimemerge.com/
* Git - git-branch Documentation : https://git-scm.com/docs/git-branch
* Git - git-rebase Documentation : https://git-scm.com/docs/git-rebase
* (再演) detached HEADを理解して脱Git初心者を目指す方のためのGit入門勉強会 @サポーターズCoLab - Speaker Deck : http://bit.ly/2DpZwga
* (再演)きれいなcommit, pull requestを知りたい/作りたい方のためのgit勉強会 - Speaker Deck : http://bit.ly/2SD90uT
* Githubで間違えてgit push -f origin masterしてしまった時の対応 - Qiita : https://qiita.com/awakia/items/52b5900e801c3bfbab04

宣伝リンク

* テキスト版:Gitの困り事何でも解決いたします 勉強会講師の経験有り ❗使い方から運用まで何でもどうぞ ❗ | ココナラ : https://coconala.com/services/642499
* ビデオ版:Gitの困り事解決いたします 勉強会講師の経験有り 使い方から運用まで何でもどうぞ! | ココナラ : https://coconala.com/services/839341
* 勉強会講師も担当 ❗ 親切丁寧にGitの使い方教えます 💻 | タイムチケット : https://www.timeticket.jp/items/58703
* Git・GitHubに関する相談・レクチャー - ストアカ : https://www.street-academy.com/myclass/73592

Tomohiro Imaizumi

January 07, 2020
Tweet

More Decks by Tomohiro Imaizumi

Other Decks in Programming

Transcript

  1. git branchを
    ⾃由に操れるようになろう
    SupporterZ CoLab @YouTube Live
    1

    View Slide

  2. 2
    Tomohiro Imaizumi @imaizume
    Retty株式会社 / 株式会社UZUMAKI
    Androidユーザー歴8年のiOSプログラマ
    SupporterZ ヘビー(?)ユーザー
    ⾃⼰紹介

    View Slide

  3. 3
    coconala / Time Ticket / ストアカで
    Git / GitHubに関する相談・レクチャーを受付中❗
    本⽇の内容以外についても
    聞きたいことや悩みがあればお気軽にどうぞ
    宣伝

    View Slide

  4. 4
    TOPIC
    • (復習) git branchについて
    • (前半) branchを⾃由に操えるようになろう
    • branchを付け替えてみよう
    • 付け替え前のcommit IDを忘れたら
    • remoteとの乖離が発⽣したら
    • (復習) git rebase -iについて
    • (後半) rebase -iでcommitとPull Requestを整理
    • ⼤きなPull Requestを分割するために
    • git branchの分岐元を変える
    • Pull Requestを⼩さくできない時は?

    View Slide

  5. 5
    補⾜: commit logを⾒やすくするために
    今回commit logがたくさん出てきます。
    ブランチの状態を⾒やすくするために...
    • ターミナル上で "git log --graph --all --oneline"
    • Sublime MergeのようなGUIツールを使う
    Sublime Mergeの画⾯

    View Slide

  6. 6
    (復習) git branchについて

    View Slide

  7. 7
    git branchとは
    • 複数の変更履歴を切り替えるための⽬印
    • 並列・⾮同期での開発に役⽴つ
    > git branch feature
    // feature ブランチを作成
    > git checkout feature
    // feature ブランチに切り替え
    > git branch -d old
    // old ブランチを削除
    ブランチの作成・切り替え・削除

    View Slide

  8. 001
    002
    master
    003
    dev
    004
    005
    branch is コレ
    よくあるブランチの説明
    ※「detached HEADを理解して脱Git初⼼者を⽬指す⽅のためのGit⼊⾨勉強会」より
    (古い)
    (新しい)

    View Slide

  9. 002
    master
    001
    ※「detached HEADを理解して脱Git初⼼者を⽬指す⽅のためのGit⼊⾨勉強会」より
    git branchとは??
    > The command’s second form creates a new branch head
    named which points to the current HEAD
    branch = commitへのポインタ
    Gitの公式マニュアルでも "points to" と表現

    View Slide

  10. ⭐ さらにざっくり言えば
    「branch = commitの別名」
    (⾠全く同じではない)
    よくある勘違いの原因
    「branch ≠ コミット群」

    左の例では
    • master は004を指すポインタ
    • devは 005を指すポインタ
    001
    002
    master
    003
    dev
    004
    005
    ※「detached HEADを理解して脱Git初⼼者を⽬指す⽅のためのGit⼊⾨勉強会」より

    View Slide

  11. ⭐ 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
    HEADとは??
    ※「detached HEADを理解して脱Git初⼼者を⽬指す⽅のためのGit⼊⾨勉強会」より

    View Slide

  12. 12
    (前半) branchを⾃由に操えるようになろう

    View Slide

  13. 13
    branchを付け替えてみよう
    ➡ branchは付け替え可能
    feature
    A B
    feature
    A B
    • branch = commitへのポインタ
    • ポインタは付け替えが可能
    BEFORE AFTER

    View Slide

  14. 14
    git branch -f : 強制的なブランチ移動
    > git checkout master (HEADをmasterへ切り替え)
    > git branch -f feature (masterと同じcommitにfeatureを移動)
    ブランチの強制的な付け替え
    master
    A B
    feature master
    A B
    feature
    Bを指すブランチが無い

    View Slide

  15. 15
    ⼀時ブランチを使った付け替え
    > git checkout feature (featureへ移動)
    > git branch tmp (一時的なブランチtmpを作成)
    > git checkout master (masterへ移動)
    > git branch -f feature (featureをmasterへ移動)
    > git checkout tmp (tmpへ移動)
    > git branch -f master (masterをtmpへ移動)
    > git checkout master (masterへ移動)
    ⼀時ブランチを使った付け替え
    master
    A B
    feature master
    A B
    feature
    tmp
    master
    A B
    feature
    tmp

    View Slide

  16. 16
    commit IDを覚えて付け替え
    master
    A B
    feature
    ポイント先=B
    master
    A B
    feature
    HEAD HEAD
    featureを付け替え後Bをcheckout
    master
    A B
    feature
    HEAD
    > git checkout master (masterへ移動)
    > git branch -f feature (featureをmasterへ移動)
    > git checkout B (Bへ移動)
    > git branch -f master (masterをBへ移動)
    > git checkout master (Bへ移動)
    commit IDを覚えて付け替え

    View Slide

  17. > git reflog
    HEADの移動履歴をreflogで確認
    17
    git reflog : HEADの移動履歴を参照する
    付け替え前のcommit IDを忘れたらgit reflogで探す
    master
    A B
    feature
    HEAD
    ここでgit reflog

    View Slide

  18. 18
    git reflog : HEADの移動履歴を参照する
    > git reflog
    A (HEAD -> master, feature) HEAD@{0}: checkout: moving from feature to master
    B HEAD@{1}: commit: commit on feature
    ...
    HEADの移動履歴をreflogで確認
    付け替え前のcommit IDを忘れたらgit reflogで探す
    master
    A B
    feature
    HEAD
    master
    A B
    feature
    HEAD
    master
    A B
    feature
    HEAD

    View Slide

  19. 19
    git reflog : HEADの移動履歴を参照する
    > git reflog
    A (HEAD -> master, feature) HEAD@{0}: checkout: moving from feature to master
    B HEAD@{1}: commit: commit on feature
    ...
    HEADの移動履歴をreflogで確認
    付け替え前のcommit IDを忘れたらgit reflogで探す
    master
    A B
    feature
    HEAD
    master
    A B
    feature
    HEAD
    master
    A B
    feature
    HEAD
    HEADが移動してないので
    reflog には残らない
    featureでの最後のcommitは "B"

    View Slide

  20. 20
    diverged branch : リモートとの乖離
    ブランチの履歴がリモートと変わると同期できなくなる
    master
    A B
    feature
    master
    A B
    feature
    push/pull可能 push/pull不可
    feature
    A B
    master


    View Slide

  21. 21
    git push -f : 強制的にリモートへpush
    master
    A B
    feature
    master
    A B
    feature master
    B A
    feature

    View Slide

  22. 22
    git push -f : 強制的にリモートへpush
    master
    A B
    feature
    > git checkout feature (featureへ移動)
    > git push -f origin feature (強制的にリモートのfeatureを更新)
    強制的にリモートへpush
    master
    A B
    feature master
    B A
    feature
    master
    A B
    feature
    featureのみリモートに反映
    masterもforce pushでBを指す

    View Slide

  23. 23
    実際の開発現場の運⽤では...
    • force pushは原則的に望ましくない
    • リモートの履歴はマスターデータ
    • 確実に安全 or 責任が取れる範囲でのみ
    • push前にローカルリポジトリでやっておく
    master
    A B
    feature master
    B A
    feature
    O O
    O どちらの状態でも
    push可能

    View Slide

  24. 24
    演習: git branch -f
    imaizume/2020-01-07_SupporterZ_branch-f
    git clone またはZIPダウンロードして移動をお願いします
    リセットするにはgit branch -fで移動させるだけ!
    (なのでbackup上ではcommit等はしないでください)
    (ちなみに...)
    "backup/xxx" は初期状態のxxxと同じcommitを指します

    View Slide

  25. 25
    (復習) git rebase -iについて

    View Slide

  26. rebase -i で commit log を再編集
    =結合/分割/書き換え/順序⼊れ替えが可能
    001
    002
    003
    004
    001*
    002*
    005
    > Fix bugs
    > Remove
    methods
    001*
    002A
    002B
    005*
    書き換え
    結合
    分割
    順序⼊れ替え
    ※「きれいなcommit,pull requestを知りたい/作りたい⽅のためのgit勉強会」より

    View Slide

  27. imaizumeオススメのcommit作成⼿順
    ProfileVC.swift
    極⼒その場でadd -p&commit
    messageは最低限の質で
    Old Service Update
    VC/Service Update
    Add new property
    New Service Update
    Update TestClass
    プロフィール画面を作成
    〜ができるようYYYServiceを〜に変更
    〜ができるようYYYVCを〜に変更
    OldServiceの一部をNewServiceに分離
    ZZZAPIを管理するNewServiceを作成
    〜ができるようXXXClassの〜を変更
    あとでまとめてrebase -i
    整理整頓後リモートPUSH
    ProfileVC.storyboard
    ※「きれいなcommit,pull requestを知りたい/作りたい⽅のためのgit勉強会」より

    View Slide

  28. 28
    (後半) rebase -iでcommitとPull Requestを整理

    View Slide

  29. 29
    ⼤きなPull Requestを複数に分割
    途中のcommitでbranchを作成し複数のPull Requestに
    master
    feature
    たくさんのcommit→
    master
    feature1
    feature
    feature2
    1つの大きなPull Request 複数の小さなPull Request

    View Slide

  30. 30
    ⼤きなPull Requestを複数に分割
    途中のcommitでbranchを作成し複数のPull Requestに
    master
    feature1
    feature2
    レビュー時だけ
    feature2のmerge先を分岐元に
    feature1をmaster merge後に
    feature2をマージ
    feature

    View Slide

  31. 31
    ⼤きなPull Requestを複数に分割
    途中のcommitでbranchを作成し複数のPull Requestに
    master
    feature1
    feature2
    feature
    commit履歴を
    事前に整理する必要あり
    意味単位でまとまったbranchにしたい

    View Slide

  32. 32
    事前にやること: commitの順序を整理
    関連commitごとになるようgit rebase -iで履歴を整理
    A Top Page更新
    Header作成
    Header内容追加
    Header⼀部削除
    Top 画像追加
    Top 画像更新
    footer追加
    footer削除
    B
    C
    D
    E
    F
    G
    H
    A' Top Page更新
    Top 画像追加
    Header作成
    Header内容追加
    Top 画像更新
    footer追加
    Header⼀部削除
    footer削除
    C'
    G'
    B'
    D'
    E'
    F'
    H'

    View Slide

  33. 33
    事前にやること: commitの順序を整理
    関連commitごとになるようgit rebase -iで履歴を整理
    A' Top Page更新
    Top 画像追加
    Header作成
    Header内容追加
    Top 画像更新
    Footer追加
    Header⼀部削除
    Footer削除
    C'
    G'
    B'
    D'
    E'
    F'
    H'
    Footer関連
    Header関連
    Top関連

    View Slide

  34. 34
    事前にやること: rebase -i でcommit順序を変更
    > git rebase -i HEAD~8
    // editor(vim)が起動
    rebase -i でcommitの順序を整理
    pick A Top Page更新
    pick B Header作成
    pick C Top 画像追加
    pick D Header内容追加
    pick E Header一部削除
    pick F Footer追加
    pick G Top 画像更新
    pick H Footer削除
    BEFORE
    pick A Top Page更新
    pick C Top 画像追加
    pick G Top 画像更新
    pick B Header作成
    pick D Header内容追加
    pick E Header一部削除
    pick F Footer追加
    pick H Footer削除
    :wq
    AFTER
    NORMAL
    NORMAL
    ※Vimの詳しい使い⽅については本⽇割愛
    ⾏を⼊れ替えて保存後エディタを閉じる
    (失敗して進まなくなったら rebase --abort)

    View Slide

  35. 35
    事前にやること: commitを統合/削除する
    細かすぎるcommitは1つに、不必要なcommitは削除
    A' Top Page更新
    Top 画像追加
    Header作成
    Header内容追加
    Top 画像更新
    Footer追加
    Header⼀部削除
    Footer削除
    C'
    G'
    B'
    D'
    E'
    F'
    H'
    A" Top Page更新
    Header作成
    Top 画像追加
    C"
    B"
    差分が±0なのでcommitにしない
    適切な粒度でcommitをまとめる

    View Slide

  36. 36
    事前にやること: rebase -i でcommitを統合/削除
    > git rebase -i HEAD~8
    // editor(vim)が起動
    rebase -i でcommitの順序を整理
    pick A' Top Page更新
    pick C' Top 画像追加
    pick G' Top 画像更新
    pick B' Header作成
    pick D' Header内容追加
    pick E' Header一部削除
    pick F' Footer追加
    pick H' Footer削除
    BEFORE
    pick A' Top Page更新
    pick C' Top 画像追加
    s G' Top 画像更新
    pick B' Header作成
    s D' Header内容追加
    s E' Header一部削除
    d F' Footer追加
    d H' Footer削除
    :wq
    AFTER
    NORMAL
    NORMAL
    ⾏頭をsquash(s)またはdrop(d)に変えて保存

    View Slide

  37. 37
    (再) ⼤きなPull Requestを複数に分割
    A" Top Page更新
    Header作成
    Top 画像追加
    C"
    B"
    master
    feature/header
    feature/top
    feature/top_image
    意味単位でまとまった⼩さなPull Requestへ

    View Slide

  38. 38
    rebase -iするための前提条件
    各commit間に依存関係がないこと
    ≒差分が⼩さいcommitであること
    (⼤きなcommitほど他のcommitが依存する可能性⼤)
    ※詳しくは「きれいなcommit,pull requestを知りたい/作りたい⽅のためのgit勉強会」を参照

    View Slide

  39. 39
    演習: git rebase -i
    imaizume/2020-01-07_SupporterZ_rebase-i
    git clone またはZIP DL後にターミナルでcdをお願いします

    View Slide

  40. 40
    より⾼度なテクニック: 分岐元を変える
    ある作業中に別ブランチにしたい差分が発⽣
    (例: 投稿画⾯を作成中にアプリ全体で共有する関数を実装)
    A1
    master
    shared/func
    An
    投稿画⾯ / UI Test
    B1
    Bn
    グローバル関数 / Unit Test
    masterから分岐させたい
    feature/post 依存関係なし
    ※コミット前なら "git stash save" が使える

    View Slide

  41. 41
    rebase --onto: 分岐元を付け替える
    依存関係がなければ分岐元を他のブランチに付け替え可能
    A1
    master
    shared/func
    An
    投稿画⾯ / UI Test
    B1'
    Bn'
    グローバル関数 / Unit Test
    feature/post
    > git checkout feature/array
    > git rebase --onto master feature/post shared/func
    分岐元を付け替え

    View Slide

  42. 42
    演習: git rebase --onto
    imaizume/2020-01-07_SupporterZ_rebase--onto
    git clone またはZIP DL後にターミナルでcdをお願いします

    View Slide

  43. 43
    リモートと乖離してpushできなくなる
    rebaseではcommit idが変わるため (順序変更以外でも)
    A
    B
    C
    A'
    B'
    C'
    feature feature
    A
    B
    feature
    ⭕push可能 ❌push不可

    View Slide

  44. 44
    force push による更新
    リモートの状態を強制的に更新する
    B
    A'
    B'
    C'
    feature
    feature
    A
    B
    A
    > git checkout feature
    > git rebase -i HEAD~2
    履歴を書き換え

    View Slide

  45. 45
    force push時の注意点
    間違えた&他のローカルに元の状態がない場合に復旧困難
    B
    A'
    B'
    C'
    feature
    A
    B
    A'
    B'
    C'
    feature
    > git push -f origin feature
    強制的に更新
    A
    ⚠戻すのが困難

    View Slide

  46. 46
    rebaseした履歴を安全にpushするには
    rebase前の履歴を別のブランチでリモートにpushしておく
    B
    feature
    A
    B
    A
    old_feature
    old_feature feature
    > git checkout feature
    > git branch old_feature
    > git push origin old_feature
    rebase前の履歴をpush

    View Slide

  47. 47
    rebaseした履歴を安全にpushするには
    その後rebaseした履歴をforce pushする
    B
    A'
    B'
    C'
    feature
    A
    B
    A'
    B'
    C'
    feature
    A
    old_feature
    old_feature
    > git rebase -i HEAD~3
    > git push -f origin feature
    rebase後の履歴をpush
    feature
    元に戻したい場合はold_featureとブランチを付け替える

    View Slide

  48. 48
    Pull Requestを⼩さくできないときは?
    • commit/Pull Requestの単位を⾒直す
    • 作成と編集、定義と実装で分ける
    • スコープやファイル単位で分ける
    • 実装やcommitの仕⽅を変えてみる
    • git add -pの活⽤
    • 実装前にインターフェースやテストを書く
    • アプリ設計の⾒直しも必要かも (SOLID原則等)
    • 同じPull Requestにする必要性は?
    • commit間に依存がないなら分けられるはず

    View Slide

  49. 49
    まとめ

    View Slide

  50. 50
    まとめ
    ✓ git branchは付け替え可能
    ✓ただし元のブランチを⾒失わないように
    ✓ rebase -i で履歴をいい感じに整理してからPRに
    ✓rebaseしやすくするため⼩さいcommitを意識しよう
    ✓ リモートと履歴が異なる場合はforce pushも可能
    ✓ ただし復旧困難にならないよう慎重に
    前半
    後半

    View Slide

  51. 51
    参考リンク
    Sublime Merge - Git Client, done Sublime : https://www.sublimemerge.com/
    Git - git-branch Documentation : https://git-scm.com/docs/git-branch
    Git - git-rebase Documentation : https://git-scm.com/docs/git-rebase
    (再演) detached HEADを理解して脱Git初⼼者を⽬指す⽅のためのGit⼊⾨勉強会 @サポー
    ターズCoLab - Speaker Deck : http://bit.ly/2DpZwga
    (再演)きれいなcommit, pull requestを知りたい/作りたい⽅のためのgit勉強会 - Speaker
    Deck : http://bit.ly/2SD90uT
    Githubで間違えてgit push -f origin masterしてしまった時の対応 - Qiita : https://
    qiita.com/awakia/items/52b5900e801c3bfbab04
    テキスト版:Gitの困り事何でも解決いたします 勉強会講師の経験有り ❗ 使い⽅から運⽤
    まで何でもどうぞ ❗ | ココナラ : https://coconala.com/services/642499
    ビデオ版:Gitの困り事解決いたします 勉強会講師の経験有り 使い⽅から運⽤まで何でもど
    うぞ! | ココナラ : https://coconala.com/services/839341
    勉強会講師も担当 ❗ 親切丁寧にGitの使い⽅教えます | タイムチケット : https://
    www.timeticket.jp/items/58703
    Git・GitHubに関する相談・レクチャー - ストアカ : https://www.street-academy.com/
    myclass/73592

    View Slide