char *new_branch;
int new_branch_log;
- int track;
+ enum branch_track track;
};
struct branch_info {
}
static int merge_working_tree(struct checkout_opts *opts,
- struct branch_info *old, struct branch_info *new,
- const char *prefix)
+ struct branch_info *old, struct branch_info *new)
{
int ret;
struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
refresh_cache(REFRESH_QUIET);
if (unmerged_cache()) {
- ret = opts->merge ? -1 :
- error("you need to resolve your current index first");
- } else {
- topts.update = 1;
- topts.merge = 1;
- topts.gently = opts->merge;
- topts.fn = twoway_merge;
- topts.dir = xcalloc(1, sizeof(*topts.dir));
- topts.dir->show_ignored = 1;
- topts.dir->exclude_per_dir = ".gitignore";
- tree = parse_tree_indirect(old->commit->object.sha1);
- init_tree_desc(&trees[0], tree->buffer, tree->size);
- tree = parse_tree_indirect(new->commit->object.sha1);
- init_tree_desc(&trees[1], tree->buffer, tree->size);
- ret = unpack_trees(2, trees, &topts);
+ error("you need to resolve your current index first");
+ return 1;
}
- if (ret) {
+
+ /* 2-way merge to the new branch */
+ topts.update = 1;
+ topts.merge = 1;
+ topts.gently = opts->merge;
+ topts.verbose_update = !opts->quiet;
+ topts.fn = twoway_merge;
+ topts.dir = xcalloc(1, sizeof(*topts.dir));
+ topts.dir->show_ignored = 1;
+ topts.dir->exclude_per_dir = ".gitignore";
+ tree = parse_tree_indirect(old->commit->object.sha1);
+ init_tree_desc(&trees[0], tree->buffer, tree->size);
+ tree = parse_tree_indirect(new->commit->object.sha1);
+ init_tree_desc(&trees[1], tree->buffer, tree->size);
+
+ if (unpack_trees(2, trees, &topts)) {
/*
* Unpack couldn't do a trivial merge; either
* give up or do a real merge, depending on
return 0;
}
-static void adjust_to_tracking(struct branch_info *new, struct checkout_opts *opts)
+static void report_tracking(struct branch_info *new, struct checkout_opts *opts)
{
/*
* We have switched to a new branch; is it building on
int rev_argc;
int num_ours, num_theirs;
const char *remote_msg;
- struct branch *branch = branch_get(NULL);
+ struct branch *branch = branch_get(new->name);
/*
* Nothing to report unless we are marked to build on top of
* somebody else.
*/
- if (!branch || !branch->merge)
+ if (!branch || !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)
return;
/*
remote_msg, base,
num_ours, (num_ours == 1) ? "" : "s");
else if (!num_ours)
- printf("Your branch is behind of the tracked%s branch '%s' "
+ printf("Your branch is behind the tracked%s branch '%s' "
"by %d commit%s,\n"
"and can be fast-forwarded.\n",
remote_msg, base,
remove_branch_state();
strbuf_release(&msg);
if (!opts->quiet && (new->path || !strcmp(new->name, "HEAD")))
- adjust_to_tracking(new, opts);
+ report_tracking(new, opts);
}
-static int switch_branches(struct checkout_opts *opts,
- struct branch_info *new, const char *prefix)
+static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
{
int ret = 0;
struct branch_info old;
opts->force = 1;
}
- ret = merge_working_tree(opts, &old, new, prefix);
+ ret = merge_working_tree(opts, &old, new);
if (ret)
return ret;
return post_checkout_hook(old.commit, new->commit, 1);
}
-static int branch_track = 0;
-
static int git_checkout_config(const char *var, const char *value)
{
- if (!strcmp(var, "branch.autosetupmerge"))
- branch_track = git_config_bool(var, value);
-
return git_default_config(var, value);
}
OPT__QUIET(&opts.quiet),
OPT_STRING('b', NULL, &opts.new_branch, "new branch", "branch"),
OPT_BOOLEAN('l', NULL, &opts.new_branch_log, "log for new branch"),
- OPT_BOOLEAN( 0 , "track", &opts.track, "track"),
+ OPT_SET_INT( 0 , "track", &opts.track, "track",
+ BRANCH_TRACK_EXPLICIT),
OPT_BOOLEAN('f', NULL, &opts.force, "force"),
OPT_BOOLEAN('m', NULL, &opts.merge, "merge"),
OPT_END(),
git_config(git_checkout_config);
- opts.track = branch_track;
+ opts.track = git_branch_track;
argc = parse_options(argc, argv, options, checkout_usage, 0);
if (argc) {
argc--;
}
- if (!opts.new_branch && (opts.track != branch_track))
+ if (!opts.new_branch && (opts.track != git_branch_track))
die("git checkout: --track and --no-track require -b");
if (opts.force && opts.merge)
if (argc) {
const char **pathspec = get_pathspec(prefix, argv);
+
+ if (!pathspec)
+ die("invalid path specification");
+
/* Checkout paths */
if (opts.new_branch || opts.force || opts.merge) {
if (argc == 1) {
die("Cannot switch branch to a non-commit.");
}
- return switch_branches(&opts, &new, prefix);
+ return switch_branches(&opts, &new);
}