@@ -2841,6 +2841,26 @@ static int do_reset(const char *name, int len, struct replay_opts *opts)
2841
2841
return ret ;
2842
2842
}
2843
2843
2844
+ static struct commit * lookup_label (const char * label , int len ,
2845
+ struct strbuf * buf )
2846
+ {
2847
+ struct commit * commit ;
2848
+
2849
+ strbuf_reset (buf );
2850
+ strbuf_addf (buf , "refs/rewritten/%.*s" , len , label );
2851
+ commit = lookup_commit_reference_by_name (buf -> buf );
2852
+ if (!commit ) {
2853
+ /* fall back to non-rewritten ref or commit */
2854
+ strbuf_splice (buf , 0 , strlen ("refs/rewritten/" ), "" , 0 );
2855
+ commit = lookup_commit_reference_by_name (buf -> buf );
2856
+ }
2857
+
2858
+ if (!commit )
2859
+ error (_ ("could not resolve '%s'" ), buf -> buf );
2860
+
2861
+ return commit ;
2862
+ }
2863
+
2844
2864
static int do_merge (struct commit * commit , const char * arg , int arg_len ,
2845
2865
int flags , struct replay_opts * opts )
2846
2866
{
@@ -2849,8 +2869,9 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2849
2869
struct strbuf ref_name = STRBUF_INIT ;
2850
2870
struct commit * head_commit , * merge_commit , * i ;
2851
2871
struct commit_list * bases , * j , * reversed = NULL ;
2872
+ struct commit_list * to_merge = NULL , * * tail = & to_merge ;
2852
2873
struct merge_options o ;
2853
- int merge_arg_len , oneline_offset , can_fast_forward , ret ;
2874
+ int merge_arg_len , oneline_offset , can_fast_forward , ret , k ;
2854
2875
static struct lock_file lock ;
2855
2876
const char * p ;
2856
2877
@@ -2865,26 +2886,34 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2865
2886
goto leave_merge ;
2866
2887
}
2867
2888
2868
- oneline_offset = arg_len ;
2869
- merge_arg_len = strcspn (arg , " \t\n" );
2870
- p = arg + merge_arg_len ;
2871
- p += strspn (p , " \t\n" );
2872
- if (* p == '#' && (!p [1 ] || isspace (p [1 ]))) {
2873
- p += 1 + strspn (p + 1 , " \t\n" );
2874
- oneline_offset = p - arg ;
2875
- } else if (p - arg < arg_len )
2876
- BUG ("octopus merges are not supported yet: '%s'" , p );
2877
-
2878
- strbuf_addf (& ref_name , "refs/rewritten/%.*s" , merge_arg_len , arg );
2879
- merge_commit = lookup_commit_reference_by_name (ref_name .buf );
2880
- if (!merge_commit ) {
2881
- /* fall back to non-rewritten ref or commit */
2882
- strbuf_splice (& ref_name , 0 , strlen ("refs/rewritten/" ), "" , 0 );
2883
- merge_commit = lookup_commit_reference_by_name (ref_name .buf );
2889
+ /*
2890
+ * For octopus merges, the arg starts with the list of revisions to be
2891
+ * merged. The list is optionally followed by '#' and the oneline.
2892
+ */
2893
+ merge_arg_len = oneline_offset = arg_len ;
2894
+ for (p = arg ; p - arg < arg_len ; p += strspn (p , " \t\n" )) {
2895
+ if (!* p )
2896
+ break ;
2897
+ if (* p == '#' && (!p [1 ] || isspace (p [1 ]))) {
2898
+ p += 1 + strspn (p + 1 , " \t\n" );
2899
+ oneline_offset = p - arg ;
2900
+ break ;
2901
+ }
2902
+ k = strcspn (p , " \t\n" );
2903
+ if (!k )
2904
+ continue ;
2905
+ merge_commit = lookup_label (p , k , & ref_name );
2906
+ if (!merge_commit ) {
2907
+ ret = error (_ ("unable to parse '%.*s'" ), k , p );
2908
+ goto leave_merge ;
2909
+ }
2910
+ tail = & commit_list_insert (merge_commit , tail )-> next ;
2911
+ p += k ;
2912
+ merge_arg_len = p - arg ;
2884
2913
}
2885
2914
2886
- if (!merge_commit ) {
2887
- ret = error (_ ("could not resolve '%s'" ), ref_name . buf );
2915
+ if (!to_merge ) {
2916
+ ret = error (_ ("nothing to merge: '%.* s'" ), arg_len , arg );
2888
2917
goto leave_merge ;
2889
2918
}
2890
2919
@@ -2895,8 +2924,13 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2895
2924
* "[new root]", let's simply fast-forward to the merge head.
2896
2925
*/
2897
2926
rollback_lock_file (& lock );
2898
- ret = fast_forward_to (& merge_commit -> object .oid ,
2899
- & head_commit -> object .oid , 0 , opts );
2927
+ if (to_merge -> next )
2928
+ ret = error (_ ("octopus merge cannot be executed on "
2929
+ "top of a [new root]" ));
2930
+ else
2931
+ ret = fast_forward_to (& to_merge -> item -> object .oid ,
2932
+ & head_commit -> object .oid , 0 ,
2933
+ opts );
2900
2934
goto leave_merge ;
2901
2935
}
2902
2936
@@ -2932,7 +2966,8 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2932
2966
p = arg + oneline_offset ;
2933
2967
len = arg_len - oneline_offset ;
2934
2968
} else {
2935
- strbuf_addf (& buf , "Merge branch '%.*s'" ,
2969
+ strbuf_addf (& buf , "Merge %s '%.*s'" ,
2970
+ to_merge -> next ? "branches" : "branch" ,
2936
2971
merge_arg_len , arg );
2937
2972
p = buf .buf ;
2938
2973
len = buf .len ;
@@ -2956,28 +2991,76 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2956
2991
& head_commit -> object .oid );
2957
2992
2958
2993
/*
2959
- * If the merge head is different from the original one, we cannot
2994
+ * If any merge head is different from the original one, we cannot
2960
2995
* fast-forward.
2961
2996
*/
2962
2997
if (can_fast_forward ) {
2963
- struct commit_list * second_parent = commit -> parents -> next ;
2998
+ struct commit_list * p = commit -> parents -> next ;
2964
2999
2965
- if (second_parent && !second_parent -> next &&
2966
- oidcmp (& merge_commit -> object .oid ,
2967
- & second_parent -> item -> object .oid ))
3000
+ for (j = to_merge ; j && p ; j = j -> next , p = p -> next )
3001
+ if (oidcmp (& j -> item -> object .oid ,
3002
+ & p -> item -> object .oid )) {
3003
+ can_fast_forward = 0 ;
3004
+ break ;
3005
+ }
3006
+ /*
3007
+ * If the number of merge heads differs from the original merge
3008
+ * commit, we cannot fast-forward.
3009
+ */
3010
+ if (j || p )
2968
3011
can_fast_forward = 0 ;
2969
3012
}
2970
3013
2971
- if (can_fast_forward && commit -> parents -> next &&
2972
- !commit -> parents -> next -> next &&
2973
- !oidcmp (& commit -> parents -> next -> item -> object .oid ,
2974
- & merge_commit -> object .oid )) {
3014
+ if (can_fast_forward ) {
2975
3015
rollback_lock_file (& lock );
2976
3016
ret = fast_forward_to (& commit -> object .oid ,
2977
3017
& head_commit -> object .oid , 0 , opts );
2978
3018
goto leave_merge ;
2979
3019
}
2980
3020
3021
+ if (to_merge -> next ) {
3022
+ /* Octopus merge */
3023
+ struct child_process cmd = CHILD_PROCESS_INIT ;
3024
+
3025
+ if (read_env_script (& cmd .env_array )) {
3026
+ const char * gpg_opt = gpg_sign_opt_quoted (opts );
3027
+
3028
+ ret = error (_ (staged_changes_advice ), gpg_opt , gpg_opt );
3029
+ goto leave_merge ;
3030
+ }
3031
+
3032
+ cmd .git_cmd = 1 ;
3033
+ argv_array_pushl (& cmd .args ,
3034
+ "merge" ,
3035
+ "--strategy=octopus" ,
3036
+ "--no-edit" ,
3037
+ "--no-ff" ,
3038
+ "--no-log" ,
3039
+ "--no-stat" ,
3040
+ "-F" , git_path_merge_msg (),
3041
+ NULL );
3042
+ if (opts -> gpg_sign )
3043
+ argv_array_push (& cmd .args , opts -> gpg_sign );
3044
+
3045
+ /* Add the tips to be merged */
3046
+ for (j = to_merge ; j ; j = j -> next )
3047
+ argv_array_push (& cmd .args ,
3048
+ oid_to_hex (& j -> item -> object .oid ));
3049
+
3050
+ strbuf_release (& ref_name );
3051
+ unlink (git_path_cherry_pick_head ());
3052
+ rollback_lock_file (& lock );
3053
+
3054
+ rollback_lock_file (& lock );
3055
+ ret = run_command (& cmd );
3056
+
3057
+ /* force re-reading of the cache */
3058
+ if (!ret && (discard_cache () < 0 || read_cache () < 0 ))
3059
+ ret = error (_ ("could not read index" ));
3060
+ goto leave_merge ;
3061
+ }
3062
+
3063
+ merge_commit = to_merge -> item ;
2981
3064
write_message (oid_to_hex (& merge_commit -> object .oid ), GIT_SHA1_HEXSZ ,
2982
3065
git_path_merge_head (), 0 );
2983
3066
write_message ("no-ff" , 5 , git_path_merge_mode (), 0 );
@@ -3040,6 +3123,7 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
3040
3123
leave_merge :
3041
3124
strbuf_release (& ref_name );
3042
3125
rollback_lock_file (& lock );
3126
+ free_commit_list (to_merge );
3043
3127
return ret ;
3044
3128
}
3045
3129
@@ -3877,7 +3961,6 @@ static int make_script_with_merges(struct pretty_print_context *pp,
3877
3961
*/
3878
3962
while ((commit = get_revision (revs ))) {
3879
3963
struct commit_list * to_merge ;
3880
- int is_octopus ;
3881
3964
const char * p1 , * p2 ;
3882
3965
struct object_id * oid ;
3883
3966
int is_empty ;
@@ -3909,11 +3992,6 @@ static int make_script_with_merges(struct pretty_print_context *pp,
3909
3992
continue ;
3910
3993
}
3911
3994
3912
- is_octopus = to_merge && to_merge -> next ;
3913
-
3914
- if (is_octopus )
3915
- BUG ("Octopus merges not yet supported" );
3916
-
3917
3995
/* Create a label */
3918
3996
strbuf_reset (& label );
3919
3997
if (skip_prefix (oneline .buf , "Merge " , & p1 ) &&
@@ -3935,13 +4013,17 @@ static int make_script_with_merges(struct pretty_print_context *pp,
3935
4013
strbuf_addf (& buf , "%s -C %s" ,
3936
4014
cmd_merge , oid_to_hex (& commit -> object .oid ));
3937
4015
3938
- /* label the tip of merged branch */
3939
- oid = & to_merge -> item -> object .oid ;
3940
- strbuf_addch (& buf , ' ' );
4016
+ /* label the tips of merged branches */
4017
+ for (; to_merge ; to_merge = to_merge -> next ) {
4018
+ oid = & to_merge -> item -> object .oid ;
4019
+ strbuf_addch (& buf , ' ' );
4020
+
4021
+ if (!oidset_contains (& interesting , oid )) {
4022
+ strbuf_addstr (& buf , label_oid (oid , NULL ,
4023
+ & state ));
4024
+ continue ;
4025
+ }
3941
4026
3942
- if (!oidset_contains (& interesting , oid ))
3943
- strbuf_addstr (& buf , label_oid (oid , NULL , & state ));
3944
- else {
3945
4027
tips_tail = & commit_list_insert (to_merge -> item ,
3946
4028
tips_tail )-> next ;
3947
4029
0 commit comments