git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 00/20] fundamentals of merge-ort implementation

From
Elijah Newren via GitGitGadget <gitgitgadget@gmail.com>
Date
Nov 29, 2020, 07:43 UTC
Message-ID
<pull.923.git.git.1606635803.gitgitgadget@gmail.com>

This is actually v3 of this series; but v2 depended on two topics that hadn't graduated yet so I couldn't easily use gitgitgadget and get its testing. Now that the topics have graduated, I have rebased on master. You can see v2 and comments on it over here: https://lore.kernel.org/git/20201102204344.342633-1-newren@gmail.com/

The goal of this series is to show the new design and structure behind merge-ort, particularly the bits that are completely different to how merge-recursive operates. There are still multiple important codepaths that die with a "Not yet implemented" message, so the new merge algorithm is still not very usable. However, it can handle very trivial rebases or cherry-picks at the end of the series, and the number of test failures when run under GIT_TEST_MERGE_ALGORITHM=ort drops from 2281 down to 1453.

At a high level, merge-ort avoids unpack_trees() and the index, instead using traverse_trees() and its own data structure. After it is done processing each path, it writes a tree. Only after it has created a new tree will it touch the working copy or the index. It does so by using a simple checkout-like step to switch from head to the newly created tree. If there are conflicted entries, it touches up the index after the checkout-like step to record those higher order stages.

In the series:
 * Patch 1 adds some basic data structures.
 * Patch 2 documents the high-level steps.
 * Patches 3-5 are some simple setup.
 * Patches 6-10 collect data from the traverse_trees() operation.
 * Patches 11-15 process the individual paths and create a tree.
 * Patches 16-19 handle checkout-and-then-write-higher-order-stages.
 * Patch 20 frees data from the merge_options_internal data structure

Changes since v2 (Thanks to Stolee and Jonathan Tan for their excellent and detailed reviews!):

 * Add thorough code comments to data structures, to try to answer multiple
   questions the reviewers brought up.
 * Add comments in various areas of the code that were a bit tricky.
 * As per Stolee's request/suggestion, restructured accesses to
   conflict_info* to make the code document that we
 * As per Jonathan's suggestion, restructured tree writing to have
   "END_TREE" markers for directories -- namely, the directory itself.
 * Removed path_conflict field (will add it back in a later series when it
   is actually used)
 * Improved requested commit messages
 * Settled on "conflicted" instead of mix of "conflicted" and "unmerged"
 * Fixed various typos, missing words, etc.
 * Fixed various spaces around operators, missing blank lines, etc.
 * Some other small tweaks I probably forgot or overlooked while typing up
   this summary.
Things for reviewers to concentrate on:
 * Patch 1: I added lots of comments describing the data structures, based
   on reviewer questions/comments. Are they clear?
 * Patch 9: Stolee was worried about the allocation of merged_info OR
   conflict_info and whether we were safely accessing the fields. Since this
   is our primary and largest data structure and many times most entries
   only need a smaller merged_info, I really do want the space savings of
   not always allocating the larger type. I typically access as a
   merged_info* now, and added some accessor macros to document why each
   access as a conflict_info* is okay. Does this seem like a good solution
   to the concern? 
 * Patch 15: Jonathan felt the previous version of this patch was hard to
   follow. I've restructured so that we process the directories in
   opt->priv->paths directly; you can kind of view them as non-synthetic
   end-of-tree markers. They may not stand out as such, though (since they
   aren't synthetic with special names or handling), so I've added some
   pretty big comments to explain things. Does this address concerns?
 * Patches 16-20: these have not yet been reviewed, though these are easier
   patches to review than many of the first 15! A quick guide: * Patches 16,
      18, and 20 are very straightforward; patches 17 and 19 are the ones
      that would benefit more from review.
    * Patch 17 is
      basically the twoway_merge subset of merge_working_tree() from
      builtin/checkout.c. Find that bit of code and it's a direct
      comparison.
    * Patch 19
      amounts to "how do I remove stage 0 entries in the index and replace
      them with 1-3 higher order stages?".
Elijah Newren (20):
  merge-ort: setup basic internal data structures
  merge-ort: add some high-level algorithm structure
  merge-ort: port merge_start() from merge-recursive
  merge-ort: use histogram diff
  merge-ort: add an err() function similar to one from merge-recursive
  merge-ort: implement a very basic collect_merge_info()
  merge-ort: avoid repeating fill_tree_descriptor() on the same tree
  merge-ort: compute a few more useful fields for collect_merge_info
  merge-ort: record stage and auxiliary info for every path
  merge-ort: avoid recursing into identical trees
  merge-ort: add a preliminary simple process_entries() implementation
  merge-ort: have process_entries operate in a defined order
  merge-ort: step 1 of tree writing -- record basenames, modes, and oids
  merge-ort: step 2 of tree writing -- function to create tree object
  merge-ort: step 3 of tree writing -- handling subdirectories as we go
  merge-ort: basic outline for merge_switch_to_result()
  merge-ort: add implementation of checkout()
  tree: enable cmp_cache_name_compare() to be used elsewhere
  merge-ort: add implementation of record_conflicted_index_entries()
  merge-ort: free data structures in merge_finalize()
 merge-ort.c | 1207 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 tree.c      |    2 +-
 tree.h      |    2 +
 3 files changed, 1207 insertions(+), 4 deletions(-)
base-commit: e67fbf927dfdf13d0b21dc6ea15dc3c7ef448ea0
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-923%2Fnewren%2Fort-basics-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-923/newren/ort-basics-v1
Pull-Request: https://github.com/git/git/pull/923
-- 
gitgitgadget
Next: Elijah Newren via GitGitGadget
Message 1 of 70 in “fundamentals of merge-ort implementation”
  1. 00/20 fundamentals of merge-ort implementationElijah Newren via GitGitGadget, Nov 29, 2020
  2. 03/20 merge-ort: port merge_start() from merge-recursiveElijah Newren via GitGitGadget, Nov 29, 2020
  3. 02/20 merge-ort: add some high-level algorithm structureElijah Newren via GitGitGadget, Nov 29, 2020
  4. 04/20 merge-ort: use histogram diffElijah Newren via GitGitGadget, Nov 29, 2020
  5. 01/20 merge-ort: setup basic internal data structuresElijah Newren via GitGitGadget, Nov 29, 2020
  6. 07/20 merge-ort: avoid repeating fill_tree_descriptor() on the same treeElijah Newren via GitGitGadget, Nov 29, 2020
  7. 05/20 merge-ort: add an err() function similar to one from merge-recursiveElijah Newren via GitGitGadget, Nov 29, 2020
  8. Ævar Arnfjörð BjarmasonNov 29, 2020
  9. Elijah NewrenNov 30, 2020
  10. Ævar Arnfjörð BjarmasonNov 29, 2020
  11. 10/20 merge-ort: avoid recursing into identical treesElijah Newren via GitGitGadget, Nov 29, 2020
  12. 08/20 merge-ort: compute a few more useful fields for collect_merge_infoElijah Newren via GitGitGadget, Nov 29, 2020
  13. 06/20 merge-ort: implement a very basic collect_merge_info()Elijah Newren via GitGitGadget, Nov 29, 2020
  14. 11/20 merge-ort: add a preliminary simple process_entries() implementationElijah Newren via GitGitGadget, Nov 29, 2020
  15. 12/20 merge-ort: have process_entries operate in a defined orderElijah Newren via GitGitGadget, Nov 29, 2020
  16. 14/20 merge-ort: step 2 of tree writing -- function to create tree objectElijah Newren via GitGitGadget, Nov 29, 2020
  17. 09/20 merge-ort: record stage and auxiliary info for every pathElijah Newren via GitGitGadget, Nov 29, 2020
  18. 15/20 merge-ort: step 3 of tree writing -- handling subdirectories as we goElijah Newren via GitGitGadget, Nov 29, 2020
  19. 16/20 merge-ort: basic outline for merge_switch_to_result()Elijah Newren via GitGitGadget, Nov 29, 2020
  20. 13/20 merge-ort: step 1 of tree writing -- record basenames, modes, and oidsElijah Newren via GitGitGadget, Nov 29, 2020
  21. 19/20 merge-ort: add implementation of record_conflicted_index_entries()Elijah Newren via GitGitGadget, Nov 29, 2020
  22. Ævar Arnfjörð BjarmasonNov 29, 2020
  23. 18/20 tree: enable cmp_cache_name_compare() to be used elsewhereElijah Newren via GitGitGadget, Nov 29, 2020
  24. 17/20 merge-ort: add implementation of checkout()Elijah Newren via GitGitGadget, Nov 29, 2020
  25. 20/20 merge-ort: free data structures in merge_finalize()Elijah Newren via GitGitGadget, Nov 29, 2020
  26. Elijah NewrenNov 29, 2020
  27. 00/20 fundamentals of merge-ort implementationElijah Newren via GitGitGadget, Dec 4, 2020
  28. 02/20 merge-ort: add some high-level algorithm structureElijah Newren via GitGitGadget, Dec 4, 2020
  29. 03/20 merge-ort: port merge_start() from merge-recursiveElijah Newren via GitGitGadget, Dec 4, 2020
  30. 01/20 merge-ort: setup basic internal data structuresElijah Newren via GitGitGadget, Dec 4, 2020
  31. 05/20 merge-ort: add an err() function similar to one from merge-recursiveElijah Newren via GitGitGadget, Dec 4, 2020
  32. 04/20 merge-ort: use histogram diffElijah Newren via GitGitGadget, Dec 4, 2020
  33. 15/20 merge-ort: step 3 of tree writing -- handling subdirectories as we goElijah Newren via GitGitGadget, Dec 4, 2020
  34. 14/20 merge-ort: step 2 of tree writing -- function to create tree objectElijah Newren via GitGitGadget, Dec 4, 2020
  35. 07/20 merge-ort: avoid repeating fill_tree_descriptor() on the same treeElijah Newren via GitGitGadget, Dec 4, 2020
  36. 09/20 merge-ort: record stage and auxiliary info for every pathElijah Newren via GitGitGadget, Dec 4, 2020
  37. 11/20 merge-ort: add a preliminary simple process_entries() implementationElijah Newren via GitGitGadget, Dec 4, 2020
  38. 10/20 merge-ort: avoid recursing into identical treesElijah Newren via GitGitGadget, Dec 4, 2020
  39. 08/20 merge-ort: compute a few more useful fields for collect_merge_infoElijah Newren via GitGitGadget, Dec 4, 2020
  40. 19/20 merge-ort: add implementation of record_conflicted_index_entries()Elijah Newren via GitGitGadget, Dec 4, 2020
  41. 18/20 tree: enable cmp_cache_name_compare() to be used elsewhereElijah Newren via GitGitGadget, Dec 4, 2020
  42. 12/20 merge-ort: have process_entries operate in a defined orderElijah Newren via GitGitGadget, Dec 4, 2020
  43. 13/20 merge-ort: step 1 of tree writing -- record basenames, modes, and oidsElijah Newren via GitGitGadget, Dec 4, 2020
  44. 06/20 merge-ort: implement a very basic collect_merge_info()Elijah Newren via GitGitGadget, Dec 4, 2020
  45. 17/20 merge-ort: add implementation of checkout()Elijah Newren via GitGitGadget, Dec 4, 2020
  46. 16/20 merge-ort: basic outline for merge_switch_to_result()Elijah Newren via GitGitGadget, Dec 4, 2020
  47. 20/20 merge-ort: free data structures in merge_finalize()Elijah Newren via GitGitGadget, Dec 4, 2020
  48. 00/20 fundamentals of merge-ort implementationElijah Newren via GitGitGadget, Dec 13, 2020
  49. 01/20 merge-ort: setup basic internal data structuresElijah Newren via GitGitGadget, Dec 13, 2020
  50. 04/20 merge-ort: use histogram diffElijah Newren via GitGitGadget, Dec 13, 2020
  51. 03/20 merge-ort: port merge_start() from merge-recursiveElijah Newren via GitGitGadget, Dec 13, 2020
  52. 02/20 merge-ort: add some high-level algorithm structureElijah Newren via GitGitGadget, Dec 13, 2020
  53. 08/20 merge-ort: compute a few more useful fields for collect_merge_infoElijah Newren via GitGitGadget, Dec 13, 2020
  54. 06/20 merge-ort: implement a very basic collect_merge_info()Elijah Newren via GitGitGadget, Dec 13, 2020
  55. 07/20 merge-ort: avoid repeating fill_tree_descriptor() on the same treeElijah Newren via GitGitGadget, Dec 13, 2020
  56. 05/20 merge-ort: add an err() function similar to one from merge-recursiveElijah Newren via GitGitGadget, Dec 13, 2020
  57. 10/20 merge-ort: avoid recursing into identical treesElijah Newren via GitGitGadget, Dec 13, 2020
  58. 14/20 merge-ort: step 2 of tree writing -- function to create tree objectElijah Newren via GitGitGadget, Dec 13, 2020
  59. 12/20 merge-ort: have process_entries operate in a defined orderElijah Newren via GitGitGadget, Dec 13, 2020
  60. 16/20 merge-ort: basic outline for merge_switch_to_result()Elijah Newren via GitGitGadget, Dec 13, 2020
  61. 09/20 merge-ort: record stage and auxiliary info for every pathElijah Newren via GitGitGadget, Dec 13, 2020
  62. 18/20 tree: enable cmp_cache_name_compare() to be used elsewhereElijah Newren via GitGitGadget, Dec 13, 2020
  63. 15/20 merge-ort: step 3 of tree writing -- handling subdirectories as we goElijah Newren via GitGitGadget, Dec 13, 2020
  64. 17/20 merge-ort: add implementation of checkout()Elijah Newren via GitGitGadget, Dec 13, 2020
  65. 19/20 merge-ort: add implementation of record_conflicted_index_entries()Elijah Newren via GitGitGadget, Dec 13, 2020
  66. 20/20 merge-ort: free data structures in merge_finalize()Elijah Newren via GitGitGadget, Dec 13, 2020
  67. 13/20 merge-ort: step 1 of tree writing -- record basenames, modes, and oidsElijah Newren via GitGitGadget, Dec 13, 2020
  68. 11/20 merge-ort: add a preliminary simple process_entries() implementationElijah Newren via GitGitGadget, Dec 13, 2020
  69. Felipe ContrerasDec 14, 2020
  70. Elijah NewrenDec 14, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.