@@ -387,8 +387,24 @@ struct merge_options_internal {
387
387
388
388
/* call_depth: recursion level counter for merging merge bases */
389
389
int call_depth ;
390
+
391
+ /* field that holds submodule conflict information */
392
+ struct string_list conflicted_submodules ;
393
+ };
394
+
395
+ struct conflicted_submodule_item {
396
+ char * abbrev ;
397
+ int flag ;
390
398
};
391
399
400
+ static void conflicted_submodule_item_free (void * util , const char * str )
401
+ {
402
+ struct conflicted_submodule_item * item = util ;
403
+
404
+ free (item -> abbrev );
405
+ free (item );
406
+ }
407
+
392
408
struct version_info {
393
409
struct object_id oid ;
394
410
unsigned short mode ;
@@ -517,6 +533,7 @@ enum conflict_and_info_types {
517
533
CONFLICT_SUBMODULE_NOT_INITIALIZED ,
518
534
CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE ,
519
535
CONFLICT_SUBMODULE_MAY_HAVE_REWINDS ,
536
+ CONFLICT_SUBMODULE_NULL_MERGE_BASE ,
520
537
521
538
/* Keep this entry _last_ in the list */
522
539
NB_CONFLICT_TYPES ,
@@ -570,6 +587,8 @@ static const char *type_short_descriptions[] = {
570
587
"CONFLICT (submodule history not available)" ,
571
588
[CONFLICT_SUBMODULE_MAY_HAVE_REWINDS ] =
572
589
"CONFLICT (submodule may have rewinds)" ,
590
+ [CONFLICT_SUBMODULE_NULL_MERGE_BASE ] =
591
+ "CONFLICT (submodule lacks merge base)"
573
592
};
574
593
575
594
struct logical_conflict_info {
@@ -686,6 +705,9 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
686
705
687
706
mem_pool_discard (& opti -> pool , 0 );
688
707
708
+ string_list_clear_func (& opti -> conflicted_submodules ,
709
+ conflicted_submodule_item_free );
710
+
689
711
/* Clean out callback_data as well. */
690
712
FREE_AND_NULL (renames -> callback_data );
691
713
renames -> callback_data_nr = renames -> callback_data_alloc = 0 ;
@@ -1744,24 +1766,32 @@ static int merge_submodule(struct merge_options *opt,
1744
1766
1745
1767
int i ;
1746
1768
int search = !opt -> priv -> call_depth ;
1769
+ int sub_not_initialized = 1 ;
1770
+ int sub_flag = CONFLICT_SUBMODULE_FAILED_TO_MERGE ;
1747
1771
1748
1772
/* store fallback answer in result in case we fail */
1749
1773
oidcpy (result , opt -> priv -> call_depth ? o : a );
1750
1774
1751
1775
/* we can not handle deletion conflicts */
1752
- if (is_null_oid (o ))
1753
- return 0 ;
1754
- if (is_null_oid (a ))
1755
- return 0 ;
1756
- if (is_null_oid (b ))
1757
- return 0 ;
1776
+ if (is_null_oid (a ) || is_null_oid (b ))
1777
+ BUG ("submodule deleted on one side; this should be handled outside of merge_submodule()" );
1758
1778
1759
- if (repo_submodule_init (& subrepo , opt -> repo , path , null_oid ())) {
1779
+ if ((sub_not_initialized = repo_submodule_init (& subrepo ,
1780
+ opt -> repo , path , null_oid ()))) {
1760
1781
path_msg (opt , CONFLICT_SUBMODULE_NOT_INITIALIZED , 0 ,
1761
1782
path , NULL , NULL , NULL ,
1762
1783
_ ("Failed to merge submodule %s (not checked out)" ),
1763
1784
path );
1764
- return 0 ;
1785
+ sub_flag = CONFLICT_SUBMODULE_NOT_INITIALIZED ;
1786
+ goto cleanup ;
1787
+ }
1788
+
1789
+ if (is_null_oid (o )) {
1790
+ path_msg (opt , CONFLICT_SUBMODULE_NULL_MERGE_BASE , 0 ,
1791
+ path , NULL , NULL , NULL ,
1792
+ _ ("Failed to merge submodule %s (no merge base)" ),
1793
+ path );
1794
+ goto cleanup ;
1765
1795
}
1766
1796
1767
1797
if (!(commit_o = lookup_commit_reference (& subrepo , o )) ||
@@ -1771,6 +1801,7 @@ static int merge_submodule(struct merge_options *opt,
1771
1801
path , NULL , NULL , NULL ,
1772
1802
_ ("Failed to merge submodule %s (commits not present)" ),
1773
1803
path );
1804
+ sub_flag = CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE ;
1774
1805
goto cleanup ;
1775
1806
}
1776
1807
@@ -1849,7 +1880,23 @@ static int merge_submodule(struct merge_options *opt,
1849
1880
1850
1881
object_array_clear (& merges );
1851
1882
cleanup :
1852
- repo_clear (& subrepo );
1883
+ if (!opt -> priv -> call_depth && !ret ) {
1884
+ struct string_list * csub = & opt -> priv -> conflicted_submodules ;
1885
+ struct conflicted_submodule_item * util ;
1886
+ const char * abbrev ;
1887
+
1888
+ util = xmalloc (sizeof (* util ));
1889
+ util -> flag = sub_flag ;
1890
+ util -> abbrev = NULL ;
1891
+ if (!sub_not_initialized ) {
1892
+ abbrev = repo_find_unique_abbrev (& subrepo , b , DEFAULT_ABBREV );
1893
+ util -> abbrev = xstrdup (abbrev );
1894
+ }
1895
+ string_list_append (csub , path )-> util = util ;
1896
+ }
1897
+
1898
+ if (!sub_not_initialized )
1899
+ repo_clear (& subrepo );
1853
1900
return ret ;
1854
1901
}
1855
1902
@@ -4434,6 +4481,63 @@ static int record_conflicted_index_entries(struct merge_options *opt)
4434
4481
return errs ;
4435
4482
}
4436
4483
4484
+ static void print_submodule_conflict_suggestion (struct string_list * csub ) {
4485
+ struct string_list_item * item ;
4486
+ struct strbuf msg = STRBUF_INIT ;
4487
+ struct strbuf tmp = STRBUF_INIT ;
4488
+ struct strbuf subs = STRBUF_INIT ;
4489
+
4490
+ if (!csub -> nr )
4491
+ return ;
4492
+
4493
+ strbuf_add_separated_string_list (& subs , " " , csub );
4494
+ for_each_string_list_item (item , csub ) {
4495
+ struct conflicted_submodule_item * util = item -> util ;
4496
+
4497
+ /*
4498
+ * NEEDSWORK: The steps to resolve these errors deserve a more
4499
+ * detailed explanation than what is currently printed below.
4500
+ */
4501
+ if (util -> flag == CONFLICT_SUBMODULE_NOT_INITIALIZED ||
4502
+ util -> flag == CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE )
4503
+ continue ;
4504
+
4505
+ /*
4506
+ * TRANSLATORS: This is a line of advice to resolve a merge
4507
+ * conflict in a submodule. The first argument is the submodule
4508
+ * name, and the second argument is the abbreviated id of the
4509
+ * commit that needs to be merged. For example:
4510
+ * - go to submodule (mysubmodule), and either merge commit abc1234"
4511
+ */
4512
+ strbuf_addf (& tmp , _ (" - go to submodule (%s), and either merge commit %s\n"
4513
+ " or update to an existing commit which has merged those changes\n" ),
4514
+ item -> string , util -> abbrev );
4515
+ }
4516
+
4517
+ /*
4518
+ * TRANSLATORS: This is a detailed message for resolving submodule
4519
+ * conflicts. The first argument is string containing one step per
4520
+ * submodule. The second is a space-separated list of submodule names.
4521
+ */
4522
+ strbuf_addf (& msg ,
4523
+ _ ("Recursive merging with submodules currently only supports trivial cases.\n"
4524
+ "Please manually handle the merging of each conflicted submodule.\n"
4525
+ "This can be accomplished with the following steps:\n"
4526
+ "%s"
4527
+ " - come back to superproject and run:\n\n"
4528
+ " git add %s\n\n"
4529
+ " to record the above merge or update\n"
4530
+ " - resolve any other conflicts in the superproject\n"
4531
+ " - commit the resulting index in the superproject\n" ),
4532
+ tmp .buf , subs .buf );
4533
+
4534
+ printf ("%s" , msg .buf );
4535
+
4536
+ strbuf_release (& subs );
4537
+ strbuf_release (& tmp );
4538
+ strbuf_release (& msg );
4539
+ }
4540
+
4437
4541
void merge_display_update_messages (struct merge_options * opt ,
4438
4542
int detailed ,
4439
4543
struct merge_result * result )
@@ -4483,6 +4587,8 @@ void merge_display_update_messages(struct merge_options *opt,
4483
4587
}
4484
4588
string_list_clear (& olist , 0 );
4485
4589
4590
+ print_submodule_conflict_suggestion (& opti -> conflicted_submodules );
4591
+
4486
4592
/* Also include needed rename limit adjustment now */
4487
4593
diff_warn_rename_limit ("merge.renamelimit" ,
4488
4594
opti -> renames .needed_limit , 0 );
@@ -4684,6 +4790,7 @@ static void merge_start(struct merge_options *opt, struct merge_result *result)
4684
4790
trace2_region_enter ("merge" , "allocate/init" , opt -> repo );
4685
4791
if (opt -> priv ) {
4686
4792
clear_or_reinit_internal_opts (opt -> priv , 1 );
4793
+ string_list_init_nodup (& opt -> priv -> conflicted_submodules );
4687
4794
trace2_region_leave ("merge" , "allocate/init" , opt -> repo );
4688
4795
return ;
4689
4796
}
0 commit comments