@@ -74,13 +74,6 @@ static GIT_PATH_FUNC(rebase_path_message, "rebase-merge/message")
74
74
* previous commit and from the first squash/fixup commit are written
75
75
* to it. The commit message for each subsequent squash/fixup commit
76
76
* is appended to the file as it is processed.
77
- *
78
- * The first line of the file is of the form
79
- * # This is a combination of $count commits.
80
- * where $count is the number of commits whose messages have been
81
- * written to the file so far (including the initial "pick" commit).
82
- * Each time that a commit message is processed, this line is read and
83
- * updated. It is deleted just before the combined commit is made.
84
77
*/
85
78
static GIT_PATH_FUNC (rebase_path_squash_msg , "rebase-merge/message-squash" )
86
79
/*
@@ -91,6 +84,11 @@ static GIT_PATH_FUNC(rebase_path_squash_msg, "rebase-merge/message-squash")
91
84
* commit without opening the editor.)
92
85
*/
93
86
static GIT_PATH_FUNC (rebase_path_fixup_msg , "rebase-merge/message-fixup" )
87
+ /*
88
+ * This file contains the list fixup/squash commands that have been
89
+ * accumulated into message-fixup or message-squash so far.
90
+ */
91
+ static GIT_PATH_FUNC (rebase_path_current_fixups , "rebase-merge/current-fixups" )
94
92
/*
95
93
* A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
96
94
* GIT_AUTHOR_DATE that will be used for the commit that is currently
@@ -253,6 +251,7 @@ int sequencer_remove_state(struct replay_opts *opts)
253
251
for (i = 0 ; i < opts -> xopts_nr ; i ++ )
254
252
free (opts -> xopts [i ]);
255
253
free (opts -> xopts );
254
+ strbuf_release (& opts -> current_fixups );
256
255
257
256
strbuf_addstr (& dir , get_dir (opts ));
258
257
remove_dir_recursively (& dir , 0 );
@@ -718,6 +717,8 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
718
717
argv_array_pushf (& cmd .args , "-S%s" , opts -> gpg_sign );
719
718
if (defmsg )
720
719
argv_array_pushl (& cmd .args , "-F" , defmsg , NULL );
720
+ else if (!(flags & EDIT_MSG ))
721
+ argv_array_pushl (& cmd .args , "-C" , "HEAD" , NULL );
721
722
if ((flags & CLEANUP_MSG ))
722
723
argv_array_push (& cmd .args , "--cleanup=strip" );
723
724
if ((flags & EDIT_MSG ))
@@ -1331,34 +1332,23 @@ static int update_squash_messages(enum todo_command command,
1331
1332
struct commit * commit , struct replay_opts * opts )
1332
1333
{
1333
1334
struct strbuf buf = STRBUF_INIT ;
1334
- int count , res ;
1335
+ int res ;
1335
1336
const char * message , * body ;
1336
1337
1337
- if (file_exists ( rebase_path_squash_msg ()) ) {
1338
+ if (opts -> current_fixup_count > 0 ) {
1338
1339
struct strbuf header = STRBUF_INIT ;
1339
- char * eol , * p ;
1340
+ char * eol ;
1340
1341
1341
- if (strbuf_read_file (& buf , rebase_path_squash_msg (), 2048 ) <= 0 )
1342
+ if (strbuf_read_file (& buf , rebase_path_squash_msg (), 9 ) <= 0 )
1342
1343
return error (_ ("could not read '%s'" ),
1343
1344
rebase_path_squash_msg ());
1344
1345
1345
- p = buf .buf + 1 ;
1346
- eol = strchrnul (buf .buf , '\n' );
1347
- if (buf .buf [0 ] != comment_line_char ||
1348
- (p += strcspn (p , "0123456789\n" )) == eol )
1349
- return error (_ ("unexpected 1st line of squash message:"
1350
- "\n\n\t%.*s" ),
1351
- (int )(eol - buf .buf ), buf .buf );
1352
- count = strtol (p , NULL , 10 );
1353
-
1354
- if (count < 1 )
1355
- return error (_ ("invalid 1st line of squash message:\n"
1356
- "\n\t%.*s" ),
1357
- (int )(eol - buf .buf ), buf .buf );
1346
+ eol = buf .buf [0 ] != comment_line_char ?
1347
+ buf .buf : strchrnul (buf .buf , '\n' );
1358
1348
1359
1349
strbuf_addf (& header , "%c " , comment_line_char );
1360
- strbuf_addf (& header ,
1361
- _ ( "This is a combination of %d commits." ), ++ count );
1350
+ strbuf_addf (& header , _ ( "This is a combination of %d commits." ),
1351
+ opts -> current_fixup_count + 2 );
1362
1352
strbuf_splice (& buf , 0 , eol - buf .buf , header .buf , header .len );
1363
1353
strbuf_release (& header );
1364
1354
} else {
@@ -1381,10 +1371,8 @@ static int update_squash_messages(enum todo_command command,
1381
1371
rebase_path_fixup_msg ());
1382
1372
}
1383
1373
1384
- count = 2 ;
1385
1374
strbuf_addf (& buf , "%c " , comment_line_char );
1386
- strbuf_addf (& buf , _ ("This is a combination of %d commits." ),
1387
- count );
1375
+ strbuf_addf (& buf , _ ("This is a combination of %d commits." ), 2 );
1388
1376
strbuf_addf (& buf , "\n%c " , comment_line_char );
1389
1377
strbuf_addstr (& buf , _ ("This is the 1st commit message:" ));
1390
1378
strbuf_addstr (& buf , "\n\n" );
@@ -1401,13 +1389,14 @@ static int update_squash_messages(enum todo_command command,
1401
1389
if (command == TODO_SQUASH ) {
1402
1390
unlink (rebase_path_fixup_msg ());
1403
1391
strbuf_addf (& buf , "\n%c " , comment_line_char );
1404
- strbuf_addf (& buf , _ ("This is the commit message #%d:" ), count );
1392
+ strbuf_addf (& buf , _ ("This is the commit message #%d:" ),
1393
+ ++ opts -> current_fixup_count );
1405
1394
strbuf_addstr (& buf , "\n\n" );
1406
1395
strbuf_addstr (& buf , body );
1407
1396
} else if (command == TODO_FIXUP ) {
1408
1397
strbuf_addf (& buf , "\n%c " , comment_line_char );
1409
1398
strbuf_addf (& buf , _ ("The commit message #%d will be skipped:" ),
1410
- count );
1399
+ ++ opts -> current_fixup_count );
1411
1400
strbuf_addstr (& buf , "\n\n" );
1412
1401
strbuf_add_commented_lines (& buf , body , strlen (body ));
1413
1402
} else
@@ -1416,6 +1405,17 @@ static int update_squash_messages(enum todo_command command,
1416
1405
1417
1406
res = write_message (buf .buf , buf .len , rebase_path_squash_msg (), 0 );
1418
1407
strbuf_release (& buf );
1408
+
1409
+ if (!res ) {
1410
+ strbuf_addf (& opts -> current_fixups , "%s%s %s" ,
1411
+ opts -> current_fixups .len ? "\n" : "" ,
1412
+ command_to_string (command ),
1413
+ oid_to_hex (& commit -> object .oid ));
1414
+ res = write_message (opts -> current_fixups .buf ,
1415
+ opts -> current_fixups .len ,
1416
+ rebase_path_current_fixups (), 0 );
1417
+ }
1418
+
1419
1419
return res ;
1420
1420
}
1421
1421
@@ -1678,6 +1678,9 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
1678
1678
if (!res && final_fixup ) {
1679
1679
unlink (rebase_path_fixup_msg ());
1680
1680
unlink (rebase_path_squash_msg ());
1681
+ unlink (rebase_path_current_fixups ());
1682
+ strbuf_reset (& opts -> current_fixups );
1683
+ opts -> current_fixup_count = 0 ;
1681
1684
}
1682
1685
1683
1686
leave :
@@ -2054,6 +2057,16 @@ static int read_populate_opts(struct replay_opts *opts)
2054
2057
read_strategy_opts (opts , & buf );
2055
2058
strbuf_release (& buf );
2056
2059
2060
+ if (read_oneliner (& opts -> current_fixups ,
2061
+ rebase_path_current_fixups (), 1 )) {
2062
+ const char * p = opts -> current_fixups .buf ;
2063
+ opts -> current_fixup_count = 1 ;
2064
+ while ((p = strchr (p , '\n' ))) {
2065
+ opts -> current_fixup_count ++ ;
2066
+ p ++ ;
2067
+ }
2068
+ }
2069
+
2057
2070
return 0 ;
2058
2071
}
2059
2072
@@ -2400,10 +2413,9 @@ static int error_with_patch(struct commit *commit,
2400
2413
static int error_failed_squash (struct commit * commit ,
2401
2414
struct replay_opts * opts , int subject_len , const char * subject )
2402
2415
{
2403
- if (rename ( rebase_path_squash_msg (), rebase_path_message () ))
2404
- return error (_ ("could not rename '%s' to '%s'" ),
2416
+ if (copy_file ( rebase_path_message (), rebase_path_squash_msg (), 0666 ))
2417
+ return error (_ ("could not copy '%s' to '%s'" ),
2405
2418
rebase_path_squash_msg (), rebase_path_message ());
2406
- unlink (rebase_path_fixup_msg ());
2407
2419
unlink (git_path_merge_msg ());
2408
2420
if (copy_file (git_path_merge_msg (), rebase_path_message (), 0666 ))
2409
2421
return error (_ ("could not copy '%s' to '%s'" ),
@@ -2769,19 +2781,16 @@ static int continue_single_pick(void)
2769
2781
return run_command_v_opt (argv , RUN_GIT_CMD );
2770
2782
}
2771
2783
2772
- static int commit_staged_changes (struct replay_opts * opts )
2784
+ static int commit_staged_changes (struct replay_opts * opts ,
2785
+ struct todo_list * todo_list )
2773
2786
{
2774
2787
unsigned int flags = ALLOW_EMPTY | EDIT_MSG ;
2788
+ unsigned int final_fixup = 0 , is_clean ;
2775
2789
2776
2790
if (has_unstaged_changes (1 ))
2777
2791
return error (_ ("cannot rebase: You have unstaged changes." ));
2778
- if (!has_uncommitted_changes (0 )) {
2779
- const char * cherry_pick_head = git_path_cherry_pick_head ();
2780
2792
2781
- if (file_exists (cherry_pick_head ) && unlink (cherry_pick_head ))
2782
- return error (_ ("could not remove CHERRY_PICK_HEAD" ));
2783
- return 0 ;
2784
- }
2793
+ is_clean = !has_uncommitted_changes (0 );
2785
2794
2786
2795
if (file_exists (rebase_path_amend ())) {
2787
2796
struct strbuf rev = STRBUF_INIT ;
@@ -2794,19 +2803,107 @@ static int commit_staged_changes(struct replay_opts *opts)
2794
2803
if (get_oid_hex (rev .buf , & to_amend ))
2795
2804
return error (_ ("invalid contents: '%s'" ),
2796
2805
rebase_path_amend ());
2797
- if (oidcmp (& head , & to_amend ))
2806
+ if (! is_clean && oidcmp (& head , & to_amend ))
2798
2807
return error (_ ("\nYou have uncommitted changes in your "
2799
2808
"working tree. Please, commit them\n"
2800
2809
"first and then run 'git rebase "
2801
2810
"--continue' again." ));
2811
+ /*
2812
+ * When skipping a failed fixup/squash, we need to edit the
2813
+ * commit message, the current fixup list and count, and if it
2814
+ * was the last fixup/squash in the chain, we need to clean up
2815
+ * the commit message and if there was a squash, let the user
2816
+ * edit it.
2817
+ */
2818
+ if (is_clean && !oidcmp (& head , & to_amend ) &&
2819
+ opts -> current_fixup_count > 0 &&
2820
+ file_exists (rebase_path_stopped_sha ())) {
2821
+ const char * p = opts -> current_fixups .buf ;
2822
+ int len = opts -> current_fixups .len ;
2823
+
2824
+ opts -> current_fixup_count -- ;
2825
+ if (!len )
2826
+ BUG ("Incorrect current_fixups:\n%s" , p );
2827
+ while (len && p [len - 1 ] != '\n' )
2828
+ len -- ;
2829
+ strbuf_setlen (& opts -> current_fixups , len );
2830
+ if (write_message (p , len , rebase_path_current_fixups (),
2831
+ 0 ) < 0 )
2832
+ return error (_ ("could not write file: '%s'" ),
2833
+ rebase_path_current_fixups ());
2834
+
2835
+ /*
2836
+ * If a fixup/squash in a fixup/squash chain failed, the
2837
+ * commit message is already correct, no need to commit
2838
+ * it again.
2839
+ *
2840
+ * Only if it is the final command in the fixup/squash
2841
+ * chain, and only if the chain is longer than a single
2842
+ * fixup/squash command (which was just skipped), do we
2843
+ * actually need to re-commit with a cleaned up commit
2844
+ * message.
2845
+ */
2846
+ if (opts -> current_fixup_count > 0 &&
2847
+ !is_fixup (peek_command (todo_list , 0 ))) {
2848
+ final_fixup = 1 ;
2849
+ /*
2850
+ * If there was not a single "squash" in the
2851
+ * chain, we only need to clean up the commit
2852
+ * message, no need to bother the user with
2853
+ * opening the commit message in the editor.
2854
+ */
2855
+ if (!starts_with (p , "squash " ) &&
2856
+ !strstr (p , "\nsquash " ))
2857
+ flags = (flags & ~EDIT_MSG ) | CLEANUP_MSG ;
2858
+ } else if (is_fixup (peek_command (todo_list , 0 ))) {
2859
+ /*
2860
+ * We need to update the squash message to skip
2861
+ * the latest commit message.
2862
+ */
2863
+ struct commit * commit ;
2864
+ const char * path = rebase_path_squash_msg ();
2865
+
2866
+ if (parse_head (& commit ) ||
2867
+ !(p = get_commit_buffer (commit , NULL )) ||
2868
+ write_message (p , strlen (p ), path , 0 )) {
2869
+ unuse_commit_buffer (commit , p );
2870
+ return error (_ ("could not write file: "
2871
+ "'%s'" ), path );
2872
+ }
2873
+ unuse_commit_buffer (commit , p );
2874
+ }
2875
+ }
2802
2876
2803
2877
strbuf_release (& rev );
2804
2878
flags |= AMEND_MSG ;
2805
2879
}
2806
2880
2807
- if (run_git_commit (rebase_path_message (), opts , flags ))
2881
+ if (is_clean ) {
2882
+ const char * cherry_pick_head = git_path_cherry_pick_head ();
2883
+
2884
+ if (file_exists (cherry_pick_head ) && unlink (cherry_pick_head ))
2885
+ return error (_ ("could not remove CHERRY_PICK_HEAD" ));
2886
+ if (!final_fixup )
2887
+ return 0 ;
2888
+ }
2889
+
2890
+ if (run_git_commit (final_fixup ? NULL : rebase_path_message (),
2891
+ opts , flags ))
2808
2892
return error (_ ("could not commit staged changes." ));
2809
2893
unlink (rebase_path_amend ());
2894
+ if (final_fixup ) {
2895
+ unlink (rebase_path_fixup_msg ());
2896
+ unlink (rebase_path_squash_msg ());
2897
+ }
2898
+ if (opts -> current_fixup_count > 0 ) {
2899
+ /*
2900
+ * Whether final fixup or not, we just cleaned up the commit
2901
+ * message...
2902
+ */
2903
+ unlink (rebase_path_current_fixups ());
2904
+ strbuf_reset (& opts -> current_fixups );
2905
+ opts -> current_fixup_count = 0 ;
2906
+ }
2810
2907
return 0 ;
2811
2908
}
2812
2909
@@ -2818,14 +2915,16 @@ int sequencer_continue(struct replay_opts *opts)
2818
2915
if (read_and_refresh_cache (opts ))
2819
2916
return -1 ;
2820
2917
2918
+ if (read_populate_opts (opts ))
2919
+ return -1 ;
2821
2920
if (is_rebase_i (opts )) {
2822
- if (commit_staged_changes (opts ))
2921
+ if ((res = read_populate_todo (& todo_list , opts )))
2922
+ goto release_todo_list ;
2923
+ if (commit_staged_changes (opts , & todo_list ))
2823
2924
return -1 ;
2824
2925
} else if (!file_exists (get_todo_path (opts )))
2825
2926
return continue_single_pick ();
2826
- if (read_populate_opts (opts ))
2827
- return -1 ;
2828
- if ((res = read_populate_todo (& todo_list , opts )))
2927
+ else if ((res = read_populate_todo (& todo_list , opts )))
2829
2928
goto release_todo_list ;
2830
2929
2831
2930
if (!is_rebase_i (opts )) {
0 commit comments