きれいなcommit, pull requestを知りたい/作りたい方のためのgit勉強会

きれいなcommit, pull requestを知りたい/作りたい方のためのgit勉強会

2018年3月27日にSupporterZ CoLabで行われたgit勉強会の資料です。

1a74617b91d2757b839b9cf3614648ce?s=128

Tomohiro Imaizumi

March 27, 2018
Tweet

Transcript

  1. 9.

    そもそもcommit logとは ❓ commit: 変更の塊 の log: 履歴 002 001

    003 + .green { + color: green; + } * 001: Committed at Jan 1st, 2018 | message: green classを追加 * 002: Committed at Feb 2nd, 2018…
  2. 17.

    可読性 (readability) commit message の読みやすさ 論理性 (logicality) 変更内容が 意味的に まとまっているか

    「きれいなcommit」を構成する3要素 commitの 粒度の⼩ささ 原⼦性 (atomicity)
  3. 18.

    論理性(logicality) 原⼦性(atomicity) commit (ϝοηʔδ) commitྻ Pull Request ߦࠩ෼ ộ 可読性(readability)

    それぞれレイヤーが異なる Pull Requestの 構成要素 下の層での出来は 上の層での出来に影響 ʴ (มߋ܈)
  4. 21.

    > fix width and height Project A の commit message

    ‣ 何のwidth/heightだろう❓(差分を⾒て分かれば良いが…) ‣ fixとは「固定」という意味❓それとも「修正」の意味❓ ‣ 何がどうダメだったんだろう❓(PRコメントもない…) > add / Update ‣ 何をadd/Updateしたんだろう❓ ‣ どうしてそうしたのだろう❓ ‣ػೳݟͨ໨తʹ͸Կ͕มΘͬͨͷͩΖ͏❓ commit messageからは変更概要が⾒えづらい
  5. 22.

    > Facebook登録時に学校情報がない時に デフォルト値を送信しない Project B の commit message ‣ おそらくAPIを叩く時のパラメータを変えたんだな

    ‣ でもなぜそんな仕様に❓                 →PRコメントに仕様と関連issueへのリンクが記載 > 実際の職業を表示するセルの テキスト色を濃くする ‣ おそらく職業表⽰画⾯のUIの変更だな ‣ 理由は❓→PRコメントにデザインへのリンク commit messageから変更概要が⾒える
  6. 33.

    imaizume@mac ~/works/project (master) $ git log —oneline —graph -1 *

    001 - (HEAD -> master) Update order and theme of header nav アイテムの順序変更と テーマ更新が 同じcommitに含まれている commitをrevertすると アイテムの順序だけなく テーマまで戻ってしまう ではどうすればよかったか❓
  7. 34.

    原⼦性を上げてみる imaizume@mac ~/works/project (master) $ git log —oneline —graph -4

    * 004 - (HEAD -> master) Reorder header nav item in HTML * 003 - Add class switch with jQuery for header navigation to JavaScript * 002 - Add class for header navigation to CSS * 001 - Add section for header navigation to HTML 各ファイルでの変更を それぞれ別のcommitに 当初の⽬的は達成されたようだが… テーマを戻したくなったら 3 commit分のrevertが必要 「不適切に」原⼦性が⾼い
  8. 35.

    ✨ 意味的にまとまる範囲で原⼦性を向上 imaizume@mac ~/works/project (master) $ git log —oneline —graph

    -4 * 004 - (HEAD -> master) Reorder header nav item in HTML * 003 - Update header navigation themes * 002 - Enable SP header button appending new selector to HTML and JS * 001 - Use background-image on div instead of img element 意味的にまとまる範囲で commitへまとめた ⼩さなcommitを意識しつつ、 意味的にまとまっていると 戻す時もまとめて戻せる 「ファイルの粒度」ではなく 「意味の粒度」にまとめる
  9. 39.

    可読性 (readability) commit message の読みやすさ 論理性 (logicality) 変更内容が 意味的に まとまっているか

    再掲:「きれいなcommit」の構成要素 commitの 粒度の⼩ささ 原⼦性 (atomicity)
  10. 43.

    具体性がないメッセージ例 ‣ Fix bugs ‣ Add new class ‣ 直した

    ⭕具体性があるメッセージ例 ‣ ヘッダーナビゲーションのボタンタップが正しく反 応するようjQueryのセレクタ名を修正 ‣ WebViewへのリンクを可変にするため HogeViewControllerのコンストラクタにURLパラメー タを追加 5W1Hで指⽰語や曖昧な⾔葉を使わない
  11. 44.

    ⼈間的意味のないメッセージ例 ‣ addParamsメソッドの引数を0からに1変更 ‣ OLD_CONST1, OLD_CONST2を削除 ‣ MemberModelにsuccessフィールドを追加 ⭕⼈間的意味のあるメッセージ例 ‣

    addParamsに間違った引数(0)が渡されていたので正 しい状態値(1)を渡すように修正 ‣ ver2.0で廃止した登録関連の古い定数を削除 ‣ API取得が正常に完了したかを保持できるよう MemberModelに新規のフィールドを追加 変更の詳細は差分を⾒れば分かるので ⼈間的な意味を書くようにする
  12. 45.

    + let tmp = Foo.bar(baz: Qux.quux) + let httpReq =

    + APIManger.getRequest(of: Endpoint.member) →コメントで補⾜が必要 差分を⾒れば⼗分意図が伝わる 過度にmessageの具体性を上げる必要なし 補⾜1 ⼩さい差分で叙述的なコードなら コードがcommit message として機能する場合も (参考: リーダブルコード)
  13. 47.

    その他気をつけると良い点 ‣ 詳細な伝達事項がある場合 (ほとんどない) ‣ imaizumeは、基本的に1 line messageで派 GitHubやRedmineなどのIssue番号を⼊れる ‣

    GitHub上でissueからもコミットが参照できる ‣ 「詳細はISSUEを⾒て」というメッセージに ‣ closeなどのキーワードでISSUEを操作可能 ✍必要なら複数⾏書く
  14. 50.

    みなさんはgit addする時 どんなコマンドを叩いていますか imaizume@mac ~/works/pretty-git (master) $ git status On

    branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: index.html modified: script.js modified: style.css no changes added to commit (use "git add" and/or "git commit -a") imaizume@mac ~/works/pretty-git (master) $ git add index.html git addの最小単位はファイルだと思っていませんか??
  15. 52.

    git addの最⼩単位は1⾏ ファイル内の変更を⾏単位でstagingへ static var f… +func xyz() {… …

    -class Abc() {… - } +class Xyz() {… +} … -static let PQ =… git add -p git add 001 002 003 全差分をstagingへ 差分を区間(hunk)毎に stagingへ 001
  16. 53.

    imaizume@mac ~/dots (master) $ git add -p diff --git a/notfy/Cell/NotificationsTableViewCell.swift

    b/notfy/Cell/ NotificationsTableViewCell.swift index 813e59f..b50e7ef 100644 --- a/notfy/Cell/NotificationsTableViewCell.swift +++ b/notfy/Cell/NotificationsTableViewCell.swift @@ -49,6 +49,7 @@ struct Notification { var memo: String } +protocol TriggerContract { + func toString() -> String +} extension Notification: TriggerContract { Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? git add -p 後の画⾯ 各hunkでの操作を聞かれるれるので それぞれで必要なコマンドを実⾏ ( ? でヘルプを表⽰)
  17. 54.

    add -p の各コマンド説明 (y/n) +hunk1 … +hunk2 … -hunk3 y:

    hunkをstageする y n: hunkをstageしない +hunk1 … +hunk2 … -hunk3 n ‣hunk1のstage確定 ‣h2へ移動 ‣hunk1の⾮stage確定 ‣h2へ移動 commit対象 に含む commit対象 に含まない
  18. 55.

    add -p の各コマンド説明 (q/a) +hunk1 … +hunk2 … -hunk3 q:

    以降のhunkへの 操作をキャンセル q a: 以降の全hunkを ステージングにadd +hunk1 … +hunk2 … -hunk3 a ‣hunk1以降の全hunk の⾮stageが確定 ‣コマンド終了 ‣hunk1以降の全hunk のstageが確定 ‣コマンド終了
  19. 56.

    add -p の各コマンド説明 (j/J/k/K) +hunk1 … +hunk2 … -hunk3 k:

    現在のhunkをSKIP 前の未確定hunkへ K: 現在のhunkをSKIP 前の⾮stage hunkへ +hunk1 … +hunk2 … -hunk3 ‣hunk3は保留 ‣hunk2はSKIP ‣hunk1に移動 ‣hunk3は保留 ‣hunk2に移動 (再度stageを選択可) hunk2は 非stage確定済 hunk2は 非stage確定済 k K
  20. 57.

    s: 現在のhunkをさらに⼩さく分割 (できる場合) <body> <div id="main" class="main"> <h1>きれいなcommit logを積む</h1> +

    <h2>可読性</h2> <div class="circle"></div> + <h2>原子性</h2> </div> + <h2>論理性</h2> <script src="./jquery-3.3.1.min.js"/> <script src="./script.js"> </body> Stage this hunk [y,n,q,a,d,/,s,e,?]? s Split into 3 hunks. @@ -8,4 +8,5 @@ <body> <div id="main" class="main"> <h1>きれいなcommit logを積む</h1> + <h2>可読性</h2> <div class="circle"></div> Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? 自動判定されたhunkは1個 3個の小hunkへ add -p の各コマンド説明 (s) ※hunkと⾃動判定されるには ⼀定の⾏数以上の空き(未変更⾏)が必要
  21. 58.

    e: ⼿動でhunkを編集する <body> <div id="main" class="main"> <h1>きれいなcommit logを積む</h1> + <h2>可読性</h2>

    + <h2>原子性</h2> + <h2>論理性</h2> <div class="circle"></div> </div> <script src="./jquery-3.3.1.min.js"/> Stage this hunk [y,n,q,a,d,/,e,?]? e 連続した行に 差分がある add -p の各コマンド説明 (e) 1 # Manual hunk edit mode -- see bottom for a quick guide. 2 @@ -8,6 +8,9 @@ 3 <body> 4 <div id="main" class="main"> 5 <h1>きれいなcommit logを積む</h1> 6 + <h2>可読性</h2> 7 <div class="circle"></div> 8 </div> 9 <script src="./jquery-3.3.1.min.js"/> 10 # --- 不要な追加差分は削除 不要な削除差分は行頭を空白に viが起動
  22. 62.

    ✨ 意味的にまとまった変更をcommitにしよう imaizume@mac ~/works/project (master) $ git log —oneline —graph

    -4 * 004 - (HEAD -> master) Reorder header nav item in HTML * 003 - Update header navigation themes * 002 - Enable SP header button appending new selector to HTML and JS * 001 - Use background-image on div instead of img element ❌複数の意味を持つ変更を1commitに 1⾏/ファイル毎に変更を1commitに ⭕ 意味の最⼩粒度で1commitに 頑張りましょう
  23. 65.

    rebase -i で commit log を再編集 =結合/分割/書き換え/順序⼊れ替えが可能 001 002 003

    004 001* 002* 005 > Fix bugs > Remove methods 001* 002A 002B 005* 書き換え 結合 分割 順序⼊れ替え
  24. 66.

    補⾜: rebase コマンドとは❓ →分岐元からの差分をfast-fowardでマージ master 002 dev 004 003 001

    これを「対話的」に⾏うのが -i オプション 002 dev 004 003 001 master > git rebase master
  25. 67.

    imaizume@mac ~/dots (master) $ git rebase -i HEAD~2 pick e263636

    vimにJqコマンドを追加 pick 2b9c492 write !pbcopyとsortコマンドのキーマップを追加 # Rebase 59d63fc..2b9c492 onto 59d63fc (2 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out git rebase -i での画面説明 どのcommitまで遡るか vimが起動するので ⾏頭の単語と順序を編集後 保存して閉じる 各サブコマンド
  26. 68.

    rebase -i の各コマンド説明 (pick/reword/drop/順序入れ替え) pick: 何もしない (commitを残す) reword: commit messageを書き換え

    001 001 001* > Fix bugs > Remove methods drop: commitを削除 001 (commitの順序⼊れ替え) 001 002 001* 002*
  27. 70.

    editコマンドでのcommitの分割方法 001 002 003 HEAD 001 002 003 HEAD master

    master 分割したい 001 002 003 HEAD master 002の差分が 未commit状態に 001 002B 003* HEAD master 002A rebase -i 001 && (edit 002) reset HEAD~1 add -p && rebase —continue addとcommitを やり直し可能!
  28. 71.

    補⾜ 変更されたcommitはhashが変わる⚠ =リモートリポジトリにPush済みのcommitを rebase -i した場合Conflictが起きます 001 002 003 master

    origin/master rebase 前 001 002 003 001 002 003 master origin/master rebase 後 001 002* 003* (⾃⼰責任でforce push OR 別ブランチでPUSH)
  29. 73.

    まとめ: 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
  30. 75.

    きれいな Pull Request を作るには❓ 各commitだけではなく Pull Request全体も俯瞰する ‣ commit log

    を読み返してやったことを思い出せるか ‣ 順序やcommit粒度は適切か ‣ トータルのcommit数や差分が⼤きすぎないか ‣ Pull Requestのコメントは適切か
  31. 76.

    良いcommitやPRの先にあるもの commitྻ Pull Request ߦࠩ෼ ộ commit (มߋ܈+ίϝϯτ) ίʔυ Issue

    খλεΫ େλεΫ ϓϩδΣΫτ Ϗδϣϯ αʔϏε 良いコードが書ける 良いcommitが積める 良いPRが作れる 良いISSUEが⽴てられる 良いタスクの分割ができる 良い仕事ができる‼
  32. 80.

    git commitは「習慣」です ⼼ が変われば 態度が変わる。 態度 が変われば ⾏動 が変わる。 ⾏動

    が変われば 習慣 が変わる。 習慣 が変われば ⼈格 が変わる。 ⼈格 が変われば 運命 が変わる。 運命 が変われば ⼈⽣ が変わる。 (ヒンズー教の教えより) 良いcommitを習慣にしましょう (悪い習慣は変えましょう)
  33. 82.

    Q&Aコーナー(とありそうな質問) Q. 今⽇のやり⽅を常⽇頃から守らないとですよね❓ A. これはimaizume⼀個⼈の考え⽅・やり⽅、⽬的を⾒失なわぬように。 ⾒返す必要のないcommitを無駄にきれいにする必要はありません。 Q. 正直commit messageを考える余裕がありません… A.

    ローンチ時やリリース優先時等はやむを得ないでしょう。しかしメッ セージを考える余裕もない状態が⽇常的に続くなら転職をお薦めします。 Q. commit messageは英語にすべきですか❓ A. 基本的には⽇本語の⽅が正確に意図の伝達ができ把握もしやすいので、 ⽀障がなければ⽇本語を推奨します。commit messageを読むの誰で、何 のために書くのかを考えて選びましょう。
  34. 83.

    参考記事/リンク ‣ 横着で神経質な私とあなたに贈るgit add -p:
 https://qiita.com/crifff/items/1abf08bca4ce51db4775 ‣ gitのコミットの歴史を改変する(git rebase) 1

    / 2 · けんごのお屋敷:
 http://tkengo.github.io/blog/2013/05/16/git-rebase-reference/ ‣ detached HEADを理解して脱Git初⼼者を⽬指す⽅のためのGit⼊⾨勉強会:
 https://supporterzcolab.com/event/264/ ‣ Git - リベース:
 https://git-scm.com/book/ja/v1/Git-のブランチ機能-リベース ‣ jonas/tig: https://github.com/jonas/tig ‣ peco と alias -g で git に便利⾰命おきた:
 https://qiita.com/Kuniwak/items/b711d6c3e402dfd9356b ‣ Pro Git: https://git-scm.com/book/ja/v2
  35. 84.