@@ -702,12 +702,17 @@ static int run_specific_rebase(struct rebase_options *opts)
702702
703703#define GIT_REFLOG_ACTION_ENVIRONMENT "GIT_REFLOG_ACTION"
704704
705+ #define RESET_HEAD_DETACH (1<<0)
706+ #define RESET_HEAD_HARD (1<<1)
707+
705708static int reset_head (struct object_id * oid , const char * action ,
706- const char * switch_to_branch , int detach_head ,
709+ const char * switch_to_branch , unsigned flags ,
707710 const char * reflog_orig_head , const char * reflog_head )
708711{
712+ unsigned detach_head = flags & RESET_HEAD_DETACH ;
713+ unsigned reset_hard = flags & RESET_HEAD_HARD ;
709714 struct object_id head_oid ;
710- struct tree_desc desc ;
715+ struct tree_desc desc [ 2 ] = { { NULL }, { NULL } } ;
711716 struct lock_file lock = LOCK_INIT ;
712717 struct unpack_trees_options unpack_tree_opts ;
713718 struct tree * tree ;
@@ -716,60 +721,62 @@ static int reset_head(struct object_id *oid, const char *action,
716721 size_t prefix_len ;
717722 struct object_id * orig = NULL , oid_orig ,
718723 * old_orig = NULL , oid_old_orig ;
719- int ret = 0 ;
724+ int ret = 0 , nr = 0 ;
720725
721726 if (switch_to_branch && !starts_with (switch_to_branch , "refs/" ))
722727 BUG ("Not a fully qualified branch: '%s'" , switch_to_branch );
723728
724- if (hold_locked_index (& lock , LOCK_REPORT_ON_ERROR ) < 0 )
725- return -1 ;
729+ if (hold_locked_index (& lock , LOCK_REPORT_ON_ERROR ) < 0 ) {
730+ ret = -1 ;
731+ goto leave_reset_head ;
732+ }
726733
727- if (!oid ) {
728- if (get_oid ("HEAD" , & head_oid )) {
729- rollback_lock_file (& lock );
730- return error (_ ("could not determine HEAD revision" ));
731- }
732- oid = & head_oid ;
734+ if ((!oid || !reset_hard ) && get_oid ("HEAD" , & head_oid )) {
735+ ret = error (_ ("could not determine HEAD revision" ));
736+ goto leave_reset_head ;
733737 }
734738
739+ if (!oid )
740+ oid = & head_oid ;
741+
735742 memset (& unpack_tree_opts , 0 , sizeof (unpack_tree_opts ));
736743 setup_unpack_trees_porcelain (& unpack_tree_opts , action );
737744 unpack_tree_opts .head_idx = 1 ;
738745 unpack_tree_opts .src_index = the_repository -> index ;
739746 unpack_tree_opts .dst_index = the_repository -> index ;
740- unpack_tree_opts .fn = oneway_merge ;
747+ unpack_tree_opts .fn = reset_hard ? oneway_merge : twoway_merge ;
741748 unpack_tree_opts .update = 1 ;
742749 unpack_tree_opts .merge = 1 ;
743750 if (!detach_head )
744751 unpack_tree_opts .reset = 1 ;
745752
746753 if (read_index_unmerged (the_repository -> index ) < 0 ) {
747- rollback_lock_file ( & lock );
748- return error ( _ ( "could not read index" )) ;
754+ ret = error ( _ ( "could not read index" ) );
755+ goto leave_reset_head ;
749756 }
750757
751- if (!fill_tree_descriptor (& desc , oid )) {
752- error (_ ("failed to find tree of %s" ), oid_to_hex (oid ));
753- rollback_lock_file (& lock );
754- free ((void * )desc .buffer );
755- return -1 ;
758+ if (!reset_hard && !fill_tree_descriptor (& desc [nr ++ ], & head_oid )) {
759+ ret = error (_ ("failed to find tree of %s" ), oid_to_hex (oid ));
760+ goto leave_reset_head ;
756761 }
757762
758- if (unpack_trees (1 , & desc , & unpack_tree_opts )) {
759- rollback_lock_file (& lock );
760- free ((void * )desc .buffer );
761- return -1 ;
763+ if (!fill_tree_descriptor (& desc [nr ++ ], oid )) {
764+ ret = error (_ ("failed to find tree of %s" ), oid_to_hex (oid ));
765+ goto leave_reset_head ;
766+ }
767+
768+ if (unpack_trees (nr , desc , & unpack_tree_opts )) {
769+ ret = -1 ;
770+ goto leave_reset_head ;
762771 }
763772
764773 tree = parse_tree_indirect (oid );
765774 prime_cache_tree (the_repository -> index , tree );
766775
767- if (write_locked_index (the_repository -> index , & lock , COMMIT_LOCK ) < 0 )
776+ if (write_locked_index (the_repository -> index , & lock , COMMIT_LOCK ) < 0 ) {
768777 ret = error (_ ("could not write index" ));
769- free ((void * )desc .buffer );
770-
771- if (ret )
772- return ret ;
778+ goto leave_reset_head ;
779+ }
773780
774781 reflog_action = getenv (GIT_REFLOG_ACTION_ENVIRONMENT );
775782 strbuf_addf (& msg , "%s: " , reflog_action ? reflog_action : "rebase" );
@@ -803,7 +810,11 @@ static int reset_head(struct object_id *oid, const char *action,
803810 UPDATE_REFS_MSG_ON_ERR );
804811 }
805812
813+ leave_reset_head :
806814 strbuf_release (& msg );
815+ rollback_lock_file (& lock );
816+ while (nr )
817+ free ((void * )desc [-- nr ].buffer );
807818 return ret ;
808819}
809820
@@ -1181,7 +1192,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
11811192 rerere_clear (& merge_rr );
11821193 string_list_clear (& merge_rr , 1 );
11831194
1184- if (reset_head (NULL , "reset" , NULL , 0 , NULL , NULL ) < 0 )
1195+ if (reset_head (NULL , "reset" , NULL , RESET_HEAD_HARD ,
1196+ NULL , NULL ) < 0 )
11851197 die (_ ("could not discard worktree changes" ));
11861198 remove_branch_state ();
11871199 if (read_basic_state (& options ))
@@ -1198,7 +1210,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
11981210 if (read_basic_state (& options ))
11991211 exit (1 );
12001212 if (reset_head (& options .orig_head , "reset" ,
1201- options .head_name , 0 , NULL , NULL ) < 0 )
1213+ options .head_name , RESET_HEAD_HARD ,
1214+ NULL , NULL ) < 0 )
12021215 die (_ ("could not move back to %s" ),
12031216 oid_to_hex (& options .orig_head ));
12041217 remove_branch_state ();
@@ -1563,7 +1576,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
15631576 write_file (autostash , "%s" , oid_to_hex (& oid ));
15641577 printf (_ ("Created autostash: %s\n" ), buf .buf );
15651578 if (reset_head (& head -> object .oid , "reset --hard" ,
1566- NULL , 0 , NULL , NULL ) < 0 )
1579+ NULL , RESET_HEAD_HARD , NULL , NULL ) < 0 )
15671580 die (_ ("could not reset --hard" ));
15681581 printf (_ ("HEAD is now at %s" ),
15691582 find_unique_abbrev (& head -> object .oid ,
@@ -1683,8 +1696,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
16831696 "it...\n" ));
16841697
16851698 strbuf_addf (& msg , "rebase: checkout %s" , options .onto_name );
1686- if (reset_head (& options .onto -> object .oid , "checkout" , NULL , 1 ,
1687- NULL , msg .buf ))
1699+ if (reset_head (& options .onto -> object .oid , "checkout" , NULL ,
1700+ RESET_HEAD_DETACH , NULL , msg .buf ))
16881701 die (_ ("Could not detach HEAD" ));
16891702 strbuf_release (& msg );
16901703
0 commit comments