summaryrefslogtreecommitdiff
path: root/builtin/checkout.c
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2018-08-02 15:30:41 -0700
committerLibravatar Junio C Hamano <gitster@pobox.com>2018-08-02 15:30:41 -0700
commit50858edd1aa063d3ee2ecb48672c43630cea9070 (patch)
tree16e42089e479d0776ff94fa9621daf6f815a6668 /builtin/checkout.c
parentMerge branch 'sb/diff-color-move-more' (diff)
parentcheckout & worktree: introduce checkout.defaultRemote (diff)
downloadtgif-50858edd1aa063d3ee2ecb48672c43630cea9070.tar.xz
Merge branch 'ab/checkout-default-remote'
"git checkout" and "git worktree add" learned to honor checkout.defaultRemote when auto-vivifying a local branch out of a remote tracking branch in a repository with multiple remotes that have tracking branches that share the same names. * ab/checkout-default-remote: checkout & worktree: introduce checkout.defaultRemote checkout: add advice for ambiguous "checkout <branch>" builtin/checkout.c: use "ret" variable for return checkout: pass the "num_matches" up to callers checkout.c: change "unique" member to "num_matches" checkout.c: introduce an *_INIT macro checkout.h: wrap the arguments to unique_tracking_name() checkout tests: index should be clean after dwim checkout
Diffstat (limited to 'builtin/checkout.c')
-rw-r--r--builtin/checkout.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 28627650cd..2de10d28c7 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -23,6 +23,7 @@
#include "resolve-undo.h"
#include "submodule-config.h"
#include "submodule.h"
+#include "advice.h"
static const char * const checkout_usage[] = {
N_("git checkout [<options>] <branch>"),
@@ -879,7 +880,8 @@ static int parse_branchname_arg(int argc, const char **argv,
int dwim_new_local_branch_ok,
struct branch_info *new_branch_info,
struct checkout_opts *opts,
- struct object_id *rev)
+ struct object_id *rev,
+ int *dwim_remotes_matched)
{
struct tree **source_tree = &opts->source_tree;
const char **new_branch = &opts->new_branch;
@@ -911,8 +913,10 @@ static int parse_branchname_arg(int argc, const char **argv,
* (b) If <something> is _not_ a commit, either "--" is present
* or <something> is not a path, no -t or -b was given, and
* and there is a tracking branch whose name is <something>
- * in one and only one remote, then this is a short-hand to
- * fork local <something> from that remote-tracking branch.
+ * in one and only one remote (or if the branch exists on the
+ * remote named in checkout.defaultRemote), then this is a
+ * short-hand to fork local <something> from that
+ * remote-tracking branch.
*
* (c) Otherwise, if "--" is present, treat it like case (1).
*
@@ -973,7 +977,8 @@ static int parse_branchname_arg(int argc, const char **argv,
recover_with_dwim = 0;
if (recover_with_dwim) {
- const char *remote = unique_tracking_name(arg, rev);
+ const char *remote = unique_tracking_name(arg, rev,
+ dwim_remotes_matched);
if (remote) {
*new_branch = arg;
arg = remote;
@@ -1110,6 +1115,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
struct branch_info new_branch_info;
char *conflict_style = NULL;
int dwim_new_local_branch = 1;
+ int dwim_remotes_matched = 0;
struct option options[] = {
OPT__QUIET(&opts.quiet, N_("suppress progress reporting")),
OPT_STRING('b', NULL, &opts.new_branch, N_("branch"),
@@ -1222,7 +1228,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
opts.track == BRANCH_TRACK_UNSPECIFIED &&
!opts.new_branch;
int n = parse_branchname_arg(argc, argv, dwim_ok,
- &new_branch_info, &opts, &rev);
+ &new_branch_info, &opts, &rev,
+ &dwim_remotes_matched);
argv += n;
argc -= n;
}
@@ -1264,8 +1271,26 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
}
UNLEAK(opts);
- if (opts.patch_mode || opts.pathspec.nr)
- return checkout_paths(&opts, new_branch_info.name);
- else
+ if (opts.patch_mode || opts.pathspec.nr) {
+ int ret = checkout_paths(&opts, new_branch_info.name);
+ if (ret && dwim_remotes_matched > 1 &&
+ advice_checkout_ambiguous_remote_branch_name)
+ advise(_("'%s' matched more than one remote tracking branch.\n"
+ "We found %d remotes with a reference that matched. So we fell back\n"
+ "on trying to resolve the argument as a path, but failed there too!\n"
+ "\n"
+ "If you meant to check out a remote tracking branch on, e.g. 'origin',\n"
+ "you can do so by fully qualifying the name with the --track option:\n"
+ "\n"
+ " git checkout --track origin/<name>\n"
+ "\n"
+ "If you'd like to always have checkouts of an ambiguous <name> prefer\n"
+ "one remote, e.g. the 'origin' remote, consider setting\n"
+ "checkout.defaultRemote=origin in your config."),
+ argv[0],
+ dwim_remotes_matched);
+ return ret;
+ } else {
return checkout_branch(&opts, &new_branch_info);
+ }
}