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

Git merge in depth

C3dbf3982793b3a3ae3277934d5f6d70?s=47 Anton Chikin
November 29, 2016

Git merge in depth

How exactly 3-way recursive merge and rebase work.

C3dbf3982793b3a3ae3277934d5f6d70?s=128

Anton Chikin

November 29, 2016
Tweet

Transcript

  1. git merge in depth Anton Chikin

  2. test branch merge master to branch test branch merge branch

    to master test master
  3. test branch merge master to branch test branch merge branch

    to master test master WAT
  4. I don’t trust merge!

  5. None
  6. None
  7. 3-way merge

  8. master

  9. master branch

  10. master branch

  11. master branch

  12. master branch

  13. master branch

  14. master branch ?

  15. master branch ? var a = “foo” def getData(string path)

    var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data
  16. ? var a = “foo” def getData(string path) var data

    = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data master branch
  17. ? var a = “foo” def getData(string path) var data

    = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data master branch ?
  18. ? var a = “foo” def getData(string path) var data

    = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data master branch ? ?
  19. ? var a = “foo” def getData(string path) var data

    = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data master branch ? ? ?
  20. ? var a = “foo” def getData(string path) var data

    = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data master branch ? ? ? ?
  21. ? var a = “foo” def getData(string path) var data

    = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data master branch ? ? ? ? Nearest common ancestor var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data
  22. ? var a = “foo” def getData(string path) var data

    = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor master branch
  23. ? var a = “foo” def getData(string path) var data

    = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch
  24. ? var a = “foo” def getData(string path) var data

    = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch def getData(string path) var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo”
  25. ? var a = “foo” def getData(string path) var data

    = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch def getData(string path) var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo”
  26. ? var a = “foo” def getData(string path) var data

    = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var data = {} for l in visit(path) data[l.slot] = l.data return data var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo” def getData(string path) def getData(URI path) def getData(string path)
  27. ? var a = “foo” def getData(string path) var data

    = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var data = {} for l in visit(path) data[l.slot] = l.data return data var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo” def getData(string path) def getData(URI path) def getData(string path)
  28. def getData(string path) ? var a = “foo” def getData(string

    path) var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() for l in visit(path) data[l.slot] = l.data return data var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo” def getData(string path) def getData(URI path) var data = {}
  29. def getData(string path) ? var a = “foo” def getData(string

    path) var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() for l in visit(path) data[l.slot] = l.data return data var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo” def getData(string path) def getData(URI path) var data = {} ?????????????
  30. def getData(string path) ? var a = “foo” def getData(string

    path) var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() for l in visit(path) data[l.slot] = l.data return data var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo” def getData(string path) def getData(URI path) var data = {} ?????????????
  31. def getData(string path) <<<<<<< HEAD var data = Map() |||||||

    merged common ancestors var data = {} ======= var data = Array() >>>>>>> branch
  32. def getData(string path) ? var a = “foo” def getData(string

    path) var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() for l in visit(path) data[l.slot] = l.data return data var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo” def getData(string path) def getData(URI path) var data = {} var data = Map() for l in visit(path)
  33. def getData(string path) ? var a = “foo” def getData(string

    path) var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() for l in visit(path) data[l.slot] = l.data return data var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo” def getData(string path) def getData(URI path) var data = {} var data = Map() for l in visit(path)
  34. def getData(string path) ? var a = “foo” def getData(string

    path) var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() for l in visit(path) data[l.slot] = l.data return data var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo” def getData(string path) def getData(URI path) var data = {} var data = Map() for l in visit(path) data[l.id] = l.data
  35. def getData(string path) ? var a = “foo” def getData(string

    path) var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() for l in visit(path) data[l.slot] = l.data return data var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo” def getData(string path) def getData(URI path) var data = {} var data = Map() for l in visit(path) data[l.id] = l.data
  36. def getData(string path) ? var a = “foo” def getData(string

    path) var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() for l in visit(path) data[l.slot] = l.data return data var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo” def getData(string path) def getData(URI path) var data = {} var data = Map() for l in visit(path) data[l.id] = l.data return data.JSON()
  37. def getData(string path) ? var a = “foo” def getData(string

    path) var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() var a = “foo” def getData(URI path) var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” def getData(string path) var data = {} for l in visit(path) data[l.slot] = l.data return data ancestor merge ancestor master branch var data = Map() for l in visit(path) data[l.slot] = l.data return data.JSON() for l in visit(path) data[l.slot] = l.data return data var data = Array() for l in visit(path) data[l.id] = l.data return data var a = “foo” var a = “foo” var a = “foo” var a = “foo” def getData(string path) def getData(URI path) var data = {} var data = Map() for l in visit(path) data[l.id] = l.data return data.JSON()
  38. master branch ?

  39. master branch

  40. master branch merge master into branch

  41. master branch merge master into branch

  42. branch merge branch into master master

  43. recursive 3-way merge

  44. master Let’s take a look at a more complicated picture

  45. master hotfix Let’s take a look at a more complicated

    picture
  46. master hotfix Let’s take a look at a more complicated

    picture
  47. master feature hotfix Let’s take a look at a more

    complicated picture
  48. master hotfix feature Let’s take a look at a more

    complicated picture
  49. master hotfix feature Let’s take a look at a more

    complicated picture
  50. master M hotfix feature Let’s take a look at a

    more complicated picture
  51. master M M hotfix feature Let’s take a look at

    a more complicated picture
  52. master M M ? hotfix feature Let’s take a look

    at a more complicated picture
  53. master M M ? hotfix feature Let’s take a look

    at a more complicated picture nearest common ancestor
  54. master M M ? hotfix feature How to deal with

    two nearest common ancestors? nearest common ancestor nearest common ancestor
  55. master M M ? hotfix nearest common ancestor Step 1:

    find nearest common ancestor of those ancestors
  56. master M M ? hotfix Step 2: merge them into

    “fake” commit nearest common ancestor
  57. master M M ? hotfix Step 3: Merge our commits

    using that “fake” ancestor nearest common ancestor
  58. master M M hotfix M nearest common ancestor This process

    can be recursive
  59. master M M hotfix feature M

  60. And what about rebase?

  61. master branch master A B C

  62. master branch master A B C nearest common ancestor Again,

    find NCO
  63. master branch master diff B diff C diff A A

    B C Create diffs between each commits starting from NCO
  64. master branch master A B C diff B diff C

    diff A Move branch head to master
  65. master branch master A B C A’ diff B diff

    C Apply each diff on top of latest master commit
  66. master branch master A B C A’ B’ diff C

    Apply each diff on top of latest master commit
  67. master branch master A B C A’ B’ C’ Apply

    each diff on top of latest master commit
  68. @1,1 - A + B What does it mean to

    “apply diff”? Diff format is quite simple: In the first line
  69. @1,1 - A + B Diff format is quite simple:

    In the first line replace “A” What does it mean to “apply diff”?
  70. @1,1 - A + B Diff format is quite simple:

    In the first line replace “A” with “B” What does it mean to “apply diff”?
  71. A B C @1,1 - A + B B B

    C What does it mean to “apply diff”?
  72. D B C @1,1 - A + B ???????? B

    C What if first line in file is not “A” but “D”? Same as in merge - conflict! What does it mean to “apply diff”?
  73. D B C @1,1 - A + B ???????? B

    C What if first line in file is not “A” but “D”? Same as in merge - conflict! What does it mean to “apply diff”?
  74. master branch branch master A’ B’ C’ A B C

    M Merge and rebase give you different branch structure but the same result
  75. Merge commits “train station”

  76. Merge commits “subway”

  77. Finally - don’t be afraid of recursive merge - merge

    a ->b == merge b ->a - merge == rebase - prefer merge over rebase - merge will never never let you down
  78. •http://think-like-a-git.net/ •http://git-school.github.io/visualizing-git/ Resources

  79. Questions?

  80. git merge in depth Anton Chikin