1717#include "merge-ll.h"
1818#include "lockfile.h"
1919#include "mem-pool.h"
20- #include "merge-ort-wrappers.h"
2120#include "object-file.h"
2221#include "object-name.h"
2322#include "odb.h"
3029#include "repo-settings.h"
3130#include "resolve-undo.h"
3231#include "revision.h"
32+ #include "sequencer.h"
3333#include "setup.h"
3434#include "submodule.h"
3535#include "symlinks.h"
@@ -99,6 +99,8 @@ struct checkout_opts {
9999 .auto_advance = 1, \
100100}
101101
102+ #define MERGE_WORKING_TREE_UNPACK_FAILED (-2)
103+
102104struct branch_info {
103105 char * name ; /* The short name used */
104106 char * path ; /* The full name of a real branch */
@@ -753,9 +755,9 @@ static void setup_branch_path(struct branch_info *branch)
753755 branch -> path = strbuf_detach (& buf , NULL );
754756}
755757
756- static void init_topts (struct unpack_trees_options * topts , int merge ,
758+ static void init_topts (struct unpack_trees_options * topts ,
757759 int show_progress , int overwrite_ignore ,
758- struct commit * old_commit )
760+ bool quiet )
759761{
760762 memset (topts , 0 , sizeof (* topts ));
761763 topts -> head_idx = -1 ;
@@ -767,7 +769,7 @@ static void init_topts(struct unpack_trees_options *topts, int merge,
767769 topts -> initial_checkout = is_index_unborn (the_repository -> index );
768770 topts -> update = 1 ;
769771 topts -> merge = 1 ;
770- topts -> quiet = merge && old_commit ;
772+ topts -> quiet = quiet ;
771773 topts -> verbose_update = show_progress ;
772774 topts -> fn = twoway_merge ;
773775 topts -> preserve_ignored = !overwrite_ignore ;
@@ -776,6 +778,7 @@ static void init_topts(struct unpack_trees_options *topts, int merge,
776778static int merge_working_tree (const struct checkout_opts * opts ,
777779 struct branch_info * old_branch_info ,
778780 struct branch_info * new_branch_info ,
781+ bool quiet ,
779782 int * writeout_error )
780783{
781784 int ret ;
@@ -826,8 +829,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
826829 }
827830
828831 /* 2-way merge to the new branch */
829- init_topts (& topts , opts -> merge , opts -> show_progress ,
830- opts -> overwrite_ignore , old_branch_info -> commit );
832+ init_topts (& topts , opts -> show_progress ,
833+ opts -> overwrite_ignore , quiet );
831834 init_checkout_metadata (& topts .meta , new_branch_info -> refname ,
832835 new_branch_info -> commit ?
833836 & new_branch_info -> commit -> object .oid :
@@ -853,90 +856,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
853856 ret = unpack_trees (2 , trees , & topts );
854857 clear_unpack_trees_porcelain (& topts );
855858 if (ret == -1 ) {
856- /*
857- * Unpack couldn't do a trivial merge; either
858- * give up or do a real merge, depending on
859- * whether the merge flag was used.
860- */
861- struct tree * work ;
862- struct tree * old_tree ;
863- struct merge_options o ;
864- struct strbuf sb = STRBUF_INIT ;
865- struct strbuf old_commit_shortname = STRBUF_INIT ;
866-
867- if (!opts -> merge ) {
868- rollback_lock_file (& lock_file );
869- return 1 ;
870- }
871-
872- /*
873- * Without old_branch_info->commit, the below is the same as
874- * the two-tree unpack we already tried and failed.
875- */
876- if (!old_branch_info -> commit ) {
877- rollback_lock_file (& lock_file );
878- return 1 ;
879- }
880- old_tree = repo_get_commit_tree (the_repository ,
881- old_branch_info -> commit );
882-
883- if (repo_index_has_changes (the_repository , old_tree , & sb ))
884- die (_ ("cannot continue with staged changes in "
885- "the following files:\n%s" ), sb .buf );
886- strbuf_release (& sb );
887-
888- /* Do more real merge */
889-
890- /*
891- * We update the index fully, then write the
892- * tree from the index, then merge the new
893- * branch with the current tree, with the old
894- * branch as the base. Then we reset the index
895- * (but not the working tree) to the new
896- * branch, leaving the working tree as the
897- * merged version, but skipping unmerged
898- * entries in the index.
899- */
900-
901- add_files_to_cache (the_repository , NULL , NULL , NULL , 0 ,
902- 0 , 0 );
903- init_ui_merge_options (& o , the_repository );
904- o .verbosity = 0 ;
905- work = write_in_core_index_as_tree (the_repository ,
906- the_repository -> index );
907-
908- ret = reset_tree (new_tree ,
909- opts , 1 ,
910- writeout_error , new_branch_info );
911- if (ret ) {
912- rollback_lock_file (& lock_file );
913- return ret ;
914- }
915- o .ancestor = old_branch_info -> name ;
916- if (!old_branch_info -> name ) {
917- strbuf_add_unique_abbrev (& old_commit_shortname ,
918- & old_branch_info -> commit -> object .oid ,
919- DEFAULT_ABBREV );
920- o .ancestor = old_commit_shortname .buf ;
921- }
922- o .branch1 = new_branch_info -> name ;
923- o .branch2 = "local" ;
924- o .conflict_style = opts -> conflict_style ;
925- ret = merge_ort_nonrecursive (& o ,
926- new_tree ,
927- work ,
928- old_tree );
929- if (ret < 0 )
930- die (NULL );
931- ret = reset_tree (new_tree ,
932- opts , 0 ,
933- writeout_error , new_branch_info );
934- strbuf_release (& o .obuf );
935- strbuf_release (& old_commit_shortname );
936- if (ret ) {
937- rollback_lock_file (& lock_file );
938- return ret ;
939- }
859+ rollback_lock_file (& lock_file );
860+ return MERGE_WORKING_TREE_UNPACK_FAILED ;
940861 }
941862 }
942863
@@ -1181,6 +1102,10 @@ static int switch_branches(const struct checkout_opts *opts,
11811102 struct object_id rev ;
11821103 int flag , writeout_error = 0 ;
11831104 int do_merge = 1 ;
1105+ int created_autostash = 0 ;
1106+ struct strbuf old_commit_shortname = STRBUF_INIT ;
1107+ struct strbuf autostash_msg = STRBUF_INIT ;
1108+ const char * stash_label_base = NULL ;
11841109
11851110 trace2_cmd_mode ("branch" );
11861111
@@ -1218,11 +1143,49 @@ static int switch_branches(const struct checkout_opts *opts,
12181143 do_merge = 0 ;
12191144 }
12201145
1146+ if (old_branch_info .name ) {
1147+ stash_label_base = old_branch_info .name ;
1148+ } else if (old_branch_info .commit ) {
1149+ strbuf_add_unique_abbrev (& old_commit_shortname ,
1150+ & old_branch_info .commit -> object .oid ,
1151+ DEFAULT_ABBREV );
1152+ stash_label_base = old_commit_shortname .buf ;
1153+ }
1154+
12211155 if (do_merge ) {
1222- ret = merge_working_tree (opts , & old_branch_info , new_branch_info , & writeout_error );
1156+ ret = merge_working_tree (opts , & old_branch_info , new_branch_info ,
1157+ opts -> merge , & writeout_error );
1158+ if (ret == MERGE_WORKING_TREE_UNPACK_FAILED && opts -> merge ) {
1159+ strbuf_addf (& autostash_msg ,
1160+ "autostash while switching to '%s'" ,
1161+ new_branch_info -> name );
1162+ create_autostash_ref (the_repository ,
1163+ "CHECKOUT_AUTOSTASH_HEAD" ,
1164+ autostash_msg .buf , true);
1165+ created_autostash = 1 ;
1166+ ret = merge_working_tree (opts , & old_branch_info , new_branch_info ,
1167+ false, & writeout_error );
1168+ }
1169+ if (created_autostash ) {
1170+ if (opts -> conflict_style >= 0 ) {
1171+ struct strbuf cfg = STRBUF_INIT ;
1172+ strbuf_addf (& cfg , "merge.conflictStyle=%s" ,
1173+ conflict_style_name (opts -> conflict_style ));
1174+ git_config_push_parameter (cfg .buf );
1175+ strbuf_release (& cfg );
1176+ }
1177+ apply_autostash_ref (the_repository ,
1178+ "CHECKOUT_AUTOSTASH_HEAD" ,
1179+ new_branch_info -> name ,
1180+ "local" ,
1181+ stash_label_base ,
1182+ autostash_msg .buf );
1183+ }
12231184 if (ret ) {
12241185 branch_info_release (& old_branch_info );
1225- return ret ;
1186+ strbuf_release (& old_commit_shortname );
1187+ strbuf_release (& autostash_msg );
1188+ return ret < 0 ? 1 : ret ;
12261189 }
12271190 }
12281191
@@ -1231,8 +1194,22 @@ static int switch_branches(const struct checkout_opts *opts,
12311194
12321195 update_refs_for_switch (opts , & old_branch_info , new_branch_info );
12331196
1197+ if (created_autostash ) {
1198+ discard_index (the_repository -> index );
1199+ if (repo_read_index (the_repository ) < 0 )
1200+ die (_ ("index file corrupt" ));
1201+
1202+ if (!opts -> quiet && new_branch_info -> commit ) {
1203+ printf (_ ("The following paths have local changes:\n" ));
1204+ show_local_changes (& new_branch_info -> commit -> object ,
1205+ & opts -> diff_options );
1206+ }
1207+ }
1208+
12341209 ret = post_checkout_hook (old_branch_info .commit , new_branch_info -> commit , 1 );
12351210 branch_info_release (& old_branch_info );
1211+ strbuf_release (& old_commit_shortname );
1212+ strbuf_release (& autostash_msg );
12361213
12371214 return ret || writeout_error ;
12381215}
0 commit comments