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

[PATCH v4 00/24] Clean up merge API

From
Elijah Newren <newren@gmail.com>
Date
Aug 17, 2019, 18:41 UTC
Message-ID
<20190817184144.32179-1-newren@gmail.com>
In-Reply-To
<20190815214053.16594-1-newren@gmail.com>

Before writing a replacement merge strategy for recursive, I decided to first cleanup the merge API -- streamlining merge-recursive.h and making it more readable. This includes some minor fixes found along the way.

Changes since v3 (full range-diff below):
  * Addressed feedback from Junio and SZEDER:
    * [Patch 4] Avoided looping over commit_list in determining
                ancestor_name
    * [Patch 12] s/inmemory/in_core/ in new cache-tree function name
    * [Patch 18] restored the '>= 0' comparision
    * [Patch 21] Use FREE_AND_NULL
    * [Patch 23] Use range checks for show_rename_progress (don't use
                 a bitfield), and don't compare an unsigned using >= 0.
Notes:
  * Patches 7, 9, 13, 14, and 15 only changed in the range-diff due to
    context changes from other patches
Derrick Stolee (1):
  merge-recursive: introduce an enum for detect_directory_renames values
Elijah Newren (23):
  merge-recursive: be consistent with assert
  checkout: provide better conflict hunk description with detached HEAD
  merge-recursive: enforce opt->ancestor != NULL when calling
    merge_trees()
  merge-recursive: provide a better label for diff3 common ancestor
  merge-recursive: future-proof update_file_flags() against memory leaks
  merge-recursive: remove another implicit dependency on the_repository
  Ensure index matches head before invoking merge machinery, round N
  merge-recursive: exit early if index != head
  merge-recursive: remove useless parameter in merge_trees()
  merge-recursive: don't force external callers to do our logging
  cache-tree: share code between functions writing an index as a tree
  merge-recursive: fix some overly long lines
  merge-recursive: use common name for ancestors/common/base_list
  merge-recursive: rename 'mrtree' to 'result_tree', for clarity
  merge-recursive: rename merge_options argument to opt in header
  merge-recursive: move some definitions around to clean up the header
  merge-recursive: consolidate unnecessary fields in merge_options
  merge-recursive: comment and reorder the merge_options fields
  merge-recursive: avoid losing output and leaking memory holding that
    output
  merge-recursive: split internal fields into a separate struct
  merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_*
  merge-recursive: add sanity checks for relevant merge_options
  merge-recursive: alphabetize include list
 builtin/am.c                      |   2 +-
 builtin/checkout.c                |  14 +-
 builtin/merge-recursive.c         |   4 +
 builtin/stash.c                   |   2 +
 cache-tree.c                      |  85 +++--
 cache-tree.h                      |   3 +-
 merge-recursive.c                 | 566 ++++++++++++++++++------------
 merge-recursive.h                 | 164 +++++----
 sequencer.c                       |   5 +-
 t/t3030-merge-recursive.sh        |   9 +-
 t/t6036-recursive-corner-cases.sh |   8 +-
 t/t6047-diff3-conflict-markers.sh | 189 ++++++++++
 12 files changed, 717 insertions(+), 334 deletions(-)
 create mode 100755 t/t6047-diff3-conflict-markers.sh
Range-diff:
 1:  21f1e04dc9 =  1:  7f99c2401e merge-recursive: be consistent with assert
 2:  ac24702773 =  2:  b305348f45 checkout: provide better conflict hunk description with detached HEAD
 3:  fd14ed9490 =  3:  5b9e32a356 merge-recursive: enforce opt->ancestor != NULL when calling merge_trees()
 4:  540a1d17d7 !  4:  566a55cf76 merge-recursive: provide a better label for diff3 common ancestor
    @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
      	struct commit *merged_common_ancestors;
      	struct tree *mrtree;
      	int clean;
    -+	int num_merge_bases;
    ++	const char *ancestor_name;
     +	struct strbuf merge_base_abbrev = STRBUF_INIT;
     +
     +	if (!opt->call_depth)
    @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
      	if (show(opt, 4)) {
      		output(opt, 4, _("Merging:"));
     @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
    - 			output_commit_title(opt, iter->item);
    + 
    + 		tree = lookup_tree(opt->repo, opt->repo->hash_algo->empty_tree);
    + 		merged_common_ancestors = make_virtual_commit(opt->repo, tree, "ancestor");
    ++		ancestor_name = "empty tree";
    ++	} else if (ca) {
    ++		ancestor_name = "merged common ancestors";
    ++	} else {
    ++		strbuf_add_unique_abbrev(&merge_base_abbrev,
    ++					 &merged_common_ancestors->object.oid,
    ++					 DEFAULT_ABBREV);
    ++		ancestor_name = merge_base_abbrev.buf;
      	}
      
    -+	num_merge_bases = commit_list_count(ca);
    - 	merged_common_ancestors = pop_commit(&ca);
    - 	if (merged_common_ancestors == NULL) {
    - 		/* if there is no common ancestor, use an empty tree */
    + 	for (iter = ca; iter; iter = iter->next) {
     @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
      	if (!opt->call_depth)
      		repo_read_index(opt->repo);
      
     -	opt->ancestor = "merged common ancestors";
    -+	switch (num_merge_bases) {
    -+	case 0:
    -+		opt->ancestor = "<empty tree>";
    -+		break;
    -+	case 1:
    -+		strbuf_add_unique_abbrev(&merge_base_abbrev,
    -+					 &merged_common_ancestors->object.oid,
    -+					 DEFAULT_ABBREV);
    -+		opt->ancestor = merge_base_abbrev.buf;
    -+		break;
    -+	default:
    -+		opt->ancestor = "merged common ancestors";
    -+	}
    ++	opt->ancestor = ancestor_name;
      	clean = merge_trees(opt, get_commit_tree(h1), get_commit_tree(h2),
      			    get_commit_tree(merged_common_ancestors),
      			    &mrtree);
    @@ t/t6047-diff3-conflict-markers.sh (new)
     +
     +		test_must_fail git -c merge.conflictstyle=diff3 merge --allow-unrelated-histories -s recursive R^0 &&
     +
    -+		grep "|||||| <empty tree>" content
    ++		grep "|||||| empty tree" content
     +	)
     +'
     +
 5:  19ff6a9503 =  5:  9c0bab2a0b merge-recursive: introduce an enum for detect_directory_renames values
 6:  5e44146da1 =  6:  2cd1a60a16 merge-recursive: future-proof update_file_flags() against memory leaks
 7:  df210eb029 !  7:  27a339781f merge-recursive: remove another implicit dependency on the_repository
    @@ Commit message
     
      ## merge-recursive.c ##
     @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
    - 	default:
    - 		opt->ancestor = "merged common ancestors";
    - 	}
    + 		repo_read_index(opt->repo);
    + 
    + 	opt->ancestor = ancestor_name;
     -	clean = merge_trees(opt, get_commit_tree(h1), get_commit_tree(h2),
     -			    get_commit_tree(merged_common_ancestors),
     +	clean = merge_trees(opt,
 8:  74dd7b8f59 =  8:  133c470371 Ensure index matches head before invoking merge machinery, round N
 9:  f04eba4184 !  9:  f43a229ae6 merge-recursive: exit early if index != head
    @@ merge-recursive.c: static struct commit_list *reverse_commit_list(struct commit_
      	struct commit_list *iter;
      	struct commit *merged_common_ancestors;
     @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
    - 	int num_merge_bases;
    + 	const char *ancestor_name;
      	struct strbuf merge_base_abbrev = STRBUF_INIT;
      
     -	if (!opt->call_depth)
    @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
      			return -1;
      		opt->branch1 = saved_b1;
     @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
    - 	default:
    - 		opt->ancestor = "merged common ancestors";
    - 	}
    + 		repo_read_index(opt->repo);
    + 
    + 	opt->ancestor = ancestor_name;
     -	clean = merge_trees(opt,
     -			    repo_get_commit_tree(opt->repo, h1),
     -			    repo_get_commit_tree(opt->repo, h2),
10:  8688d40739 = 10:  678dfbf507 merge-recursive: remove useless parameter in merge_trees()
11:  a92d460707 = 11:  7b28da5637 merge-recursive: don't force external callers to do our logging
12:  dec0ea7409 ! 12:  c1ae5cc1c4 cache-tree: share code between functions writing an index as a tree
    @@ builtin/checkout.c: static int merge_working_tree(const struct checkout_opts *op
      			init_merge_options(&o, the_repository);
      			o.verbosity = 0;
     -			work = write_tree_from_memory(&o);
    -+			work = write_inmemory_index_as_tree(the_repository);
    ++			work = write_in_core_index_as_tree(the_repository);
      
      			ret = reset_tree(new_tree,
      					 opts, 1,
    @@ cache-tree.c: static struct cache_tree *cache_tree_find(struct cache_tree *it, c
      	return it;
      }
      
    -+int write_index_as_tree_internal(struct object_id *oid, struct index_state *index_state, int cache_tree_valid, int flags, const char *prefix)
    ++static int write_index_as_tree_internal(struct object_id *oid,
    ++					struct index_state *index_state,
    ++					int cache_tree_valid,
    ++					int flags,
    ++					const char *prefix)
     +{
     +	if (flags & WRITE_TREE_IGNORE_CACHE_TREE) {
     +		cache_tree_free(&index_state->cache_tree);
    @@ cache-tree.c: static struct cache_tree *cache_tree_find(struct cache_tree *it, c
     +	return 0;
     +}
     +
    -+struct tree* write_inmemory_index_as_tree(struct repository *repo) {
    ++struct tree* write_in_core_index_as_tree(struct repository *repo) {
     +	struct object_id o;
     +	int was_valid, ret;
     +
    @@ cache-tree.h: void cache_tree_verify(struct repository *, struct index_state *);
      #define WRITE_TREE_UNMERGED_INDEX (-2)
      #define WRITE_TREE_PREFIX_ERROR (-3)
      
    -+struct tree* write_inmemory_index_as_tree(struct repository *repo);
    ++struct tree* write_in_core_index_as_tree(struct repository *repo);
      int write_index_as_tree(struct object_id *oid, struct index_state *index_state, const char *index_path, int flags, const char *prefix);
      void prime_cache_tree(struct repository *, struct index_state *, struct tree *);
      
    @@ merge-recursive.c: static int merge_trees_internal(struct merge_options *opt,
      
     -	if (opt->call_depth && !(*result = write_tree_from_memory(opt)))
     +	if (opt->call_depth &&
    -+	    !(*result = write_inmemory_index_as_tree(opt->repo)))
    ++	    !(*result = write_in_core_index_as_tree(opt->repo)))
      		return -1;
      
      	return clean;
13:  b51f3d1924 ! 13:  2e9fb223d9 merge-recursive: fix some overly long lines
    @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt
     -		merged_common_ancestors = make_virtual_commit(opt->repo, tree, "ancestor");
     +		merged_common_ancestors = make_virtual_commit(opt->repo,
     +							      tree, "ancestor");
    - 	}
    - 
    - 	for (iter = ca; iter; iter = iter->next) {
    + 		ancestor_name = "empty tree";
    + 	} else if (ca) {
    + 		ancestor_name = "merged common ancestors";
     @@ merge-recursive.c: int merge_recursive(struct merge_options *opt,
      	return clean;
      }
14:  a069cc4cca ! 14:  230d903012 merge-recursive: use common name for ancestors/common/base_list
    @@ merge-recursive.c: static struct commit_list *reverse_commit_list(struct commit_
     +	struct commit *merged_merge_bases;
      	struct tree *mrtree;
      	int clean;
    - 	int num_merge_bases;
    + 	const char *ancestor_name;
     @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
      		output_commit_title(opt, h2);
      	}
    @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt
      			output_commit_title(opt, iter->item);
      	}
      
    --	num_merge_bases = commit_list_count(ca);
     -	merged_common_ancestors = pop_commit(&ca);
     -	if (merged_common_ancestors == NULL) {
    -+	num_merge_bases = commit_list_count(merge_bases);
     +	merged_merge_bases = pop_commit(&merge_bases);
     +	if (merged_merge_bases == NULL) {
      		/* if there is no common ancestor, use an empty tree */
    @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt
     -							      tree, "ancestor");
     +		merged_merge_bases = make_virtual_commit(opt->repo, tree,
     +							 "ancestor");
    + 		ancestor_name = "empty tree";
    +-	} else if (ca) {
    ++	} else if (merge_bases) {
    + 		ancestor_name = "merged common ancestors";
    + 	} else {
    + 		strbuf_add_unique_abbrev(&merge_base_abbrev,
    +-					 &merged_common_ancestors->object.oid,
    ++					 &merged_merge_bases->object.oid,
    + 					 DEFAULT_ABBREV);
    + 		ancestor_name = merge_base_abbrev.buf;
      	}
      
     -	for (iter = ca; iter; iter = iter->next) {
    @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt
      			return err(opt, _("merge returned no commit"));
      	}
      
    -@@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
    - 		break;
    - 	case 1:
    - 		strbuf_add_unique_abbrev(&merge_base_abbrev,
    --					 &merged_common_ancestors->object.oid,
    -+					 &merged_merge_bases->object.oid,
    - 					 DEFAULT_ABBREV);
    - 		opt->ancestor = merge_base_abbrev.buf;
    - 		break;
     @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
      				     repo_get_commit_tree(opt->repo, h1),
      				     repo_get_commit_tree(opt->repo, h2),
15:  93a3ce6b88 ! 15:  28c20a2d08 merge-recursive: rename 'mrtree' to 'result_tree', for clarity
    @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt
     -	struct tree *mrtree;
     +	struct tree *result_tree;
      	int clean;
    - 	int num_merge_bases;
    + 	const char *ancestor_name;
      	struct strbuf merge_base_abbrev = STRBUF_INIT;
     @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
      				     repo_get_commit_tree(opt->repo, h2),
16:  1b1df10c11 = 16:  50e2e51cf6 merge-recursive: rename merge_options argument to opt in header
17:  1526977a85 = 17:  b8cd111bd2 merge-recursive: move some definitions around to clean up the header
18:  c90f2f15cd ! 18:  9bb8a7f162 merge-recursive: consolidate unnecessary fields in merge_options
    @@ merge-recursive.c: static int add_cacheinfo(struct merge_options *opt,
      {
     -	return opt->merge_detect_rename >= 0 ? opt->merge_detect_rename :
     -		opt->diff_detect_rename >= 0 ? opt->diff_detect_rename : 1;
    -+	return (opt->detect_renames != -1) ? opt->detect_renames : 1;
    ++	return (opt->detect_renames >= 0) ? opt->detect_renames : 1;
      }
      
      static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree)
    @@ merge-recursive.c: static struct diff_queue_struct *get_diffpairs(struct merge_o
     -	opts.rename_limit = opt->merge_rename_limit >= 0 ? opt->merge_rename_limit :
     -			    opt->diff_rename_limit >= 0 ? opt->diff_rename_limit :
     -			    1000;
    -+	opts.rename_limit = (opt->rename_limit != -1) ? opt->rename_limit : 1000;
    ++	opts.rename_limit = (opt->rename_limit >= 0) ? opt->rename_limit : 1000;
      	opts.rename_score = opt->rename_score;
      	opts.show_rename_progress = opt->show_rename_progress;
      	opts.output_format = DIFF_FORMAT_NO_OUTPUT;
19:  6d930dba72 = 19:  2140490796 merge-recursive: comment and reorder the merge_options fields
20:  ec3e15f6a8 = 20:  02478e2088 merge-recursive: avoid losing output and leaking memory holding that output
21:  7edfac7048 ! 21:  2781ca78d7 merge-recursive: split internal fields into a separate struct
    @@ merge-recursive.c: static int merge_trees_internal(struct merge_options *opt,
      
     -	if (opt->call_depth &&
     +	if (opt->priv->call_depth &&
    - 	    !(*result = write_inmemory_index_as_tree(opt->repo)))
    + 	    !(*result = write_in_core_index_as_tree(opt->repo)))
      		return -1;
      
     @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
    @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt
     +	if (!opt->priv->call_depth)
      		repo_read_index(opt->repo);
      
    - 	switch (num_merge_bases) {
    + 	opt->ancestor = ancestor_name;
     @@ merge-recursive.c: static int merge_recursive_internal(struct merge_options *opt,
      		return clean;
      	}
    @@ merge-recursive.c: static int merge_start(struct merge_options *opt, struct tree
      		diff_warn_rename_limit("merge.renamelimit",
     -				       opt->needed_rename_limit, 0);
     +				       opt->priv->needed_rename_limit, 0);
    -+	free(opt->priv);
    -+	opt->priv = NULL;
    ++	FREE_AND_NULL(opt->priv);
      }
      
      int merge_trees(struct merge_options *opt,
22:  9a381873c2 = 22:  5a52aa786e merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_*
23:  c6bc8a196f ! 23:  b7e6c2436a merge-recursive: add sanity checks for relevant merge_options
    @@ merge-recursive.c: static int merge_start(struct merge_options *opt, struct tree
     +	       opt->detect_directory_renames <= MERGE_DIRECTORY_RENAMES_TRUE);
     +	assert(opt->rename_limit >= -1);
     +	assert(opt->rename_score >= 0 && opt->rename_score <= MAX_SCORE);
    ++	assert(opt->show_rename_progress >= 0 && opt->show_rename_progress <= 1);
     +
     +	assert(opt->xdl_opts >= 0);
     +	assert(opt->recursive_variant >= MERGE_VARIANT_NORMAL &&
     +	       opt->recursive_variant <= MERGE_VARIANT_THEIRS);
     +
     +	assert(opt->verbosity >= 0 && opt->verbosity <= 5);
    -+	assert(opt->buffer_output >= 0 && opt->buffer_output <= 2);
    ++	assert(opt->buffer_output <= 2);
     +	assert(opt->obuf.len == 0);
     +
     +	assert(opt->priv == NULL);
    @@ merge-recursive.c: static int merge_start(struct merge_options *opt, struct tree
      	if (repo_index_has_changes(opt->repo, head, &sb)) {
      		err(opt, _("Your local changes to the following files would be overwritten by merge:\n  %s"),
      		    sb.buf);
    -
    - ## merge-recursive.h ##
    -@@ merge-recursive.h: struct merge_options {
    - 	} detect_directory_renames;
    - 	int rename_limit;
    - 	int rename_score;
    --	int show_rename_progress;
    -+	int show_rename_progress : 1;
    - 
    - 	/* xdiff-related options (patience, ignore whitespace, ours/theirs) */
    - 	long xdl_opts;
24:  2123e9e4e4 = 24:  6ac9e42a3e merge-recursive: alphabetize include list
-- 
2.23.0.rc2.28.g5f89f15d7b.dirty
Previous: Elijah NewrenNext: Elijah Newren
Message 117 of 157 in “Cleanup merge API”
  1. 00/19 Cleanup merge APIElijah Newren, Jul 25, 2019
  2. 01/19 merge-recursive: fix minor memory leak in error conditionElijah Newren, Jul 25, 2019
  3. 02/19 merge-recursive: remove another implicit dependency on the_repositoryElijah Newren, Jul 25, 2019
  4. 05/19 merge-recursive: don't force external callers to do our loggingElijah Newren, Jul 25, 2019
  5. 04/19 merge-recursive: exit early if index != headElijah Newren, Jul 25, 2019
  6. Johannes SchindelinJul 25, 2019
  7. Elijah NewrenJul 25, 2019
  8. 03/19 Ensure index matches head before invoking merge machinery, round NElijah Newren, Jul 25, 2019
  9. Johannes SchindelinJul 25, 2019
  10. Elijah NewrenJul 25, 2019
  11. Johannes SchindelinJul 26, 2019
  12. 07/19 Move write_tree_from_memory() from merge-recursive to cache-treeElijah Newren, Jul 25, 2019
  13. 08/19 merge-recursive: fix some overly long linesElijah Newren, Jul 25, 2019
  14. 09/19 merge-recursive: use common name for ancestors/common/base_listElijah Newren, Jul 25, 2019
  15. 10/19 merge-recursive: rename 'mrtree' to 'result_tree', for clarityElijah Newren, Jul 25, 2019
  16. Johannes SchindelinJul 25, 2019
  17. 11/19 merge-recursive: rename merge_options argument to opt in headerElijah Newren, Jul 25, 2019
  18. 13/19 merge-recursive: consolidate unnecessary fields in merge_optionsElijah Newren, Jul 25, 2019
  19. 12/19 merge-recursive: move some definitions around to clean up the headerElijah Newren, Jul 25, 2019
  20. 15/19 merge-recursive: split internal fields into a separate structElijah Newren, Jul 25, 2019
  21. Johannes SchindelinJul 25, 2019
  22. Elijah NewrenJul 25, 2019
  23. Johannes SchindelinJul 26, 2019
  24. Elijah NewrenJul 26, 2019
  25. 17/19 merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_*Elijah Newren, Jul 25, 2019
  26. 16/19 merge-recursive: alphabetize include listElijah Newren, Jul 25, 2019
  27. 18/19 merge-recursive: be consistent with assertElijah Newren, Jul 25, 2019
  28. 19/19 merge-recursive: provide a better label for diff3 common ancestorElijah Newren, Jul 25, 2019
  29. Johannes SchindelinJul 25, 2019
  30. 06/19 Change call signature of write_tree_from_memory()Elijah Newren, Jul 25, 2019
  31. Johannes SchindelinJul 25, 2019
  32. Elijah NewrenJul 26, 2019
  33. 14/19 merge-recursive: comment and reorder the merge_options fieldsElijah Newren, Jul 25, 2019
  34. Junio C HamanoJul 25, 2019
  35. Elijah NewrenJul 25, 2019
  36. Junio C HamanoJul 25, 2019
  37. Johannes SchindelinJul 26, 2019
  38. Johannes SchindelinJul 25, 2019
  39. Elijah NewrenJul 26, 2019
  40. 00/20 Cleanup merge APIElijah Newren, Jul 26, 2019
  41. 01/20 merge-recursive: fix minor memory leak in error conditionElijah Newren, Jul 26, 2019
  42. Junio C HamanoJul 26, 2019
  43. Elijah NewrenJul 26, 2019
  44. Derrick StoleeJul 29, 2019
  45. 03/20 Ensure index matches head before invoking merge machinery, round NElijah Newren, Jul 26, 2019
  46. Junio C HamanoJul 26, 2019
  47. Elijah NewrenJul 26, 2019
  48. 02/20 merge-recursive: remove another implicit dependency on the_repositoryElijah Newren, Jul 26, 2019
  49. Junio C HamanoJul 26, 2019
  50. 04/20 merge-recursive: exit early if index != headElijah Newren, Jul 26, 2019
  51. Junio C HamanoJul 26, 2019
  52. Elijah NewrenJul 26, 2019
  53. Junio C HamanoJul 29, 2019
  54. 05/20 merge-recursive: remove useless parameter in merge_trees()Elijah Newren, Jul 26, 2019
  55. Junio C HamanoJul 26, 2019
  56. 07/20 Use write_index_as_tree() in lieu of write_tree_from_memory()Elijah Newren, Jul 26, 2019
  57. Junio C HamanoJul 26, 2019
  58. Elijah NewrenJul 26, 2019
  59. Junio C HamanoJul 29, 2019
  60. 08/20 merge-recursive: fix some overly long linesElijah Newren, Jul 26, 2019
  61. 06/20 merge-recursive: don't force external callers to do our loggingElijah Newren, Jul 26, 2019
  62. Junio C HamanoJul 26, 2019
  63. Elijah NewrenJul 26, 2019
  64. 10/20 merge-recursive: rename 'mrtree' to 'result_tree', for clarityElijah Newren, Jul 26, 2019
  65. 11/20 merge-recursive: rename merge_options argument to opt in headerElijah Newren, Jul 26, 2019
  66. 09/20 merge-recursive: use common name for ancestors/common/base_listElijah Newren, Jul 26, 2019
  67. 14/20 merge-recursive: comment and reorder the merge_options fieldsElijah Newren, Jul 26, 2019
  68. 13/20 merge-recursive: consolidate unnecessary fields in merge_optionsElijah Newren, Jul 26, 2019
  69. 15/20 merge-recursive: avoid losing output and leaking memory holding that outputElijah Newren, Jul 26, 2019
  70. 12/20 merge-recursive: move some definitions around to clean up the headerElijah Newren, Jul 26, 2019
  71. 16/20 merge-recursive: split internal fields into a separate structElijah Newren, Jul 26, 2019
  72. 17/20 merge-recursive: alphabetize include listElijah Newren, Jul 26, 2019
  73. 18/20 merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_*Elijah Newren, Jul 26, 2019
  74. 20/20 merge-recursive: provide a better label for diff3 common ancestorElijah Newren, Jul 26, 2019
  75. 19/20 merge-recursive: be consistent with assertElijah Newren, Jul 26, 2019
  76. 00/24 Clean up merge APIElijah Newren, Aug 15, 2019
  77. 01/24 merge-recursive: be consistent with assertElijah Newren, Aug 15, 2019
  78. 03/24 merge-recursive: enforce opt->ancestor != NULL when calling merge_trees()Elijah Newren, Aug 15, 2019
  79. Junio C HamanoAug 16, 2019
  80. 02/24 checkout: provide better conflict hunk description with detached HEADElijah Newren, Aug 15, 2019
  81. 04/24 merge-recursive: provide a better label for diff3 common ancestorElijah Newren, Aug 15, 2019
  82. Junio C HamanoAug 16, 2019
  83. Elijah NewrenAug 16, 2019
  84. 05/24 merge-recursive: introduce an enum for detect_directory_renames valuesElijah Newren, Aug 15, 2019
  85. 06/24 merge-recursive: future-proof update_file_flags() against memory leaksElijah Newren, Aug 15, 2019
  86. 07/24 merge-recursive: remove another implicit dependency on the_repositoryElijah Newren, Aug 15, 2019
  87. 08/24 Ensure index matches head before invoking merge machinery, round NElijah Newren, Aug 15, 2019
  88. 09/24 merge-recursive: exit early if index != headElijah Newren, Aug 15, 2019
  89. 10/24 merge-recursive: remove useless parameter in merge_trees()Elijah Newren, Aug 15, 2019
  90. 11/24 merge-recursive: don't force external callers to do our loggingElijah Newren, Aug 15, 2019
  91. 15/24 merge-recursive: rename 'mrtree' to 'result_tree', for clarityElijah Newren, Aug 15, 2019
  92. 14/24 merge-recursive: use common name for ancestors/common/base_listElijah Newren, Aug 15, 2019
  93. 13/24 merge-recursive: fix some overly long linesElijah Newren, Aug 15, 2019
  94. 12/24 cache-tree: share code between functions writing an index as a treeElijah Newren, Aug 15, 2019
  95. Junio C HamanoAug 16, 2019
  96. Elijah NewrenAug 16, 2019
  97. 16/24 merge-recursive: rename merge_options argument to opt in headerElijah Newren, Aug 15, 2019
  98. 17/24 merge-recursive: move some definitions around to clean up the headerElijah Newren, Aug 15, 2019
  99. 19/24 merge-recursive: comment and reorder the merge_options fieldsElijah Newren, Aug 15, 2019
  100. 20/24 merge-recursive: avoid losing output and leaking memory holding that outputElijah Newren, Aug 15, 2019
  101. 24/24 merge-recursive: alphabetize include listElijah Newren, Aug 15, 2019
  102. 21/24 merge-recursive: split internal fields into a separate structElijah Newren, Aug 15, 2019
  103. SZEDER GáborAug 16, 2019
  104. Elijah NewrenAug 16, 2019
  105. Junio C HamanoAug 16, 2019
  106. 18/24 merge-recursive: consolidate unnecessary fields in merge_optionsElijah Newren, Aug 15, 2019
  107. Junio C HamanoAug 16, 2019
  108. Elijah NewrenAug 16, 2019
  109. Junio C HamanoAug 16, 2019
  110. 23/24 merge-recursive: add sanity checks for relevant merge_optionsElijah Newren, Aug 15, 2019
  111. Junio C HamanoAug 16, 2019
  112. Elijah NewrenAug 16, 2019
  113. Junio C HamanoAug 16, 2019
  114. Junio C HamanoAug 16, 2019
  115. Elijah NewrenAug 16, 2019
  116. 22/24 merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_*Elijah Newren, Aug 15, 2019
  117. 00/24 Clean up merge APIElijah Newren, Aug 17, 2019
  118. 01/24 merge-recursive: be consistent with assertElijah Newren, Aug 17, 2019
  119. 02/24 checkout: provide better conflict hunk description with detached HEADElijah Newren, Aug 17, 2019
  120. 03/24 merge-recursive: enforce opt->ancestor != NULL when calling merge_trees()Elijah Newren, Aug 17, 2019
  121. 04/24 merge-recursive: provide a better label for diff3 common ancestorElijah Newren, Aug 17, 2019
  122. Jeff KingSep 30, 2019
  123. Jeff KingSep 30, 2019
  124. merge-recursive: fix the diff3 common ancestor label for virtual commitsElijah Newren, Sep 30, 2019
  125. Elijah NewrenOct 1, 2019
  126. merge-recursive: fix the diff3 common ancestor label for virtual commitsElijah Newren, Oct 1, 2019
  127. Jeff KingOct 1, 2019
  128. merge-recursive: fix the diff3 common ancestor label for virtual commitsElijah Newren, Oct 1, 2019
  129. Junio C HamanoOct 7, 2019
  130. merge-recursive: fix the fix to the diff3 common ancestor labelElijah Newren, Oct 7, 2019
  131. Junio C HamanoOct 8, 2019
  132. Junio C HamanoOct 8, 2019
  133. Elijah NewrenOct 8, 2019
  134. 05/24 merge-recursive: introduce an enum for detect_directory_renames valuesElijah Newren, Aug 17, 2019
  135. 06/24 merge-recursive: future-proof update_file_flags() against memory leaksElijah Newren, Aug 17, 2019
  136. 09/24 merge-recursive: exit early if index != headElijah Newren, Aug 17, 2019
  137. 08/24 Ensure index matches head before invoking merge machinery, round NElijah Newren, Aug 17, 2019
  138. Johannes SchindelinSep 2, 2019
  139. Johannes SchindelinSep 3, 2019
  140. Elijah NewrenSep 3, 2019
  141. 10/24 merge-recursive: remove useless parameter in merge_trees()Elijah Newren, Aug 17, 2019
  142. 11/24 merge-recursive: don't force external callers to do our loggingElijah Newren, Aug 17, 2019
  143. 13/24 merge-recursive: fix some overly long linesElijah Newren, Aug 17, 2019
  144. 12/24 cache-tree: share code between functions writing an index as a treeElijah Newren, Aug 17, 2019
  145. 14/24 merge-recursive: use common name for ancestors/common/base_listElijah Newren, Aug 17, 2019
  146. 15/24 merge-recursive: rename 'mrtree' to 'result_tree', for clarityElijah Newren, Aug 17, 2019
  147. 17/24 merge-recursive: move some definitions around to clean up the headerElijah Newren, Aug 17, 2019
  148. 07/24 merge-recursive: remove another implicit dependency on the_repositoryElijah Newren, Aug 17, 2019
  149. 16/24 merge-recursive: rename merge_options argument to opt in headerElijah Newren, Aug 17, 2019
  150. 20/24 merge-recursive: avoid losing output and leaking memory holding that outputElijah Newren, Aug 17, 2019
  151. 21/24 merge-recursive: split internal fields into a separate structElijah Newren, Aug 17, 2019
  152. Junio C HamanoAug 19, 2019
  153. 19/24 merge-recursive: comment and reorder the merge_options fieldsElijah Newren, Aug 17, 2019
  154. 18/24 merge-recursive: consolidate unnecessary fields in merge_optionsElijah Newren, Aug 17, 2019
  155. 22/24 merge-recursive: rename MERGE_RECURSIVE_* to MERGE_VARIANT_*Elijah Newren, Aug 17, 2019
  156. 24/24 merge-recursive: alphabetize include listElijah Newren, Aug 17, 2019
  157. 23/24 merge-recursive: add sanity checks for relevant merge_optionsElijah Newren, Aug 17, 2019

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.