@@ -123,6 +123,12 @@ static GIT_PATH_FUNC(rebase_path_rewritten_list, "rebase-merge/rewritten-list")
123
123
static GIT_PATH_FUNC (rebase_path_rewritten_pending ,
124
124
"rebase-merge/rewritten-pending" )
125
125
126
+ /*
127
+ * The path of the file containig the OID of the "squash onto" commit, i.e.
128
+ * the dummy commit used for `reset [new root]`.
129
+ */
130
+ static GIT_PATH_FUNC (rebase_path_squash_onto , "rebase-merge/squash-onto" )
131
+
126
132
/*
127
133
* The path of the file listing refs that need to be deleted after the rebase
128
134
* finishes. This is used by the `label` command to record the need for cleanup.
@@ -469,7 +475,8 @@ static int fast_forward_to(const struct object_id *to, const struct object_id *f
469
475
transaction = ref_transaction_begin (& err );
470
476
if (!transaction ||
471
477
ref_transaction_update (transaction , "HEAD" ,
472
- to , unborn ? & null_oid : from ,
478
+ to , unborn && !is_rebase_i (opts ) ?
479
+ & null_oid : from ,
473
480
0 , sb .buf , & err ) ||
474
481
ref_transaction_commit (transaction , & err )) {
475
482
ref_transaction_free (transaction );
@@ -561,9 +568,23 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
561
568
return !clean ;
562
569
}
563
570
571
+ static struct object_id * get_cache_tree_oid (void )
572
+ {
573
+ if (!active_cache_tree )
574
+ active_cache_tree = cache_tree ();
575
+
576
+ if (!cache_tree_fully_valid (active_cache_tree ))
577
+ if (cache_tree_update (& the_index , 0 )) {
578
+ error (_ ("unable to update cache tree" ));
579
+ return NULL ;
580
+ }
581
+
582
+ return & active_cache_tree -> oid ;
583
+ }
584
+
564
585
static int is_index_unchanged (void )
565
586
{
566
- struct object_id head_oid ;
587
+ struct object_id head_oid , * cache_tree_oid ;
567
588
struct commit * head_commit ;
568
589
569
590
if (!resolve_ref_unsafe ("HEAD" , RESOLVE_REF_READING , & head_oid , NULL ))
@@ -582,15 +603,10 @@ static int is_index_unchanged(void)
582
603
if (parse_commit (head_commit ))
583
604
return -1 ;
584
605
585
- if (!active_cache_tree )
586
- active_cache_tree = cache_tree ();
587
-
588
- if (!cache_tree_fully_valid (active_cache_tree ))
589
- if (cache_tree_update (& the_index , 0 ))
590
- return error (_ ("unable to update cache tree" ));
606
+ if (!(cache_tree_oid = get_cache_tree_oid ()))
607
+ return -1 ;
591
608
592
- return !oidcmp (& active_cache_tree -> oid ,
593
- get_commit_tree_oid (head_commit ));
609
+ return !oidcmp (cache_tree_oid , get_commit_tree_oid (head_commit ));
594
610
}
595
611
596
612
static int write_author_script (const char * message )
@@ -682,6 +698,52 @@ static char *get_author(const char *message)
682
698
return NULL ;
683
699
}
684
700
701
+ /* Read author-script and return an ident line (author <email> timestamp) */
702
+ static const char * read_author_ident (struct strbuf * buf )
703
+ {
704
+ const char * keys [] = {
705
+ "GIT_AUTHOR_NAME=" , "GIT_AUTHOR_EMAIL=" , "GIT_AUTHOR_DATE="
706
+ };
707
+ char * in , * out , * eol ;
708
+ int i = 0 , len ;
709
+
710
+ if (strbuf_read_file (buf , rebase_path_author_script (), 256 ) <= 0 )
711
+ return NULL ;
712
+
713
+ /* dequote values and construct ident line in-place */
714
+ for (in = out = buf -> buf ; i < 3 && in - buf -> buf < buf -> len ; i ++ ) {
715
+ if (!skip_prefix (in , keys [i ], (const char * * )& in )) {
716
+ warning ("could not parse '%s' (looking for '%s'" ,
717
+ rebase_path_author_script (), keys [i ]);
718
+ return NULL ;
719
+ }
720
+
721
+ eol = strchrnul (in , '\n' );
722
+ * eol = '\0' ;
723
+ sq_dequote (in );
724
+ len = strlen (in );
725
+
726
+ if (i > 0 ) /* separate values by spaces */
727
+ * (out ++ ) = ' ' ;
728
+ if (i == 1 ) /* email needs to be surrounded by <...> */
729
+ * (out ++ ) = '<' ;
730
+ memmove (out , in , len );
731
+ out += len ;
732
+ if (i == 1 ) /* email needs to be surrounded by <...> */
733
+ * (out ++ ) = '>' ;
734
+ in = eol + 1 ;
735
+ }
736
+
737
+ if (i < 3 ) {
738
+ warning ("could not parse '%s' (looking for '%s')" ,
739
+ rebase_path_author_script (), keys [i ]);
740
+ return NULL ;
741
+ }
742
+
743
+ buf -> len = out - buf -> buf ;
744
+ return buf -> buf ;
745
+ }
746
+
685
747
static const char staged_changes_advice [] =
686
748
N_ ("you have staged changes in your working tree\n"
687
749
"If these changes are meant to be squashed into the previous commit, run:\n"
@@ -701,6 +763,7 @@ N_("you have staged changes in your working tree\n"
701
763
#define AMEND_MSG (1<<2)
702
764
#define CLEANUP_MSG (1<<3)
703
765
#define VERIFY_MSG (1<<4)
766
+ #define CREATE_ROOT_COMMIT (1<<5)
704
767
705
768
/*
706
769
* If we are cherry-pick, and if the merge did not result in
@@ -720,6 +783,40 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
720
783
struct child_process cmd = CHILD_PROCESS_INIT ;
721
784
const char * value ;
722
785
786
+ if (flags & CREATE_ROOT_COMMIT ) {
787
+ struct strbuf msg = STRBUF_INIT , script = STRBUF_INIT ;
788
+ const char * author = is_rebase_i (opts ) ?
789
+ read_author_ident (& script ) : NULL ;
790
+ struct object_id root_commit , * cache_tree_oid ;
791
+ int res = 0 ;
792
+
793
+ if (!defmsg )
794
+ BUG ("root commit without message" );
795
+
796
+ if (!(cache_tree_oid = get_cache_tree_oid ()))
797
+ res = -1 ;
798
+
799
+ if (!res )
800
+ res = strbuf_read_file (& msg , defmsg , 0 );
801
+
802
+ if (res <= 0 )
803
+ res = error_errno (_ ("could not read '%s'" ), defmsg );
804
+ else
805
+ res = commit_tree (msg .buf , msg .len , cache_tree_oid ,
806
+ NULL , & root_commit , author ,
807
+ opts -> gpg_sign );
808
+
809
+ strbuf_release (& msg );
810
+ strbuf_release (& script );
811
+ if (!res ) {
812
+ update_ref (NULL , "CHERRY_PICK_HEAD" , & root_commit , NULL ,
813
+ REF_NO_DEREF , UPDATE_REFS_MSG_ON_ERR );
814
+ res = update_ref (NULL , "HEAD" , & root_commit , NULL , 0 ,
815
+ UPDATE_REFS_MSG_ON_ERR );
816
+ }
817
+ return res < 0 ? error (_ ("writing root commit" )) : 0 ;
818
+ }
819
+
723
820
cmd .git_cmd = 1 ;
724
821
725
822
if (is_rebase_i (opts )) {
@@ -1210,7 +1307,8 @@ static int do_commit(const char *msg_file, const char *author,
1210
1307
{
1211
1308
int res = 1 ;
1212
1309
1213
- if (!(flags & EDIT_MSG ) && !(flags & VERIFY_MSG )) {
1310
+ if (!(flags & EDIT_MSG ) && !(flags & VERIFY_MSG ) &&
1311
+ !(flags & CREATE_ROOT_COMMIT )) {
1214
1312
struct object_id oid ;
1215
1313
struct strbuf sb = STRBUF_INIT ;
1216
1314
@@ -1363,6 +1461,22 @@ static int is_fixup(enum todo_command command)
1363
1461
return command == TODO_FIXUP || command == TODO_SQUASH ;
1364
1462
}
1365
1463
1464
+ /* Does this command create a (non-merge) commit? */
1465
+ static int is_pick_or_similar (enum todo_command command )
1466
+ {
1467
+ switch (command ) {
1468
+ case TODO_PICK :
1469
+ case TODO_REVERT :
1470
+ case TODO_EDIT :
1471
+ case TODO_REWORD :
1472
+ case TODO_FIXUP :
1473
+ case TODO_SQUASH :
1474
+ return 1 ;
1475
+ default :
1476
+ return 0 ;
1477
+ }
1478
+ }
1479
+
1366
1480
static int update_squash_messages (enum todo_command command ,
1367
1481
struct commit * commit , struct replay_opts * opts )
1368
1482
{
@@ -1516,7 +1630,14 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
1516
1630
return error (_ ("your index file is unmerged." ));
1517
1631
} else {
1518
1632
unborn = get_oid ("HEAD" , & head );
1519
- if (unborn )
1633
+ /* Do we want to generate a root commit? */
1634
+ if (is_pick_or_similar (command ) && opts -> have_squash_onto &&
1635
+ !oidcmp (& head , & opts -> squash_onto )) {
1636
+ if (is_fixup (command ))
1637
+ return error (_ ("cannot fixup root commit" ));
1638
+ flags |= CREATE_ROOT_COMMIT ;
1639
+ unborn = 1 ;
1640
+ } else if (unborn )
1520
1641
oidcpy (& head , the_hash_algo -> empty_tree );
1521
1642
if (index_differs_from (unborn ? EMPTY_TREE_SHA1_HEX : "HEAD" ,
1522
1643
NULL , 0 ))
@@ -2142,6 +2263,12 @@ static int read_populate_opts(struct replay_opts *opts)
2142
2263
}
2143
2264
}
2144
2265
2266
+ if (read_oneliner (& buf , rebase_path_squash_onto (), 0 )) {
2267
+ if (get_oid_hex (buf .buf , & opts -> squash_onto ) < 0 )
2268
+ return error (_ ("unusable squash-onto" ));
2269
+ opts -> have_squash_onto = 1 ;
2270
+ }
2271
+
2145
2272
return 0 ;
2146
2273
}
2147
2274
@@ -2634,18 +2761,34 @@ static int do_reset(const char *name, int len, struct replay_opts *opts)
2634
2761
if (hold_locked_index (& lock , LOCK_REPORT_ON_ERROR ) < 0 )
2635
2762
return -1 ;
2636
2763
2637
- /* Determine the length of the label */
2638
- for (i = 0 ; i < len ; i ++ )
2639
- if (isspace (name [i ]))
2640
- len = i ;
2641
-
2642
- strbuf_addf (& ref_name , "refs/rewritten/%.*s" , len , name );
2643
- if (get_oid (ref_name .buf , & oid ) &&
2644
- get_oid (ref_name .buf + strlen ("refs/rewritten/" ), & oid )) {
2645
- error (_ ("could not read '%s'" ), ref_name .buf );
2646
- rollback_lock_file (& lock );
2647
- strbuf_release (& ref_name );
2648
- return -1 ;
2764
+ if (len == 10 && !strncmp ("[new root]" , name , len )) {
2765
+ if (!opts -> have_squash_onto ) {
2766
+ const char * hex ;
2767
+ if (commit_tree ("" , 0 , the_hash_algo -> empty_tree ,
2768
+ NULL , & opts -> squash_onto ,
2769
+ NULL , NULL ))
2770
+ return error (_ ("writing fake root commit" ));
2771
+ opts -> have_squash_onto = 1 ;
2772
+ hex = oid_to_hex (& opts -> squash_onto );
2773
+ if (write_message (hex , strlen (hex ),
2774
+ rebase_path_squash_onto (), 0 ))
2775
+ return error (_ ("writing squash-onto" ));
2776
+ }
2777
+ oidcpy (& oid , & opts -> squash_onto );
2778
+ } else {
2779
+ /* Determine the length of the label */
2780
+ for (i = 0 ; i < len ; i ++ )
2781
+ if (isspace (name [i ]))
2782
+ len = i ;
2783
+
2784
+ strbuf_addf (& ref_name , "refs/rewritten/%.*s" , len , name );
2785
+ if (get_oid (ref_name .buf , & oid ) &&
2786
+ get_oid (ref_name .buf + strlen ("refs/rewritten/" ), & oid )) {
2787
+ error (_ ("could not read '%s'" ), ref_name .buf );
2788
+ rollback_lock_file (& lock );
2789
+ strbuf_release (& ref_name );
2790
+ return -1 ;
2791
+ }
2649
2792
}
2650
2793
2651
2794
memset (& unpack_tree_opts , 0 , sizeof (unpack_tree_opts ));
@@ -2741,6 +2884,18 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
2741
2884
goto leave_merge ;
2742
2885
}
2743
2886
2887
+ if (opts -> have_squash_onto &&
2888
+ !oidcmp (& head_commit -> object .oid , & opts -> squash_onto )) {
2889
+ /*
2890
+ * When the user tells us to "merge" something into a
2891
+ * "[new root]", let's simply fast-forward to the merge head.
2892
+ */
2893
+ rollback_lock_file (& lock );
2894
+ ret = fast_forward_to (& merge_commit -> object .oid ,
2895
+ & head_commit -> object .oid , 0 , opts );
2896
+ goto leave_merge ;
2897
+ }
2898
+
2744
2899
if (commit ) {
2745
2900
const char * message = get_commit_buffer (commit , NULL );
2746
2901
const char * body ;
@@ -3850,7 +4005,8 @@ static int make_script_with_merges(struct pretty_print_context *pp,
3850
4005
}
3851
4006
3852
4007
if (!commit )
3853
- fprintf (out , "%s onto\n" , cmd_reset );
4008
+ fprintf (out , "%s %s\n" , cmd_reset ,
4009
+ rebase_cousins ? "onto" : "[new root]" );
3854
4010
else {
3855
4011
const char * to = NULL ;
3856
4012
0 commit comments