@@ -2850,6 +2850,26 @@ static int do_reset(const char *name, int len, struct replay_opts *opts)
2850
2850
return ret ;
2851
2851
}
2852
2852
2853
+ static struct commit * lookup_label (const char * label , int len ,
2854
+ struct strbuf * buf )
2855
+ {
2856
+ struct commit * commit ;
2857
+
2858
+ strbuf_reset (buf );
2859
+ strbuf_addf (buf , "refs/rewritten/%.*s" , len , label );
2860
+ commit = lookup_commit_reference_by_name (buf -> buf );
2861
+ if (!commit ) {
2862
+ /* fall back to non-rewritten ref or commit */
2863
+ strbuf_splice (buf , 0 , strlen ("refs/rewritten/" ), "" , 0 );
2864
+ commit = lookup_commit_reference_by_name (buf -> buf );
2865
+ }
2866
+
2867
+ if (!commit )
2868
+ error (_ ("could not resolve '%s'" ), buf -> buf );
2869
+
2870
+ return commit ;
2871
+ }
2872
+
2853
2873
static int do_merge (struct commit * commit , const char * arg , int arg_len ,
2854
2874
int flags , struct replay_opts * opts )
2855
2875
{
@@ -2858,8 +2878,9 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2858
2878
struct strbuf ref_name = STRBUF_INIT ;
2859
2879
struct commit * head_commit , * merge_commit , * i ;
2860
2880
struct commit_list * bases , * j , * reversed = NULL ;
2881
+ struct commit_list * to_merge = NULL , * * tail = & to_merge ;
2861
2882
struct merge_options o ;
2862
- int merge_arg_len , oneline_offset , can_fast_forward , ret ;
2883
+ int merge_arg_len , oneline_offset , can_fast_forward , ret , k ;
2863
2884
static struct lock_file lock ;
2864
2885
const char * p ;
2865
2886
@@ -2874,26 +2895,34 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2874
2895
goto leave_merge ;
2875
2896
}
2876
2897
2877
- oneline_offset = arg_len ;
2878
- merge_arg_len = strcspn (arg , " \t\n" );
2879
- p = arg + merge_arg_len ;
2880
- p += strspn (p , " \t\n" );
2881
- if (* p == '#' && (!p [1 ] || isspace (p [1 ]))) {
2882
- p += 1 + strspn (p + 1 , " \t\n" );
2883
- oneline_offset = p - arg ;
2884
- } else if (p - arg < arg_len )
2885
- BUG ("octopus merges are not supported yet: '%s'" , p );
2886
-
2887
- strbuf_addf (& ref_name , "refs/rewritten/%.*s" , merge_arg_len , arg );
2888
- merge_commit = lookup_commit_reference_by_name (ref_name .buf );
2889
- if (!merge_commit ) {
2890
- /* fall back to non-rewritten ref or commit */
2891
- strbuf_splice (& ref_name , 0 , strlen ("refs/rewritten/" ), "" , 0 );
2892
- merge_commit = lookup_commit_reference_by_name (ref_name .buf );
2898
+ /*
2899
+ * For octopus merges, the arg starts with the list of revisions to be
2900
+ * merged. The list is optionally followed by '#' and the oneline.
2901
+ */
2902
+ merge_arg_len = oneline_offset = arg_len ;
2903
+ for (p = arg ; p - arg < arg_len ; p += strspn (p , " \t\n" )) {
2904
+ if (!* p )
2905
+ break ;
2906
+ if (* p == '#' && (!p [1 ] || isspace (p [1 ]))) {
2907
+ p += 1 + strspn (p + 1 , " \t\n" );
2908
+ oneline_offset = p - arg ;
2909
+ break ;
2910
+ }
2911
+ k = strcspn (p , " \t\n" );
2912
+ if (!k )
2913
+ continue ;
2914
+ merge_commit = lookup_label (p , k , & ref_name );
2915
+ if (!merge_commit ) {
2916
+ ret = error (_ ("unable to parse '%.*s'" ), k , p );
2917
+ goto leave_merge ;
2918
+ }
2919
+ tail = & commit_list_insert (merge_commit , tail )-> next ;
2920
+ p += k ;
2921
+ merge_arg_len = p - arg ;
2893
2922
}
2894
2923
2895
- if (!merge_commit ) {
2896
- ret = error (_ ("could not resolve '%s'" ), ref_name . buf );
2924
+ if (!to_merge ) {
2925
+ ret = error (_ ("nothing to merge: '%.* s'" ), arg_len , arg );
2897
2926
goto leave_merge ;
2898
2927
}
2899
2928
@@ -2904,8 +2933,13 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2904
2933
* "[new root]", let's simply fast-forward to the merge head.
2905
2934
*/
2906
2935
rollback_lock_file (& lock );
2907
- ret = fast_forward_to (& merge_commit -> object .oid ,
2908
- & head_commit -> object .oid , 0 , opts );
2936
+ if (to_merge -> next )
2937
+ ret = error (_ ("octopus merge cannot be executed on "
2938
+ "top of a [new root]" ));
2939
+ else
2940
+ ret = fast_forward_to (& to_merge -> item -> object .oid ,
2941
+ & head_commit -> object .oid , 0 ,
2942
+ opts );
2909
2943
goto leave_merge ;
2910
2944
}
2911
2945
@@ -2941,7 +2975,8 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2941
2975
p = arg + oneline_offset ;
2942
2976
len = arg_len - oneline_offset ;
2943
2977
} else {
2944
- strbuf_addf (& buf , "Merge branch '%.*s'" ,
2978
+ strbuf_addf (& buf , "Merge %s '%.*s'" ,
2979
+ to_merge -> next ? "branches" : "branch" ,
2945
2980
merge_arg_len , arg );
2946
2981
p = buf .buf ;
2947
2982
len = buf .len ;
@@ -2965,28 +3000,76 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2965
3000
& head_commit -> object .oid );
2966
3001
2967
3002
/*
2968
- * If the merge head is different from the original one, we cannot
3003
+ * If any merge head is different from the original one, we cannot
2969
3004
* fast-forward.
2970
3005
*/
2971
3006
if (can_fast_forward ) {
2972
- struct commit_list * second_parent = commit -> parents -> next ;
3007
+ struct commit_list * p = commit -> parents -> next ;
2973
3008
2974
- if (second_parent && !second_parent -> next &&
2975
- oidcmp (& merge_commit -> object .oid ,
2976
- & second_parent -> item -> object .oid ))
3009
+ for (j = to_merge ; j && p ; j = j -> next , p = p -> next )
3010
+ if (oidcmp (& j -> item -> object .oid ,
3011
+ & p -> item -> object .oid )) {
3012
+ can_fast_forward = 0 ;
3013
+ break ;
3014
+ }
3015
+ /*
3016
+ * If the number of merge heads differs from the original merge
3017
+ * commit, we cannot fast-forward.
3018
+ */
3019
+ if (j || p )
2977
3020
can_fast_forward = 0 ;
2978
3021
}
2979
3022
2980
- if (can_fast_forward && commit -> parents -> next &&
2981
- !commit -> parents -> next -> next &&
2982
- !oidcmp (& commit -> parents -> next -> item -> object .oid ,
2983
- & merge_commit -> object .oid )) {
3023
+ if (can_fast_forward ) {
2984
3024
rollback_lock_file (& lock );
2985
3025
ret = fast_forward_to (& commit -> object .oid ,
2986
3026
& head_commit -> object .oid , 0 , opts );
2987
3027
goto leave_merge ;
2988
3028
}
2989
3029
3030
+ if (to_merge -> next ) {
3031
+ /* Octopus merge */
3032
+ struct child_process cmd = CHILD_PROCESS_INIT ;
3033
+
3034
+ if (read_env_script (& cmd .env_array )) {
3035
+ const char * gpg_opt = gpg_sign_opt_quoted (opts );
3036
+
3037
+ ret = error (_ (staged_changes_advice ), gpg_opt , gpg_opt );
3038
+ goto leave_merge ;
3039
+ }
3040
+
3041
+ cmd .git_cmd = 1 ;
3042
+ argv_array_push (& cmd .args , "merge" );
3043
+ argv_array_push (& cmd .args , "-s" );
3044
+ argv_array_push (& cmd .args , "octopus" );
3045
+ argv_array_push (& cmd .args , "--no-edit" );
3046
+ argv_array_push (& cmd .args , "--no-ff" );
3047
+ argv_array_push (& cmd .args , "--no-log" );
3048
+ argv_array_push (& cmd .args , "--no-stat" );
3049
+ argv_array_push (& cmd .args , "-F" );
3050
+ argv_array_push (& cmd .args , git_path_merge_msg (the_repository ));
3051
+ if (opts -> gpg_sign )
3052
+ argv_array_push (& cmd .args , opts -> gpg_sign );
3053
+
3054
+ /* Add the tips to be merged */
3055
+ for (j = to_merge ; j ; j = j -> next )
3056
+ argv_array_push (& cmd .args ,
3057
+ oid_to_hex (& j -> item -> object .oid ));
3058
+
3059
+ strbuf_release (& ref_name );
3060
+ unlink (git_path_cherry_pick_head (the_repository ));
3061
+ rollback_lock_file (& lock );
3062
+
3063
+ rollback_lock_file (& lock );
3064
+ ret = run_command (& cmd );
3065
+
3066
+ /* force re-reading of the cache */
3067
+ if (!ret && (discard_cache () < 0 || read_cache () < 0 ))
3068
+ ret = error (_ ("could not read index" ));
3069
+ goto leave_merge ;
3070
+ }
3071
+
3072
+ merge_commit = to_merge -> item ;
2990
3073
write_message (oid_to_hex (& merge_commit -> object .oid ), GIT_SHA1_HEXSZ ,
2991
3074
git_path_merge_head (the_repository ), 0 );
2992
3075
write_message ("no-ff" , 5 , git_path_merge_mode (the_repository ), 0 );
@@ -3049,6 +3132,7 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
3049
3132
leave_merge :
3050
3133
strbuf_release (& ref_name );
3051
3134
rollback_lock_file (& lock );
3135
+ free_commit_list (to_merge );
3052
3136
return ret ;
3053
3137
}
3054
3138
@@ -3905,7 +3989,6 @@ static int make_script_with_merges(struct pretty_print_context *pp,
3905
3989
*/
3906
3990
while ((commit = get_revision (revs ))) {
3907
3991
struct commit_list * to_merge ;
3908
- int is_octopus ;
3909
3992
const char * p1 , * p2 ;
3910
3993
struct object_id * oid ;
3911
3994
int is_empty ;
@@ -3937,11 +4020,6 @@ static int make_script_with_merges(struct pretty_print_context *pp,
3937
4020
continue ;
3938
4021
}
3939
4022
3940
- is_octopus = to_merge && to_merge -> next ;
3941
-
3942
- if (is_octopus )
3943
- BUG ("Octopus merges not yet supported" );
3944
-
3945
4023
/* Create a label */
3946
4024
strbuf_reset (& label );
3947
4025
if (skip_prefix (oneline .buf , "Merge " , & p1 ) &&
@@ -3963,13 +4041,17 @@ static int make_script_with_merges(struct pretty_print_context *pp,
3963
4041
strbuf_addf (& buf , "%s -C %s" ,
3964
4042
cmd_merge , oid_to_hex (& commit -> object .oid ));
3965
4043
3966
- /* label the tip of merged branch */
3967
- oid = & to_merge -> item -> object .oid ;
3968
- strbuf_addch (& buf , ' ' );
4044
+ /* label the tips of merged branches */
4045
+ for (; to_merge ; to_merge = to_merge -> next ) {
4046
+ oid = & to_merge -> item -> object .oid ;
4047
+ strbuf_addch (& buf , ' ' );
4048
+
4049
+ if (!oidset_contains (& interesting , oid )) {
4050
+ strbuf_addstr (& buf , label_oid (oid , NULL ,
4051
+ & state ));
4052
+ continue ;
4053
+ }
3969
4054
3970
- if (!oidset_contains (& interesting , oid ))
3971
- strbuf_addstr (& buf , label_oid (oid , NULL , & state ));
3972
- else {
3973
4055
tips_tail = & commit_list_insert (to_merge -> item ,
3974
4056
tips_tail )-> next ;
3975
4057
0 commit comments