The Nitty Gitty

The Nitty Gitty

Git is not complicated, but it is complex (and confusing). In this talk, Daniel explains the basic building blocks of git: commits, blobs, trees and refs. He then builds on this foundation, past branches and merges to remotes and rebases in an attempt to demystify the tool we all rely on.

Presented at Async Brighton meetup 05/09/2019

https://asyncjs.com/nitty-gitty/

1a93f6606abdcf0ec6a850df9e4b830d?s=128

Daniel van Berzon

September 05, 2019
Tweet

Transcript

  1. Daniel van Berzon @ocastahq ocasta.com @dvberzon vanberzon.com

  2. None
  3. Git has a lot of commands! > git commit >

    git checkout > git pull > git branch -D > git remote add > git rebase > git reflog > git merge —-blanket
  4. Git has a lot of commands! > git commit >

    git checkout > git pull > git branch -D > git remote add > git rebase > git reflog > git merge —-blanket > git quiltimport
  5. • This talk is not a tutorial • I am

    not an expert • We can not cover everything
  6. This is a car. Passenger What kind of users does

    a car have?
  7. Passenger

  8. Driver

  9. Mechanic

  10. Project manager Developer Lead dev

  11. Git is not a car.

  12. Git is not a car... it's a skateboard

  13. Git is ... Complicated ? Confusing Complex

  14. Language Window

  15. Climb through the window Clean the window Polysemy

  16. Polysemy is a paper ... that prints papers on paper

  17. Git is riddled with polysemy Commit Commit = Snapshot Commit

    = Diff
  18. Checkout ...a book from a library • Check out a

    file • File is locked • Only you can change it • Check in file when finished
  19. checkout • Move onto a branch • Start a new

    branch • Temporarily move on to a commit • Remove local changes to a file > git checkout mybranch > git checkout -b mybranch > git checkout 5bd33a3b > git checkout index.html
  20. Demystify Building blocks Branch model History Cool tricks

  21. > git init

  22. Basics Git repository Working directory Index index.html css styles.css index.html

    css styles.css index.html > git add styles.css index.html css styles.css > git commit
  23. Building blocks

  24. Blob Tree Ref Commit Object model

  25. !Blob Binary Long Object mr-blobby.jpg 1111111111011000111111111110000000000000000100 0001001010010001100100100101000110000000000000 0001000000010000000000000000000000010000000000 0000010000000000000000111111111101101100000000 1000010000000000000001010000001100000100000010

    0000000110000001110000100000000101000001010000 1000000001100000010100000101000001010000011000 0001110000010100000101000001110000010100000111 0000010100000101000001110000010100000101000001 0100000111000010000000011100000111000001110000 0111000001110000011100001010000100000000101100 0001110000100000001110000010010000011100000111 0000110100010101000011010000111000010001000100 0100010011000100110001001100000111000010110001 0110000110000001011000010010000110000001000000 0100100001001100010010000000010000010100000101 0000010100001000000001110000100000001111000010 0100001001000011110001001000001101000011010000 1101000100100001001000010010000100100001001000 0100100001001000010010000100100001001000010010 0001001000010010000100100001001000010010000100 1000010010000100100001001000010010000100100001 0010000100100001001000010010000100100001001000 0100100001001000010010000100100001001000010010 0001001000010010000100100001001000010010000100 1000010010000100100001001000010010000100100001 0010000100100001001000010010000100101111111111 0000000000000000010001000010000000001011010000 0000010100000000000000110000000100100010000000
  26. !Blob Binary Long Object mr-blobby.jpg index.html 1111000010000101100100011011110110001101110100 0111100101110000011001010010000001101000011101 0001101101011011000011111000001010000010100011 1100011010000111010001101101011011000010000001

    1011000110000101101110011001110011110100100010 0110010101101110001000100011111000001010001111 0001101000011001010110000101100100001111100000 1010001000000010000000111100011011010110010101 1101000110000100100000011000110110100001100001 0111001001110011011001010111010000111101001000 1001110101011101000110011000101101001110000010 0010001111100000101000100000001000000011110001 1101000110100101110100011011000110010100111110 0100000101110011011110010110111001100011001000 0001000111011010010111010000100000010101000110 0001011011000110101100111100001011110111010001 1010010111010001101100011001010011111000001010 0010000000100000001111000110110101100101011101 0001100001001000000110111001100001011011010110 0101001111010010001001100100011001010111001101 1000110111001001101001011100000111010001101001 0110111101101110001000100010000001100011011011 1101101110011101000110010101101110011101000011 1101001000100100000101110011011110010110111001 1000110010000001100111011010010111010000100000 0111010001100001011011000110101100100010001111 1000001010001000000010000000111100011011010110 0101011101000110000100100000011011100110000101 1011010110010100111101001000100110000101110101
  27. 88d4d9db7773a672280c5dfb085689041f0e9a70 14b564ced10ef9ef0e741718d60ac1966d6913c0 SHA hash !Blob

  28. Hello world 11010000 11001010 11011000 11011000 11011110 01000000 11101110 11011110

    11100100 11011000 11001000 SHA 22596363b3de40b06f98 1fb85d82312e8c0ed511 SHA
  29. Hello world 11010000 11001010 11011000 11011000 11011110 01000000 11101110 11011110

    11100100 11011000 11001000 11010000 11001010 11011000 11011000 11011110 01000000 11101110 11011110 11100100 11011000 11001000 00100001 Hello world! SHA 22596363b3de40b06f98 1fb85d82312e8c0ed511 430ce34d020724ed75a1 96dfc2ad67c77772d169 ≠ SHA SHA
  30. • Git uses SHA hash as a unique ID for

    a blob • If a file changes, git stores a new blob with a new ID • SHA hash is uniquely determined by file contents: - Git can easily tell if a file has changed - Git will only store a file version once - Avoids ID clashes !Blob
  31. • Represents a single folder in the project file system

    • Also associated with an SHA ID • Has an entry for each file and subfolder: • Each entry has: " Tree - Name (index.html) - Type (blob or tree) - SHA ID
  32. " Tree blob a0423896973644771497bdc03eb99d5281615b51 index.html tree aaa96ced2d9a1c8e72c56b253a0e2fe78393feb7 css aaa96ced2d9a1c8e72c56b253a0e2fe78393feb7 blob

    790cce91278c3ad02f160faa6e1e61ca147a5c3a styles.css " ad5a762c172647d211a0881b8d9e98d38edc1de9 " index.html css styles.css
  33. " Tree aaa96ced2d9a1c8e72c56b253a0e2fe78393feb7 blob 790cce91278c3ad02f160faa6e1e61ca147a5c3a styles.css " " index.html css

    styles.css blob afc501a4a6ab0a7a229f31d05a7e843b9cbc22e5 index.html tree aaa96ced2d9a1c8e72c56b253a0e2fe78393feb7 css 95c0282573633eb230f5064039e6b359e05e8752
  34. " Tree aaa96ced2d9a1c8e72c56b253a0e2fe78393feb7 blob 790cce91278c3ad02f160faa6e1e61ca147a5c3a styles.css " " css styles.css

    about.html blob afc501a4a6ab0a7a229f31d05a7e843b9cbc22e5 about.html tree aaa96ced2d9a1c8e72c56b253a0e2fe78393feb7 css 553ae7da92f5505a92bbb8c9d47be76ab9f65bc2
  35. • Commit is a snapshot of file system • Commit

    points project root tree • Commit meta-data: - SHA ID - Author, committer and date - A commit message - Parent commit ☄ Commit
  36. • Store a new blob for the new version of

    index.hml • Store a new tree for the project root • Store a commit pointing to the new root tree ☄ Commit Index.html css styles.css tree be5b6a45346870a56564ed2652bc51c5f48e1b59 parent 343e4048d816fa663b56ff5021f2679018381b8d author Daniel van Berzon <dvberzon@gmail.com> 1564416292 +0200 committer Daniel van Berzon <dvberzon@gmail.com> 1564416292 +0200 Updating index.html with new banner
  37. $ Ref • Points to a commit • Has a

    meaningful name • Two types: % Tag & Branch Fixed to the commit Updates to latest commit
  38. % Tag a a b c d $ Ref %

    v2.0
  39. % Tag a a b c d e f $

    Ref % v2.0
  40. % Tag a a b c d & Branch a

    a b c d e f $ Ref % v2.0 & my-feature
  41. % Tag a a b c d & Branch a

    a b c d e f e f $ Ref % v2.0 & my-feature
  42. Thats it for data! ! Blob " Tree ☄ Commit

    $ Ref > commands
  43. Branch Model

  44. • Points to commit • Each commit has a parent

    • Branch represents a linear history & Branch & my-feature
  45. • Branches are lightweight. Make as many as you like

    • Default branch is master • Create a branch • Move onto a branch • (Create and move) & Branch > git checkout mybranch > git branch mybranch > git checkout -b mybranch
  46. • Current position • Normally points to a branch •

    Checked out onto that branch • Possible to point directly to a commit ' HEAD "detached HEAD"
  47. & Branch > git init > git commit a &

    master '
  48. & Branch > git init > git commit > git

    commit > git commit b a c & master '
  49. & Branch > git init > git commit > git

    commit > git commit > git branch mybranch b a c & mybranch & master '
  50. & Branch > git init > git commit > git

    commit > git commit > git branch mybranch > git checkout mybranch b a c & mybranch & master '
  51. & Branch > git init > git commit > git

    commit > git commit > git branch mybranch > git checkout mybranch > git commit > git commit b a c d e & mybranch & master '
  52. & Branch > git init > git commit > git

    commit > git commit > git branch mybranch > git checkout mybranch > git commit > git commit > git checkout master b a c d e & mybranch & master '
  53. & Branch > git init > git commit > git

    commit > git commit > git branch mybranch > git checkout mybranch > git commit > git commit > git checkout master > git commit > git commit b a c d e f g & mybranch & master '
  54. & Branch b a c f g & mybranch d

    e b a c & master
  55. & Branch - why? • Multi-task

  56. & Branch - why? • Multi-task • Collaborate

  57. & Branch - why? • Multi-task • Collaborate • Experiment

  58. & Branch - why? • Multi-task • Collaborate • Experiment

    What happens when you're finished with a branch?
  59. • Incorporate changes from one branch into another • Bad

    name! • Merge: two things → one thing • Merge branch A into B → still two branches • Should be called Import ( Merge
  60. ( Merge Simplest case... & destination d e b a

    c & source b a c source is "ahead" of destination
  61. ( Merge & destination d e b a c &

    source b a c > git checkout destination > git merge source d e • destination has changed - source is unchanged
  62. ( Merge Fast-Forward merge d e b a c &

    source & destination
  63. ( Merge Fast-Forward merge d e b a c &

    source & destination
  64. ( Merge More complex case... source and destination have "diverged"

    & destination d e b a c & source b a c f g
  65. ( Merge & source b a c f g d

    e index.html Merge commit styles.css styles.css Common Ancestor & destination
  66. ( Merge & source b a c f g d

    e index.html Merge commit styles.css styles.css M styles.css index.html Merge commit Common Ancestor & destination > git checkout destination > git merge source
  67. ( Merge & destination & source b a c f

    g d e M
  68. ( Merge & destination & source b a c f

    g d e M • Merge commit has two parents • Contains diffs between source and common ancestor • Source branch remains unchanged • Git log on destination shows commit meta-data for d and e
  69. • Git is a distributed system • Collaborators each have

    a full copy of repo and history • Sync up with another repo using remote: - Repository on another machine - Git hosting service: - Another repo on your file system ) Remotes
  70. ) Remotes Local Machine https://github.com/dvberzon/ & master b a c

    > git clone & master b a c Origin & master b a c )
  71. ) Remotes Local Machine https://github.com/dvberzon/ & master b a c

    > git fetch & master b a c ) Origin & master b a c d b a c & branch1 d b a c & branch1
  72. ) Remotes Local Machine https://github.com/dvberzon/ & master b a c

    & master b a c ) Origin & master b a c d b a c & branch1 d b a c & branch1 > git checkout d b a c & branch1 Tracking branch
  73. ) Remotes Local Machine https://github.com/dvberzon/ & master b a c

    > git fetch & master b a c ) Origin & master b a c d b a c & branch1 d b a c & branch1 d b a c & branch1 e e
  74. ) Remotes Local Machine https://github.com/dvberzon/ & master b a c

    & master b a c ) Origin & master b a c d b a c & branch1 d b a c & branch1 > git merge d b a c & branch1 e e e
  75. ) Remotes Local Machine https://github.com/dvberzon/ & master b a c

    & master b a c ) Origin & master b a c d b a c & branch1 d b a c & branch1 d b a c & branch1 > git pull e e e git fetch & git merge
  76. ) Remotes Local Machine https://github.com/dvberzon/ & master b a c

    & master b a c ) Origin & master b a c d b a c & branch1 d b a c & branch1 d b a c e & branch1 > git push e e f b a c g & mybranch f b a c g & mybranch f b a c g & mybranch
  77. History

  78. So far we have been adding commits to history What

    if we could change history?
  79. With great power comes great responsibility Rewriting History

  80. ✏ git commit --amend • Same process as commit •

    Instead of adding a new commit, adds changes to the current commit. • Can also edit the commit message b a c styles.css d index.html Ammend d
  81. ✏ git commit --amend • Same process as commit •

    Instead of adding a new commit, adds changes to the current commit. • Can also edit the commit message b a c styles.css d d' index.html d' has new SHA
  82. ↩ git reset • Opposite process to commit • Removes

    all commits up to and including the target • Diffs in the removed commits become local changes b a d Reset to b styles.css c index.html
  83. ↩ git reset • Opposite process to commit • Removes

    all commits up to and including the target • Diffs in the removed commits become local changes b a Reset to b styles.css index.html
  84. ⚾ git rebase • Change starting point (base) of a

    sequence of commits • Rewind commits to the starting point • Reapply commits from the new starting point b a c d e f g & branch1 & master > git checkout branch1 > git rebase master Current base New base
  85. ⚾ git rebase • Change starting point (base) of a

    sequence of commits • Rewind commits to the starting point • Reapply commits from the new starting point b a c d e & master f' g' & branch1 f' and g' have new SHAs
  86. Why?

  87. Two ways to look at git history Story Record

  88. ... div.panel { background-color: #eee; display: flex; flex: 1 0

    0; min-width: 250px; } ... styles.css - Story telling . in IE11
  89. ... div.panel { background-color: #eee; display: flex; - flex: 1

    0 0; + flex: 1 0 0%; min-width: 250px; } ... styles.css Document the change? - Story telling
  90. ... div.panel { background-color: #eee; display: flex; - flex: 1

    0 0; + /* IE11 requires % unit */ + flex: 1 0 0%; min-width: 250px; } ... styles.css - Story telling
  91. ... div.panel { background-color: #eee; display: flex; - flex: 1

    0 0; + flex: 1 0 0%; min-width: 250px; } ... styles.css ✉ Commit message commit 762258f4a4e64cdf156960d12fea785a3f11fdcf Author: Daniel van Berzon <dvberzon@gmail.com> Date: Mon Jul 29 18:54:33 2019 +0200 Added unit to flex basis This was causing a bug in IE11 where `flex` command is ignored if the basis part doesn't have a unit. More details here: https://github.com/philipwalton/flexbugs#flexbug-4
  92. - Story telling • A commit message can be used

    to document a change • Works best if each commit contains one logical change - Atomic commit • A logical sequence of atomic commits can tell a story
  93. None
  94. Different histories

  95. 0 Record

  96. 0 Record

  97. 0 Record

  98. - Story

  99. - Story

  100. - Story

  101. - Story

  102. • Git history that tells a coherent story has advantages:

    - Documents reason for changes - Easier to do code reviews - Easier to search and find bugs • Process of coding is messy • Use git commands to refactor history and tell the story 1 Rewriting history
  103. & master & feature1 & master & feature1 b a

    c f g ⚾ why rebase? • Useful for keeping a clean history shape d e M h M b a c d e g' M h f'
  104. ⚾ why rebase? Merge Rebase

  105. Why not?

  106. Local Machine https://github.com/dvberzon/ & branch1 b a c ☠ Dangers

    of rewriting history & branch1 b a c d e > git push
  107. Local Machine https://github.com/dvberzon/ & branch1 b a c ☠ Dangers

    of rewriting history & branch1 b a c e > git push --force e
  108. Local Machine https://github.com/dvberzon/ & branch1 b a c ☠ Dangers

    of rewriting history & branch1 b a c e > git push --force e & branch1 b a c d Collaborator > git pull
  109. • Rewriting history causes problems with published branches • Some

    say you should not do it at all • Others say it's fine, but only on personal branches • There are ways to protect yourself from issues > git push --force-with-lease ☠ Dangers of rewriting history
  110. Cool Tricks

  111. 3 git add -p (partial add) • Allows you to

    add parts of a modified file to the index • Allows you to split changes to a file into separate commits Working directory Index > git add -p index.html index.html
  112. 4 Cherry-pick & source b a c f g d

    e Alternative to merging d' > git cherry-pick 762258f4 commit 762258f4a4e64cdf156960d12fea785a3f11fdcf Author: Daniel van Berzon <dvberzon@gmail.com> Date: Mon Jul 29 18:54:33 2019 +0200 Add banner to index index.html & destination ' commit 84e7456da575a5d3d205e7876c4f465800a207ad Author: Daniel van Berzon <dvberzon@gmail.com> Date: Mon Jul 29 18:54:33 2019 +0200 Add banner to index index.html
  113. 3 git rebase -i (interactive) • Works the same way

    as rebase... • You can edit list of commits to be reapplied in a text file pick 790cce9 add emphasis pick fb0b815 adding folder pick 762258f repeat pick 84e7456 a commit # Rebase 343e404..84e7456 onto 343e404 (4 commands) # # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message
  114. 3 git rebase -i (interactive) • Works the same way

    as rebase... • You can edit list of commits to be reapplied in a text file • Allows you to: - Reorder or delete commits - Squash commits - Edit commit messages and contents pick 790cce9 add emphasis pick fb0b815 adding folder pick 762258f repeat pick 84e7456 a commit # Rebase 343e404..84e7456 onto 343e404 (4 commands) # # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message
  115. That's all we have time for

  116. 5 In Memoriam Conflicts Workflows > git stash > git

    revert > git reflog > git blame (annotate) > git log -S (pickaxe) > git bisect
  117. 6 Useful links git-scm.com/book/en/v2 • Pro git • Atlassian Git

    Tutorials • Git CLI tutorial • Oh shit git! www.atlassian.com/git ohshitgit.com/ > git help tutorial
  118. Daniel van Berzon @ocastahq ocasta.com @dvberzon vanberzon.com Thank you