@@ -48,6 +48,30 @@ static GIT_PATH_FUNC(git_path_rebase_done, "rebase-merge/done")
4848 * need to be committed following a user interaction.
4949 */
5050static GIT_PATH_FUNC (git_path_rebase_msg , "rebase-merge/message" )
51+ /*
52+ * The file into which is accumulated the suggested commit message for
53+ * squash/fixup commands. When the first of a series of squash/fixups
54+ * is seen, the file is created and the commit message from the
55+ * previous commit and from the first squash/fixup commit are written
56+ * to it. The commit message for each subsequent squash/fixup commit
57+ * is appended to the file as it is processed.
58+ *
59+ * The first line of the file is of the form
60+ * # This is a combination of $count commits.
61+ * where $count is the number of commits whose messages have been
62+ * written to the file so far (including the initial "pick" commit).
63+ * Each time that a commit message is processed, this line is read and
64+ * updated. It is deleted just before the combined commit is made.
65+ */
66+ static GIT_PATH_FUNC (squash_msg , "rebase-merge/message-squash" )
67+ /*
68+ * If the current series of squash/fixups has not yet included a squash
69+ * command, then this file exists and holds the commit message of the
70+ * original "pick" commit. (If the series ends without a "squash"
71+ * command, then this can be used as the commit message of the combined
72+ * commit without opening the editor.)
73+ */
74+ static GIT_PATH_FUNC (fixup_msg , "rebase-merge/message-fixup" )
5175/*
5276 * A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
5377 * GIT_AUTHOR_DATE that will be used for the commit that is currently
@@ -591,6 +615,8 @@ enum todo_command {
591615 TODO_PICK ,
592616 TODO_REVERT ,
593617 TODO_EDIT ,
618+ TODO_FIXUP ,
619+ TODO_SQUASH ,
594620 TODO_EXEC ,
595621 TODO_NOOP
596622};
@@ -599,6 +625,8 @@ static const char *todo_command_strings[] = {
599625 "pick" ,
600626 "revert" ,
601627 "edit" ,
628+ "fixup" ,
629+ "squash" ,
602630 "exec" ,
603631 "noop"
604632};
@@ -610,16 +638,126 @@ static const char *command_to_string(const enum todo_command command)
610638 die ("Unknown command: %d" , command );
611639}
612640
641+ static int is_fixup (enum todo_command command )
642+ {
643+ return command == TODO_FIXUP || command == TODO_SQUASH ;
644+ }
645+
646+ static const char * nth_for_number (int n )
647+ {
648+ int n1 = n % 10 , n10 = n % 100 ;
649+
650+ if (n1 == 1 && n10 != 11 )
651+ return "st" ;
652+ if (n1 == 2 && n10 != 12 )
653+ return "nd" ;
654+ if (n1 == 3 && n10 != 13 )
655+ return "rd" ;
656+ return "th" ;
657+ }
658+
659+ static int update_squash_messages (enum todo_command command ,
660+ struct commit * commit , struct replay_opts * opts )
661+ {
662+ struct strbuf buf = STRBUF_INIT ;
663+ int count ;
664+ const char * message , * body ;
665+
666+ if (file_exists (squash_msg ())) {
667+ char * p , * p2 ;
668+
669+ if (strbuf_read_file (& buf , squash_msg (), 2048 ) <= 0 )
670+ return error ("Could not read %s" , squash_msg ());
671+
672+ if (buf .buf [0 ] == '\n' || !skip_prefix (buf .buf + 1 ,
673+ " This is a combination of " ,
674+ (const char * * )& p ))
675+ return error ("Unexpected 1st line of squash message:\n"
676+ "\n\t%.*s" ,
677+ (int )(strchrnul (buf .buf , '\n' ) - buf .buf ),
678+ buf .buf );
679+ count = strtol (p , & p2 , 10 );
680+
681+ if (count < 1 || * p2 != ' ' )
682+ return error ("Invalid 1st line of squash message:\n"
683+ "\n\t%.*s" ,
684+ (int )(strchrnul (buf .buf , '\n' ) - buf .buf ),
685+ buf .buf );
686+
687+ sprintf ((char * )p , "%d" , ++ count );
688+ if (!* p2 )
689+ * p2 = ' ' ;
690+ else {
691+ * (++ p2 ) = 'c' ;
692+ strbuf_insert (& buf , p2 - buf .buf , " " , 1 );
693+ }
694+ }
695+ else {
696+ unsigned char head [20 ];
697+ struct commit * head_commit ;
698+ const char * head_message , * body ;
699+
700+ if (get_sha1 ("HEAD" , head ))
701+ return error ("Need a HEAD to fixup" );
702+ if (!(head_commit = lookup_commit_reference (head )))
703+ return error ("Could not read HEAD" );
704+ if (!(head_message = get_commit_buffer (head_commit , NULL )))
705+ return error ("Could not read HEAD's commit message" );
706+
707+ body = strstr (head_message , "\n\n" );
708+ if (!body )
709+ body = "" ;
710+ if (write_file (fixup_msg (), body ))
711+ return error ("Cannot write %s" , fixup_msg ());
712+
713+ count = 2 ;
714+ strbuf_addf (& buf , "%c This is a combination of 2 commits.\n"
715+ "%c The first commit's message is:\n\n%s" ,
716+ comment_line_char , comment_line_char , body );
717+
718+ unuse_commit_buffer (head_commit , head_message );
719+ }
720+
721+ if (!(message = get_commit_buffer (commit , NULL )))
722+ return error ("Could not read commit message of %s" ,
723+ oid_to_hex (& commit -> object .oid ));
724+ body = strstr (message , "\n\n" );
725+ if (!body )
726+ body = "" ;
727+
728+ if (command == TODO_SQUASH ) {
729+ unlink (fixup_msg ());
730+ strbuf_addf (& buf , "\n%c This is the %d%s commit message:\n\n%s" ,
731+ comment_line_char ,
732+ count , nth_for_number (count ), body );
733+ }
734+ else if (command == TODO_FIXUP ) {
735+ strbuf_addf (& buf ,
736+ "\n%c The %d%s commit message will be skipped:\n\n" ,
737+ comment_line_char , count , nth_for_number (count ));
738+ strbuf_add_commented_lines (& buf , body , strlen (body ));
739+ }
740+ else
741+ return error ("Unknown command: %d" , command );
742+ unuse_commit_buffer (commit , message );
743+
744+ write_file (squash_msg (), "%s" , buf .buf );
745+ strbuf_release (& buf );
746+ return 0 ;
747+ }
748+
613749
614750static int do_pick_commit (enum todo_command command , struct commit * commit ,
615- struct replay_opts * opts )
751+ struct replay_opts * opts , int final_fixup )
616752{
753+ const char * msg_file = git_path_merge_msg ();
754+ int edit = opts -> edit ;
617755 unsigned char head [20 ];
618756 struct commit * base , * next , * parent ;
619757 const char * base_label , * next_label ;
620758 struct commit_message msg = { NULL , NULL , NULL , NULL };
621759 struct strbuf msgbuf = STRBUF_INIT ;
622- int res , unborn = 0 , allow ;
760+ int res , unborn = 0 , amend = 0 , allow ;
623761
624762 if (opts -> no_commit ) {
625763 /*
@@ -665,7 +803,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
665803 else
666804 parent = commit -> parents -> item ;
667805
668- if (opts -> allow_ff &&
806+ if (opts -> allow_ff && ! is_fixup ( command ) &&
669807 ((parent && !hashcmp (parent -> object .oid .hash , head )) ||
670808 (!parent && unborn )))
671809 return fast_forward_to (commit -> object .oid .hash , head , unborn , opts );
@@ -732,6 +870,27 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
732870 }
733871 }
734872
873+ if (is_fixup (command )) {
874+ /* TODO: reflog action */
875+ if (update_squash_messages (command , commit , opts ))
876+ return -1 ;
877+ amend = 1 ;
878+ if (!final_fixup )
879+ msg_file = squash_msg ();
880+ else if (file_exists (fixup_msg ()))
881+ msg_file = fixup_msg ();
882+ else {
883+ const char * dest = git_path ("SQUASH_MSG" );
884+ unlink (dest );
885+ if (copy_file (dest , squash_msg (), 0666 ))
886+ return error ("Could not rename %s to "
887+ "%s" , squash_msg (), dest );
888+ unlink (git_path ("MERGE_MSG" ));
889+ msg_file = dest ;
890+ edit = 1 ;
891+ }
892+ }
893+
735894 if (!opts -> strategy || !strcmp (opts -> strategy , "recursive" ) || command == TODO_REVERT ) {
736895 res = do_recursive_merge (base , next , base_label , next_label ,
737896 head , & msgbuf , opts );
@@ -779,8 +938,12 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
779938 goto leave ;
780939 }
781940 if (!opts -> no_commit )
782- res = sequencer_commit (git_path_merge_msg (), opts , allow ,
783- opts -> edit , 0 );
941+ res = sequencer_commit (msg_file , opts , allow , edit , amend );
942+
943+ if (!res && final_fixup ) {
944+ unlink (fixup_msg ());
945+ unlink (squash_msg ());
946+ }
784947
785948leave :
786949 free_message (commit , & msg );
@@ -915,7 +1078,7 @@ static int parse_insn_buffer(char *buf, struct todo_list *todo_list,
9151078{
9161079 struct todo_item * item ;
9171080 char * p = buf ;
918- int i ;
1081+ int i , fixup_okay = file_exists ( git_path_rebase_done ()) ;
9191082
9201083 for (i = 1 ; * p ; i ++ ) {
9211084 char * eol = strchrnul (p , '\n' );
@@ -924,6 +1087,13 @@ static int parse_insn_buffer(char *buf, struct todo_list *todo_list,
9241087 item -> offset_in_buf = p - todo_list -> buf .buf ;
9251088 if (parse_insn_line (item , p , eol , opts ))
9261089 return error (_ ("Could not parse line %d." ), i );
1090+ if (fixup_okay )
1091+ ; /* do nothing */
1092+ else if (is_fixup (item -> command ))
1093+ return error ("Cannot '%s' without a previous commit" ,
1094+ command_to_string (item -> command ));
1095+ else if (item -> command != TODO_NOOP )
1096+ fixup_okay = 1 ;
9271097 p = * eol ? eol + 1 : eol ;
9281098 }
9291099 if (!todo_list -> nr )
@@ -1249,6 +1419,22 @@ static int error_with_patch(struct commit *commit,
12491419 return exit_code ;
12501420}
12511421
1422+ static int error_failed_squash (struct commit * commit ,
1423+ struct replay_opts * opts , int subject_len , const char * subject )
1424+ {
1425+ if (rename (squash_msg (), git_path_rebase_msg ()))
1426+ return error ("Could not rename %s to %s" ,
1427+ squash_msg (), git_path_rebase_msg ());
1428+ unlink (fixup_msg ());
1429+ unlink (git_path ("MERGE_MSG" ));
1430+ if (copy_file (git_path ("MERGE_MSG" ), git_path_rebase_msg (), 0666 ))
1431+ return error ("Could not copy %s to %s" , git_path_rebase_msg (),
1432+ git_path ("MERGE_MSG" ));
1433+ warning ("\nCould not apply %s... %.*s" , short_commit_name (commit ),
1434+ subject_len , subject );
1435+ return error_with_patch (commit , opts , 1 );
1436+ }
1437+
12521438static int do_exec (const char * command_line )
12531439{
12541440 const char * child_argv [] = { NULL , NULL };
@@ -1286,6 +1472,21 @@ static int do_exec(const char *command_line)
12861472 return status ;
12871473}
12881474
1475+ static int is_final_fixup (struct todo_list * todo_list )
1476+ {
1477+ int i = todo_list -> current ;
1478+
1479+ if (!is_fixup (todo_list -> items [i ].command ))
1480+ return 0 ;
1481+
1482+ while (++ i < todo_list -> nr )
1483+ if (todo_list -> items [i ].command == TODO_NOOP )
1484+ continue ;
1485+ else if (is_fixup (todo_list -> items [i ].command ))
1486+ return 0 ;
1487+ return 1 ;
1488+ }
1489+
12891490static int pick_commits (struct todo_list * todo_list , struct replay_opts * opts )
12901491{
12911492 int res = 0 ;
@@ -1301,9 +1502,14 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
13011502 struct todo_item * item = todo_list -> items + todo_list -> current ;
13021503 if (save_todo (todo_list , opts ))
13031504 return -1 ;
1304- if (item -> command <= TODO_EDIT ) {
1505+ if (IS_REBASE_I ()) {
1506+ unlink (git_path_rebase_msg ());
1507+ unlink (author_script ());
1508+ unlink (stopped_sha ());
1509+ }
1510+ if (item -> command <= TODO_SQUASH ) {
13051511 res = do_pick_commit (item -> command , item -> commit ,
1306- opts );
1512+ opts , is_final_fixup ( todo_list ) );
13071513 if (item -> command == TODO_EDIT ) {
13081514 struct commit * commit = item -> commit ;
13091515 if (!res )
@@ -1312,6 +1518,9 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
13121518 item -> arg_len , item -> arg );
13131519 return error_with_patch (commit , opts , res );
13141520 }
1521+ if (res && is_fixup (item -> command ))
1522+ return error_failed_squash (item -> commit , opts ,
1523+ item -> arg_len , item -> arg );
13151524 }
13161525 else if (item -> command == TODO_EXEC ) {
13171526 char * end_of_arg = (char * )(item -> arg + item -> arg_len );
@@ -1403,7 +1612,7 @@ static int single_pick(struct commit *cmit, struct replay_opts *opts)
14031612{
14041613 setenv (GIT_REFLOG_ACTION , action_name (opts ), 0 );
14051614 return do_pick_commit (opts -> action == REPLAY_PICK ?
1406- TODO_PICK : TODO_REVERT , cmit , opts );
1615+ TODO_PICK : TODO_REVERT , cmit , opts , 0 );
14071616}
14081617
14091618int sequencer_pick_revisions (struct replay_opts * opts )
0 commit comments