From 9188ed8962ed47c0f41c24eb1317aa07037da545 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Thu, 21 Aug 2008 19:23:20 +0200 Subject: [PATCH] Extend "checkout --track" DWIM to support more cases The code handles additionally "refs/remotes//name", "remotes//name", and "refs//name". Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- Documentation/git-checkout.txt | 13 ++++++++++--- builtin-checkout.c | 26 +++++++++++++------------- cache.h | 1 + t/t7201-co.sh | 23 ++++++++++++++++++++++- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index 43d450254..be54a0299 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -64,9 +64,16 @@ OPTIONS given. Set it to `always` if you want this behavior when the start-point is either a local or remote branch. + -If no '-b' option was given, a name will be made up for you, by stripping -the part up to the first slash of the tracked branch. For example, if you -called 'git checkout --track origin/next', the branch name will be 'next'. +If no '-b' option was given, the name of the new branch will be +derived from the remote branch, by attempting to guess the name +of the branch on remote system. If "remotes/" or "refs/remotes/" +are prefixed, it is stripped away, and then the part up to the +next slash (which would be the nickname of the remote) is removed. +This would tell us to use "hack" as the local branch when branching +off of "origin/hack" (or "remotes/origin/hack", or even +"refs/remotes/origin/hack"). If the given name has no slash, or the above +guessing results in an empty name, the guessing is aborted. You can +exlicitly give a name with '-b' in such a case. --no-track:: Ignore the branch.autosetupmerge configuration variable. diff --git a/builtin-checkout.c b/builtin-checkout.c index e95eab9b1..b380ad6e8 100644 --- a/builtin-checkout.c +++ b/builtin-checkout.c @@ -157,7 +157,7 @@ struct checkout_opts { int force; int writeout_error; - char *new_branch; + const char *new_branch; int new_branch_log; enum branch_track track; }; @@ -437,27 +437,27 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) git_config(git_default_config, NULL); - opts.track = -1; + opts.track = BRANCH_TRACK_UNSPECIFIED; argc = parse_options(argc, argv, options, checkout_usage, PARSE_OPT_KEEP_DASHDASH); /* --track without -b should DWIM */ - if (opts.track && opts.track != -1 && !opts.new_branch) { - char *slash; - if (!argc || !strcmp(argv[0], "--")) + if (0 < opts.track && !opts.new_branch) { + const char *argv0 = argv[0]; + if (!argc || !strcmp(argv0, "--")) die ("--track needs a branch name"); - slash = strchr(argv[0], '/'); - if (slash && !prefixcmp(argv[0], "refs/")) - slash = strchr(slash + 1, '/'); - if (slash && !prefixcmp(argv[0], "remotes/")) - slash = strchr(slash + 1, '/'); - if (!slash || !slash[1]) + if (!prefixcmp(argv0, "refs/")) + argv0 += 5; + if (!prefixcmp(argv0, "remotes/")) + argv0 += 8; + argv0 = strchr(argv0, '/'); + if (!argv0 || !argv0[1]) die ("Missing branch name; try -b"); - opts.new_branch = slash + 1; + opts.new_branch = argv0 + 1; } - if (opts.track == -1) + if (opts.track == BRANCH_TRACK_UNSPECIFIED) opts.track = git_branch_track; if (opts.force && opts.merge) diff --git a/cache.h b/cache.h index 928ae9f14..a097a959b 100644 --- a/cache.h +++ b/cache.h @@ -451,6 +451,7 @@ enum safe_crlf { extern enum safe_crlf safe_crlf; enum branch_track { + BRANCH_TRACK_UNSPECIFIED = -1, BRANCH_TRACK_NEVER = 0, BRANCH_TRACK_REMOTE, BRANCH_TRACK_ALWAYS, diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 943dd57aa..1dff84d2f 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -340,9 +340,30 @@ test_expect_success \ test_expect_success \ 'checkout with --track fakes a sensible -b ' ' git update-ref refs/remotes/origin/koala/bear renamer && + git update-ref refs/new/koala/bear renamer && + git checkout --track origin/koala/bear && test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && - test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"' + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && + + git checkout master && git branch -D koala/bear && + + git checkout --track refs/remotes/origin/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && + + git checkout master && git branch -D koala/bear && + + git checkout --track remotes/origin/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && + + git checkout master && git branch -D koala/bear && + + git checkout --track refs/new/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" +' test_expect_success \ 'checkout with --track, but without -b, fails with too short tracked name' ' -- 2.30.2