@@ -2806,6 +2806,26 @@ static int do_reset(const char *name, int len, struct replay_opts *opts)
2806
2806
len , name ));
2807
2807
}
2808
2808
2809
+ static struct commit * lookup_label (const char * label , int len ,
2810
+ struct strbuf * buf )
2811
+ {
2812
+ struct commit * commit ;
2813
+
2814
+ strbuf_reset (buf );
2815
+ strbuf_addf (buf , "refs/rewritten/%.*s" , len , label );
2816
+ commit = lookup_commit_reference_by_name (buf -> buf );
2817
+ if (!commit ) {
2818
+ /* fall back to non-rewritten ref or commit */
2819
+ strbuf_splice (buf , 0 , strlen ("refs/rewritten/" ), "" , 0 );
2820
+ commit = lookup_commit_reference_by_name (buf -> buf );
2821
+ }
2822
+
2823
+ if (!commit )
2824
+ error (_ ("could not resolve '%s'" ), buf -> buf );
2825
+
2826
+ return commit ;
2827
+ }
2828
+
2809
2829
static int do_merge (struct commit * commit , const char * arg , int arg_len ,
2810
2830
int flags , struct replay_opts * opts )
2811
2831
{
@@ -2814,8 +2834,9 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2814
2834
struct strbuf ref_name = STRBUF_INIT ;
2815
2835
struct commit * head_commit , * merge_commit , * i ;
2816
2836
struct commit_list * bases , * j , * reversed = NULL ;
2837
+ struct commit_list * to_merge = NULL , * * tail = & to_merge ;
2817
2838
struct merge_options o ;
2818
- int merge_arg_len , oneline_offset , can_fast_forward , ret ;
2839
+ int merge_arg_len , oneline_offset , can_fast_forward , ret , k ;
2819
2840
static struct lock_file lock ;
2820
2841
const char * p ;
2821
2842
@@ -2830,26 +2851,34 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2830
2851
goto leave_merge ;
2831
2852
}
2832
2853
2833
- oneline_offset = arg_len ;
2834
- merge_arg_len = strcspn (arg , " \t\n" );
2835
- p = arg + merge_arg_len ;
2836
- p += strspn (p , " \t\n" );
2837
- if (* p == '#' && (!p [1 ] || isspace (p [1 ]))) {
2838
- p += 1 + strspn (p + 1 , " \t\n" );
2839
- oneline_offset = p - arg ;
2840
- } else if (p - arg < arg_len )
2841
- BUG ("octopus merges are not supported yet: '%s'" , p );
2842
-
2843
- strbuf_addf (& ref_name , "refs/rewritten/%.*s" , merge_arg_len , arg );
2844
- merge_commit = lookup_commit_reference_by_name (ref_name .buf );
2845
- if (!merge_commit ) {
2846
- /* fall back to non-rewritten ref or commit */
2847
- strbuf_splice (& ref_name , 0 , strlen ("refs/rewritten/" ), "" , 0 );
2848
- merge_commit = lookup_commit_reference_by_name (ref_name .buf );
2854
+ /*
2855
+ * For octopus merges, the arg starts with the list of revisions to be
2856
+ * merged. The list is optionally followed by '#' and the oneline.
2857
+ */
2858
+ merge_arg_len = oneline_offset = arg_len ;
2859
+ for (p = arg ; p - arg < arg_len ; p += strspn (p , " \t\n" )) {
2860
+ if (!* p )
2861
+ break ;
2862
+ if (* p == '#' && (!p [1 ] || isspace (p [1 ]))) {
2863
+ p += 1 + strspn (p + 1 , " \t\n" );
2864
+ oneline_offset = p - arg ;
2865
+ break ;
2866
+ }
2867
+ k = strcspn (p , " \t\n" );
2868
+ if (!k )
2869
+ continue ;
2870
+ merge_commit = lookup_label (p , k , & ref_name );
2871
+ if (!merge_commit ) {
2872
+ ret = error (_ ("unable to parse '%.*s'" ), k , p );
2873
+ goto leave_merge ;
2874
+ }
2875
+ tail = & commit_list_insert (merge_commit , tail )-> next ;
2876
+ p += k ;
2877
+ merge_arg_len = p - arg ;
2849
2878
}
2850
2879
2851
- if (!merge_commit ) {
2852
- ret = error (_ ("could not resolve '%s'" ), ref_name . buf );
2880
+ if (!to_merge ) {
2881
+ ret = error (_ ("nothing to merge: '%.* s'" ), arg_len , arg );
2853
2882
goto leave_merge ;
2854
2883
}
2855
2884
@@ -2860,8 +2889,13 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2860
2889
* "[new root]", let's simply fast-forward to the merge head.
2861
2890
*/
2862
2891
rollback_lock_file (& lock );
2863
- ret = fast_forward_to (& merge_commit -> object .oid ,
2864
- & head_commit -> object .oid , 0 , opts );
2892
+ if (to_merge -> next )
2893
+ ret = error (_ ("octopus merge cannot be executed on "
2894
+ "top of a [new root]" ));
2895
+ else
2896
+ ret = fast_forward_to (& to_merge -> item -> object .oid ,
2897
+ & head_commit -> object .oid , 0 ,
2898
+ opts );
2865
2899
goto leave_merge ;
2866
2900
}
2867
2901
@@ -2897,7 +2931,8 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2897
2931
p = arg + oneline_offset ;
2898
2932
len = arg_len - oneline_offset ;
2899
2933
} else {
2900
- strbuf_addf (& buf , "Merge branch '%.*s'" ,
2934
+ strbuf_addf (& buf , "Merge %s '%.*s'" ,
2935
+ to_merge -> next ? "branches" : "branch" ,
2901
2936
merge_arg_len , arg );
2902
2937
p = buf .buf ;
2903
2938
len = buf .len ;
@@ -2921,28 +2956,76 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2921
2956
& head_commit -> object .oid );
2922
2957
2923
2958
/*
2924
- * If the merge head is different from the original one, we cannot
2959
+ * If any merge head is different from the original one, we cannot
2925
2960
* fast-forward.
2926
2961
*/
2927
2962
if (can_fast_forward ) {
2928
- struct commit_list * second_parent = commit -> parents -> next ;
2963
+ struct commit_list * p = commit -> parents -> next ;
2929
2964
2930
- if (second_parent && !second_parent -> next &&
2931
- oidcmp (& merge_commit -> object .oid ,
2932
- & second_parent -> item -> object .oid ))
2965
+ for (j = to_merge ; j && p ; j = j -> next , p = p -> next )
2966
+ if (oidcmp (& j -> item -> object .oid ,
2967
+ & p -> item -> object .oid )) {
2968
+ can_fast_forward = 0 ;
2969
+ break ;
2970
+ }
2971
+ /*
2972
+ * If the number of merge heads differs from the original merge
2973
+ * commit, we cannot fast-forward.
2974
+ */
2975
+ if (j || p )
2933
2976
can_fast_forward = 0 ;
2934
2977
}
2935
2978
2936
- if (can_fast_forward && commit -> parents -> next &&
2937
- !commit -> parents -> next -> next &&
2938
- !oidcmp (& commit -> parents -> next -> item -> object .oid ,
2939
- & merge_commit -> object .oid )) {
2979
+ if (can_fast_forward ) {
2940
2980
rollback_lock_file (& lock );
2941
2981
ret = fast_forward_to (& commit -> object .oid ,
2942
2982
& head_commit -> object .oid , 0 , opts );
2943
2983
goto leave_merge ;
2944
2984
}
2945
2985
2986
+ if (to_merge -> next ) {
2987
+ /* Octopus merge */
2988
+ struct child_process cmd = CHILD_PROCESS_INIT ;
2989
+
2990
+ if (read_env_script (& cmd .env_array )) {
2991
+ const char * gpg_opt = gpg_sign_opt_quoted (opts );
2992
+
2993
+ ret = error (_ (staged_changes_advice ), gpg_opt , gpg_opt );
2994
+ goto leave_merge ;
2995
+ }
2996
+
2997
+ cmd .git_cmd = 1 ;
2998
+ argv_array_push (& cmd .args , "merge" );
2999
+ argv_array_push (& cmd .args , "-s" );
3000
+ argv_array_push (& cmd .args , "octopus" );
3001
+ argv_array_push (& cmd .args , "--no-edit" );
3002
+ argv_array_push (& cmd .args , "--no-ff" );
3003
+ argv_array_push (& cmd .args , "--no-log" );
3004
+ argv_array_push (& cmd .args , "--no-stat" );
3005
+ argv_array_push (& cmd .args , "-F" );
3006
+ argv_array_push (& cmd .args , git_path_merge_msg (the_repository ));
3007
+ if (opts -> gpg_sign )
3008
+ argv_array_push (& cmd .args , opts -> gpg_sign );
3009
+
3010
+ /* Add the tips to be merged */
3011
+ for (j = to_merge ; j ; j = j -> next )
3012
+ argv_array_push (& cmd .args ,
3013
+ oid_to_hex (& j -> item -> object .oid ));
3014
+
3015
+ strbuf_release (& ref_name );
3016
+ unlink (git_path_cherry_pick_head (the_repository ));
3017
+ rollback_lock_file (& lock );
3018
+
3019
+ rollback_lock_file (& lock );
3020
+ ret = run_command (& cmd );
3021
+
3022
+ /* force re-reading of the cache */
3023
+ if (!ret && (discard_cache () < 0 || read_cache () < 0 ))
3024
+ ret = error (_ ("could not read index" ));
3025
+ goto leave_merge ;
3026
+ }
3027
+
3028
+ merge_commit = to_merge -> item ;
2946
3029
write_message (oid_to_hex (& merge_commit -> object .oid ), GIT_SHA1_HEXSZ ,
2947
3030
git_path_merge_head (the_repository ), 0 );
2948
3031
write_message ("no-ff" , 5 , git_path_merge_mode (the_repository ), 0 );
@@ -3005,6 +3088,7 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
3005
3088
leave_merge :
3006
3089
strbuf_release (& ref_name );
3007
3090
rollback_lock_file (& lock );
3091
+ free_commit_list (to_merge );
3008
3092
return ret ;
3009
3093
}
3010
3094
@@ -3910,7 +3994,6 @@ static int make_script_with_merges(struct pretty_print_context *pp,
3910
3994
*/
3911
3995
while ((commit = get_revision (revs ))) {
3912
3996
struct commit_list * to_merge ;
3913
- int is_octopus ;
3914
3997
const char * p1 , * p2 ;
3915
3998
struct object_id * oid ;
3916
3999
int is_empty ;
@@ -3942,11 +4025,6 @@ static int make_script_with_merges(struct pretty_print_context *pp,
3942
4025
continue ;
3943
4026
}
3944
4027
3945
- is_octopus = to_merge && to_merge -> next ;
3946
-
3947
- if (is_octopus )
3948
- BUG ("Octopus merges not yet supported" );
3949
-
3950
4028
/* Create a label */
3951
4029
strbuf_reset (& label );
3952
4030
if (skip_prefix (oneline .buf , "Merge " , & p1 ) &&
@@ -3968,13 +4046,17 @@ static int make_script_with_merges(struct pretty_print_context *pp,
3968
4046
strbuf_addf (& buf , "%s -C %s" ,
3969
4047
cmd_merge , oid_to_hex (& commit -> object .oid ));
3970
4048
3971
- /* label the tip of merged branch */
3972
- oid = & to_merge -> item -> object .oid ;
3973
- strbuf_addch (& buf , ' ' );
4049
+ /* label the tips of merged branches */
4050
+ for (; to_merge ; to_merge = to_merge -> next ) {
4051
+ oid = & to_merge -> item -> object .oid ;
4052
+ strbuf_addch (& buf , ' ' );
4053
+
4054
+ if (!oidset_contains (& interesting , oid )) {
4055
+ strbuf_addstr (& buf , label_oid (oid , NULL ,
4056
+ & state ));
4057
+ continue ;
4058
+ }
3974
4059
3975
- if (!oidset_contains (& interesting , oid ))
3976
- strbuf_addstr (& buf , label_oid (oid , NULL , & state ));
3977
- else {
3978
4060
tips_tail = & commit_list_insert (to_merge -> item ,
3979
4061
tips_tail )-> next ;
3980
4062
0 commit comments