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

Git merge in depth

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for Anton Chikin Anton Chikin
November 29, 2016

Git merge in depth

How exactly 3-way recursive merge and rebase work.

Avatar for Anton Chikin

Anton Chikin

November 29, 2016
Tweet

Other Decks in Technology

Transcript

  1. 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
  2. ? 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
  3. ? 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 ?
  4. ? 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 ? ?
  5. ? 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 ? ? ?
  6. ? 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 ? ? ? ?
  7. ? 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
  8. ? 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
  9. ? 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
  10. ? 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”
  11. ? 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”
  12. ? 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)
  13. ? 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)
  14. 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 = {}
  15. 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 = {} ?????????????
  16. 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 = {} ?????????????
  17. def getData(string path) <<<<<<< HEAD var data = Map() |||||||

    merged common ancestors var data = {} ======= var data = Array() >>>>>>> branch
  18. 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)
  19. 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)
  20. 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
  21. 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
  22. 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()
  23. 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()
  24. master M M ? hotfix feature Let’s take a look

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

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

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

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

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

    using that “fake” ancestor nearest common ancestor
  30. master branch master diff B diff C diff A A

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

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

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

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

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

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

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

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

    C What does it mean to “apply diff”?
  39. 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”?
  40. 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”?
  41. master branch branch master A’ B’ C’ A B C

    M Merge and rebase give you different branch structure but the same result
  42. 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