09. git best practice - nephilim/js-git-kata GitHub Wiki

Git Best Practice

Branch-per-Freature

  • ์ฃผ์š” ์›์น™
    • feature๋Š” ๊ฐ€๋Šฅํ•˜๋ฉด atomicํ•˜๊ฒŒ(OCP๋ฅผ ์ง€์ผœ์„œ), ์ž‘๊ฒŒ ์ž‘์„ฑํ•œ๋‹ค.
      • feature ๋ธŒ๋žœ์น˜๋ฅผ ISSUE-023 ํ˜•ํƒœ๋กœ ์ด์Šˆ ๊ด€๋ฆฌ์ž์˜ ticket๊ณผ ํ”ํžˆ ์—ฐ๊ฒฐ์‹œํ‚จ๋‹ค.
      • dev master ๋“ฑ์— ์ง์ ‘ ์ปค๋ฐ‹ํ•˜์ง€ ์•Š๋Š”๋‹ค.
        • git flow์—์„œ๋Š” ๊ฐ€๋Šฅํ•˜๊ธดํ•˜๋‹ค.
    • integration
      • ์ตœ๋Œ€ํ•œ ์ž์ฃผ ์‹คํ–‰

      • git-show-branch

        • ๋ธŒ๋žœ์น˜๊ฐ€ ์–ด๋””์„œ ์™”๋Š”๊ฐ€? ํ˜„์žฌ ๋ธŒ๋žœ์น˜์˜ ๊ธฐ์› ์ถ”์ ์— ํŽธ๋ฆฌ

            ! [git] /Users/nephilim/.dotfiles/git/bin ์ •๋ฆฌ
             * [master] Merge branch 'shell': md2docx added
              ! [shell] shell: md2docx added
               ! [vim-plugin] vim: rnu(relative number unit) ์ œ๊ฑฐ
            ----
             -   [master] Merge branch 'shell': md2docx added
             *+  [shell] shell: md2docx added
             *+  [shell^] taskit: help message typo fixed
             *   [master^] zsh: JAVA_HOME libexec/javahome ์„ ์ด์šฉํ•˜์—ฌ ๊ฒฝ๋กœ ์„ค์ •
             *+  [shell~2] taskit: weekday(mon, tue, ...) based registration added
             *+  [shell~3] choojerk: push notification (via parse.io) added
             *+  [shell~4] choojerk: web crawling script for Google I/O
             *+  [shell~5] taskit: task list escape added
             *+  [shell~6] taskit: tast select & done menu added
             *+  [shell~7] taskit: tasklist selection&store menu
             *+  [shell~8] google tasks api๋ฅผ ์ด์šฉํ•œ task adder
             *+  [shell~9] dev command ์ˆ˜์ •
            +*   [git] /Users/nephilim/.dotfiles/git/bin ์ •๋ฆฌ
            +*+  [shell~10] git: git-track-branch ์ถ”๊ฐ€
            ---  [shell~11] Merge branch 'vim-plugin'
            +*++ [vim-plugin] vim: rnu(relative number unit) ์ œ๊ฑฐ
          
        • shell branch์—์„œ ์‹คํ–‰ ๊ฒฐ๊ณผ

          ! [git] /Users/nephilim/.dotfiles/git/bin ์ •๋ฆฌ ! [master] Merge branch 'shell': md2docx added * [shell] shell: md2docx added ! [vim-plugin] vim: rnu(relative number unit) ์ œ๊ฑฐ

          • [master] Merge branch 'shell': md2docx added +* [shell] shell: md2docx added +* [shell^] taskit: help message typo fixed
          • [master^] zsh: JAVA_HOME libexec/javahome ์„ ์ด์šฉํ•˜์—ฌ ๊ฒฝ๋กœ ์„ค์ • +* [shell2] taskit: weekday(mon, tue, ...) based registration added +* [shell3] choojerk: push notification (via parse.io) added +* [shell4] choojerk: web crawling script for Google I/O +* [shell5] taskit: task list escape added +* [shell6] taskit: tast select & done menu added +* [shell7] taskit: tasklist selection&store menu +* [shell8] google tasks api๋ฅผ ์ด์šฉํ•œ task adder +* [shell9] dev command ์ˆ˜์ • ++ [git] /Users/nephilim/.dotfiles/git/bin ์ •๋ฆฌ ++* [shell10] git: git-track-branch ์ถ”๊ฐ€ --- [shell11] Merge branch 'vim-plugin' ++*+ [vim-plugin] vim: rnu(relative number unit) ์ œ๊ฑฐ
      • --- ์ด์ „ ๋ผ์ธ(header)

        • ๊ฐ ๋ธŒ๋žœ์น˜์˜ ์ตœ๊ทผ commit ์š”์•ฝ
        • *์€ HEAD๋ฅผ ์˜๋ฏธ, ๋‚˜๋จธ์ง€๋Š” !
      • --- ์ดํ›„ ๋ผ์ธ

        • ๊ฐ ๋ธŒ๋žœ์น˜ ๋ณ„ ๋“ค์—ฌ์“ฐ๊ธฐ
        • ๊ฐ ์ปฌ๋Ÿผ์—๋Š” ํ•ด๋‹น ๋ธŒ๋žœ์น˜๊ฐ€ ๋„๋‹ฌ ๊ฐ€๋Šฅํ•œ์ง€ ์—ฌ๋ถ€๊ฐ€ ํ‘œ์‹œ๋œ๋‹ค.
        • - merge branch
        • + branch (other than head-branch)
        • * current branch

no-ff

  • ๋‘ ๊ฐœ์˜ ๋ธŒ๋žœ์น˜๋ฅผ ๋จธ์ง€ ํ›„
    • ํ•˜๋‚˜๋ฅผ ์ทจ์†Œํ•œ๋‹ค
    • no-ff๊ฐ€ ์•„๋‹ˆ๋ฉด ์ฃผ์š” ๋ธŒ๋žœ์น˜์— ๋“ค์–ด์™€ ์žˆ์–ด์„œ ์ œ๊ฑฐ๊ฐ€ ๋ฒˆ๊ฑฐ๋กญ๋‹ค
      • ๊ทธ๋ ‡์ง€ ์•Š๋‹ค. feature ํ—ค๋“œ๊ฐ€ ๋‚จ์•„์žˆ๋‹ค๋ฉด ํฐ ์ฐจ์ด๊ฐ€ ์žˆ์ง€๋Š” ์•Š๋‹ค

          * e294960 - (HEAD, master, feature-03) feature-03:01 added (36 minutes ago)
          | * ada416f - (feature-01) feature-01:03 added (46 minutes ago)
          | *   a54c138 - Merge branch 'master' into feature-01 (47 minutes ago)
          | |\
          | |/
          |/|
          * |   247ab63 - Merge branch 'feature-01' (50 minutes ago)
        
      • ์œ„ master ๋ธŒ๋žœ์น˜์—์„œ reset --hard HEAD^ ํ•ด๋„ feature-03์ด ๋‚จ์•„์žˆ๋‹ค.

back-merge

  • back-merge๋ฅผ ํ•˜์ง€์•Š๋Š”๋‹ค.

    • feature๊ฐ€ ์ถฉ๋ถ„ํžˆ ๋…๋ฆฝ์ ์ด์ง€ ์•Š๋‹ค๋Š” smell
    • cherry-pick์„ ๊ณ ๋ คํ•ด๋ณธ๋‹ค
    • feature
  • ์‚ฌ๋ก€

    • back-mergeํ•œ ์ด๋ ฅ์ด ์žˆ๋Š” feature-01์„ ์ œ๊ฑฐํ•˜๋ ค๋ฉด?

        *   27ad9e1 - (HEAD, master) Merge branch 'feature-01' (10 minutes ago)
        |\
        | * ada416f - (feature-01) feature-01:03 added (21 minutes ago)
        | *   a54c138 - Merge branch 'master' into feature-01 (22 minutes ago)
        | |\
        * | | e294960 - (feature-03) feature-03:01 added (11 minutes ago)
        | |/
        |/|
        * |   247ab63 - Merge branch 'feature-01' (25 minutes ago)
        |\ \
        | |/
        | * 08f01db - feature-01:02 added (46 minutes ago)
        | * 40577b5 - feature-01:01 added (47 minutes ago)
        * |   1f3d63c - Merge branch 'feature-02' (35 minutes ago)
        |\ \
        | |/
        |/|
        | * 9140660 - (feature-02) feature-02:01 added (36 minutes ago)
        |/
        * 6f026d1 - initial commit (53 minutes ago)
      
    • merge ์ทจ์†Œ์— ๋Œ€ํ•œ ์ฃผ์š” ๋ฒ•์น™(03์˜ ์žฌํ™•์ธ)

      • ๋ˆ„๊ตฌ๊ฐ€์—๊ฒŒ merge ๋‹นํ•œ commit object๋Š” ์‰ฝ๊ฒŒ ์ทจ์†Œ๊ฐ€ ๋˜์ง€ ์•Š๋Š”๋‹ค.
        • ์ƒ๋Œ€์˜ ๋‚ด์šฉ์— ์˜ํ–ฅ์„ ์ฃผ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒ๋Œ€ ๋˜ํ•œ ์ž‘์—…์„ ํ•ด์•ผํ•œ๋‹ค.
      • ๋ˆ„๊ตฐ๊ฐ€๋ฅผ mergeํ•œ commit object๋Š” ์ทจ์†Œํ•  ์ˆ˜ ์žˆ๋‹ค.
        • ์ƒ๋Œ€์˜ ๋‚ด์šฉ์— ์˜ํ–ฅ์„ ์ค€ ๊ฑด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— merge commit์„ ์ทจ์†Œํ•˜๋ฉด ๋œ๋‹ค.
    • ํ•ด๋ณด๋‹ˆ

      • back-mergeํ›„ feature์˜ ๋‚ด์šฉ์— ์ง‘์ค‘ํ•˜์ง€ ์•Š๊ณ  master๋ธŒ๋žœ์น˜์˜ ๋‚ด์šฉ์„ ์ˆ˜์ •ํ•˜์—ฌ feature์— ์œ ์ง€ํ•œ๋‹ค๋ฉด ํ™•์‹คํžˆ ์ œ๊ฑฐ๊ฐ€ ์•ˆ๋  ๊ฒƒ์ž„
      • ์›๊ฒฉ์— ํ”ผํ•ด๋ฅผ ์ค„๊นŒ?
        • rebase ์ž‘์—…์€ back-merge๋ฅผ ํ•˜์ง€ ์•Š์•„๋„ ๊ฒฐ๊ตญ ์œ ์‚ฌ
        • TODO: revert๋กœ merge ์ทจ์†Œ ์ž‘์—… ์‹œ๋„
  • share

    • integration ์‹œ conflict๋Š” ๋„ˆ๋ฌด๋‚˜๋„ ์ž์—ฐ์Šค๋Ÿฌ์šด ํ˜„์ƒ(a fact of life)
    • fetch, pull, push๋ฅผ hookingํ•˜์—ฌ
    • rerere
      • reuse recorded resolution
      • .git/rr-cache์— ์ €์žฅ๋จ
      • ์ถฉ๋Œ ์‹œ ์ฒ˜๋ฆฌํ•œ (์›๋ณธ) ๋‚ด์šฉ์„ ๊ธฐ๋กํ•จ

git flow์™€์˜ ์ฐจ์ด

  • git flow์˜ ๊ฒฝ์šฐ
    1. dev branch์— ์ปค๋ฐ‹์ด ๊ฐ€๋Šฅํ•จ
    2. feature๋กœ back-merge๋ฅผ ํ—ˆ๋ฝํ•จ

DAG

  • directed acyclic graph

practice

back-merge

  • cherry-pick
    • A reasonable middle-ground is cherry-picking.
    • ์ด์œ :
      • ๋‹ค๋ฅธ feature๊ฐ€ back-merge์‹œ ํ˜ผํ•ฉ๋˜์–ด ์œ ์ž…๋  ์ˆ˜ ์žˆ๋‹ค.
      • ์œ ์ž… ํ›„ ์ˆ˜์ •๊นŒ์ง€ ๋˜์—ˆ๋‹ค๋ฉด ๋”์šฑ ์ตœ์•…

our own process

  1. feature๋Š” ๋…๋ฆฝ์ ์œผ๋กœ, dev๋ฅผ ์ง„ํ–‰ ์ค‘์ธ feature์— ๋ฐ˜์˜ํ•˜์ง€ ์•Š๋Š”๋‹ค. ํŠนํžˆ, back-merge๋Š” ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๊ตณ์ด ํ•„์š”ํ•˜๋‹ค๋ฉด dev์˜ ์›ํ•˜๋Š” commit์„ cherry-pick ํ•œ๋‹ค. ๋„์‹์œผ๋กœ ๋‚˜ํƒ€๋‚ด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. git merge --no-ff ์‚ฌ์šฉ์— ์œ ์˜ํ•˜์ž.

     d-------------d(dev)
      \           / \    
       f----f----f   f--f(feature)
    
     d-------------d(dev)
      \           /  
       f----f----f---f--f(feature)
    

    ์ฐธ๊ณ ๋กœ git-flow ๋ชจ๋ธ์—์„œ๋Š” ๋‹ค์Œ์„ ํ—ˆ์šฉํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์œ„์˜ ํ˜•ํƒœ๋กœ ์œ ์ง€๋˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

     d---d1---d2---d(dev)
      \            / \ 
       f-----f----f   f--f(feature)
    

    back-merge๊ฐ€ ํ—ˆ์šฉ๋˜๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ tree๊ฐ€ ๋œ๋‹ค. ์ด๋Ÿฐ ์‹์œผ๋กœ feature๊ฐ€ ๊ด€๋ฆฌ๋˜๋ฉด, ํ–ฅํ›„ ํŠน์ • feature๋ฅผ ์ œ๊ฑฐํ•  ๊ฒฝ์šฐ ์ž‘์—…์ด ๋งค์šฐ ๊นŒ๋‹ค๋กœ์›Œ ์ง„๋‹ค. back-merge ํ›„ feature์— dev์˜ ๋‚ด์šฉ์ด ๋ฐ˜์˜๋˜๋ฏ€๋กœ dev์—์„œ ์ œ๊ฑฐ๋ฅผ ํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค.

     d---d1---d2---d(dev)
      \            / \ 
       f-----f----f---f---f(feature)
    

    ๋‹ค๋ฅธ ์ด๋“ค์ด feature๋ฅผ ์ž‘์—…ํ•˜๊ณ  ์žˆ์ง€ ์•Š๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๋กœ rebase๋„ ๊ฐ€๋Šฅํ•˜๊ฒ ์ง€๋งŒ, ๊ถŒ๊ณ ํ•˜์ง€ ์•Š๋Š”๋‹ค.

        d--d--d--d(1.6, master)
            \
             f--f--f (feature)
    
  2. feature ๋ธŒ๋žœ์น˜ ๋ช…

    • ๊ด€๋ จ issue/ticket์ด ์žˆ๋‹ค๋ฉด ํ•ด๋‹น id๋ฅผ [id] commit message์˜ ํ˜•ํƒœ๋กœ ๊ธฐ์ˆ 
    • ๊ณต๋ฐฑ์ด ์—†์Œ(- ์œผ๋กœ ๋Œ€์ฒด)
  3. commit message

dangling object

  • ๊ฐœ๋…

    • dangling blob๊ณผ dangling commit
  • ์‹ค์Šต: check dangling object

    • TODO: ์˜ˆ์ œ git commit --amendํ›„ unreachable object๋ฅผ ํ™•์ธํ•˜๋ฉด ์ด์ „ commit ํ™•์ธ ๊ฐ€๋Šฅ

    • TODO: ๋ธŒ๋žœ์น˜ ์‚ญ์ œ

        * 9e820d4 - (HEAD, master) sample markdown document added (4 seconds ago)
        | * d9fe5bf - (develop) chapter-06 early translate: done (15 minutes ago)
        | * 984957a - sample formmated-markdown document added (71 minutes ago)
        |/
        * 878d836 - .git ignore added (73 minutes ago)
        * 311f263 - (origin/master, origin/HEAD) Initial commit (2 weeks ago)
      
  • git fsck

    • Verifies the connectivity and validity of the objects in the database
    • ๊ทธ๋ƒฅ fsck ํ•˜๋ฉด ์ง€์›Œ์ง„ ๋ธŒ๋žœ์น˜์˜ commit object๊ฐ€ ๋‚˜์˜ค์ง€ ์•Š๋Š”๋‹ค.
      • --no-reflogs ๋‚ด์šฉ ์ฐธ๊ณ 
    • --no-reflogs
      • reflog์—์„œ๋งŒ ๋„๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ๋„๋‹ฌ๊ฐ€๋Šฅ์ด๋ผ ๊ณ ๋ คํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜๋ฏธ
        • TODO: ์˜ˆ์ œ git commit --amendํ›„ unreachable object๋ฅผ ํ™•์ธํ•˜๋ฉด ์ด์ „ commit ํ™•์ธ ๊ฐ€๋Šฅ
    • --unreachable
      • reference ๋…ธ๋“œ(reflogํฌํ•จ)์—์„œ ๋„๋‹ฌํ•  ์ˆ˜ ์—†์Œ์„ ์˜๋ฏธ
      • unreachable object์˜ ํ™•์ธ
        • --no-reflogs์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ์‚ฌ๋ผ์ง„ ๋ธŒ๋žœ์น˜๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค

            > git fsck --unreachable --no-reflogs
            Checking object directories: 100% (256/256), done.
            unreachable blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
            unreachable commit 984957a17d27b0984f0b390c8a50f639698f4d7f
            unreachable commit d9fe5bf153fb37e14698c76a83b8c2e93ce2f1cf
          
    • --dangling
      • ๋งŒ๋“ค์–ด์ง€๊ธฐ๋Š” ํ–ˆ์œผ๋‚˜, ์ง์ ‘ ์‚ฌ์šฉ๋œ(์ฐธ์กฐ๋œ) ์ ์ด ์—†๋Š” object

          > git fsck --dangling --no-reflogs
          Checking object directories: 100% (256/256), done.
          dangling blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
          dangling commit d9fe5bf153fb37e14698c76a83b8c2e93ce2f1cf
        
      • 984957a17d27b0984f0b390c8a50f639698f4d7f์˜ ๊ฒฝ์šฐ ์ž์‹์ด ์žˆ์œผ๋ฏ€๋กœ dangling์—์„œ ์ œ์™ธ๋œ๋‹ค

    • --full
      • .git/object ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ packed object, GIT_ALTERNATE_OBJECT_DIRECTORIES๋ฅผ ๋ชจ๋‘ ๊ฒ€์ƒ‰ํ•จ
  • git gc

    • housekeeping tasks
      • compressing file revisions
      • removing unreachable objects
        • gc ๋Œ€์ƒ์€ dangling object๊ฐ€ ์•„๋‹˜
    • --aggresive
      • aggresively compress
      • ๋””์Šคํฌ ๊ณต๊ฐ„์— ์—ฌ์œ ๊ฐ€ ์žˆ์–ด๋„ ์••์ถ•์„ ์ˆ˜ํ–‰
    • --auto
      • gc.auto ๊ฐœ์ˆ˜๋ฅผ ๋„˜๋Š” loose object๋Š” repack
    • git gc --prune=now
      • now ์ด์ „์˜ loose object ์‚ญ์ œ
        • defalut: 2์ฃผ๋กœ ์„ค์ •๋˜์–ด ์žˆ์Œ
      • --no-prune: ์••์ถ•๋งŒ
    • config
      • gc.pruneexpire
      • gc.reflogexpire
      • gc.reflogexpireunreachable
    • ๋‹ค๋ฅธ git command์—์„œ ํ™œ์šฉํ•จ
      • gc.auto ์„ค์ •
        • git config --global gc.auto 0
  • git prune

    • remove unreachable objects
  • git reflog

    • git reflog expire --expire=now --all
  • exampleA

      git reflog expire --expire=now --all 
      # will now report unreachable 
      git reflog
      # nothing to print out 
      git fsck --unreachable 
      # will now actually delete objects 
      git prune -v 
      # gives "bad object ..." 
      git show $dead_commit 
    

notes