24
#include "submodule-config.h"
25
#include "submodule.h"
26
27
+static int checkout_optimize_new_branch;
28
+
29
static const char * const checkout_usage[] = {
30
N_("git checkout [<options>] <branch>"),
31
N_("git checkout [<options>] [<branch>] -- <file>..."),
43
int ignore_skipworktree;
44
int ignore_other_worktrees;
45
int show_progress;
46
+ /*
47
+ * If new checkout options are added, skip_merge_working_tree
48
+ * should be updated accordingly.
49
+ */
50
51
const char *new_branch;
52
const char *new_branch_force;
477
branch->path = strbuf_detach(&buf, NULL);
478
}
479
480
+/*
481
+ * Skip merging the trees, updating the index and working directory if and
482
+ * only if we are creating a new branch via "git checkout -b <new_branch>."
483
+ */
484
+static int skip_merge_working_tree(const struct checkout_opts *opts,
485
+ const struct branch_info *old_branch_info,
486
+ const struct branch_info *new_branch_info)
487
+{
488
+ /*
489
+ * Do the merge if sparse checkout is on and the user has not opted in
490
+ * to the optimized behavior
491
+ */
492
+ if (core_apply_sparse_checkout && !checkout_optimize_new_branch)
493
+ return 0;
494
+
495
+ /*
496
+ * We must do the merge if we are actually moving to a new commit.
497
+ */
498
+ if (!old_branch_info->commit || !new_branch_info->commit ||
499
+ oidcmp(&old_branch_info->commit->object.oid, &new_branch_info->commit->object.oid))
500
+ return 0;
501
+
502
+ /*
503
+ * opts->patch_mode cannot be used with switching branches so is
504
+ * not tested here
505
+ */
506
+
507
+ /*
508
+ * opts->quiet only impacts output so doesn't require a merge
509
+ */
510
+
511
+ /*
512
+ * Honor the explicit request for a three-way merge or to throw away
513
+ * local changes
514
+ */
515
+ if (opts->merge || opts->force)
516
+ return 0;
517
+
518
+ /*
519
+ * --detach is documented as "updating the index and the files in the
520
+ * working tree" but this optimization skips those steps so fall through
521
+ * to the regular code path.
522
+ */
523
+ if (opts->force_detach)
524
+ return 0;
525
+
526
+ /*
527
+ * opts->writeout_stage cannot be used with switching branches so is
528
+ * not tested here
529
+ */
530
+
531
+ /*
532
+ * Honor the explicit ignore requests
533
+ */
534
+ if (!opts->overwrite_ignore || opts->ignore_skipworktree ||
535
+ opts->ignore_other_worktrees)
536
+ return 0;
537
+
538
+ /*
539
+ * opts->show_progress only impacts output so doesn't require a merge
540
+ */
541
+
542
+ /*
543
+ * If we aren't creating a new branch any changes or updates will
544
+ * happen in the existing branch. Since that could only be updating
545
+ * the index and working directory, we don't want to skip those steps
546
+ * or we've defeated any purpose in running the command.
547
+ */
548
+ if (!opts->new_branch)
549
+ return 0;
550
+
551
+ /*
552
+ * new_branch_force is defined to "create/reset and checkout a branch"
553
+ * so needs to go through the merge to do the reset
554
+ */
555
+ if (opts->new_branch_force)
556
+ return 0;
557
+
558
+ /*
559
+ * A new orphaned branch requrires the index and the working tree to be
560
+ * adjusted to <start_point>
561
+ */
562
+ if (opts->new_orphan_branch)
563
+ return 0;
564
+
565
+ /*
566
+ * Remaining variables are not checkout options but used to track state
567
+ */
568
+
569
+ return 1;
570
+}
571
+
572
static int merge_working_tree(const struct checkout_opts *opts,
573
struct branch_info *old_branch_info,
574
struct branch_info *new_branch_info,
943
parse_commit_or_die(new_branch_info->commit);
944
}
945
848
- ret = merge_working_tree(opts, &old_branch_info, new_branch_info, &writeout_error);
849
- if (ret) {
850
- free(path_to_free);
851
- return ret;
946
+ /* optimize the "checkout -b <new_branch> path */
947
+ if (skip_merge_working_tree(opts, &old_branch_info, new_branch_info)) {
948
+ if (!checkout_optimize_new_branch && !opts->quiet) {
949
+ if (read_cache_preload(NULL) < 0)
950
+ return error(_("index file corrupt"));
951
+ show_local_changes(&new_branch_info->commit->object, &opts->diff_options);
952
+ }
953
+ } else {
954
+ ret = merge_working_tree(opts, &old_branch_info, new_branch_info, &writeout_error);
955
+ if (ret) {
956
+ free(path_to_free);
957
+ return ret;
958
+ }
959
}
960
961
if (!opts->quiet && !old_branch_info.path && old_branch_info.commit && new_branch_info->commit != old_branch_info.commit)
970
971
static int git_checkout_config(const char *var, const char *value, void *cb)
972
{
973
+ if (!strcmp(var, "checkout.optimizenewbranch")) {
974
+ checkout_optimize_new_branch = git_config_bool(var, value);
975
+ return 0;
976
+ }
977
+
978
if (!strcmp(var, "diff.ignoresubmodules")) {
979
struct checkout_opts *opts = cb;
980
handle_ignore_submodules_arg(&opts->diff_options, value);