Browse Source

Extend "checkout --track" DWIM to support more cases

The code handles additionally "refs/remotes/<something>/name",
"remotes/<something>/name", and "refs/<namespace>/name".

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Alex Riesen 17 years ago committed by Junio C Hamano
parent
commit
9188ed8962
  1. 13
      Documentation/git-checkout.txt
  2. 26
      builtin-checkout.c
  3. 1
      cache.h
  4. 23
      t/t7201-co.sh

13
Documentation/git-checkout.txt

@ -64,9 +64,16 @@ OPTIONS @@ -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.

26
builtin-checkout.c

@ -157,7 +157,7 @@ struct checkout_opts { @@ -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) @@ -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)

1
cache.h

@ -451,6 +451,7 @@ enum safe_crlf { @@ -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,

23
t/t7201-co.sh

@ -340,9 +340,30 @@ test_expect_success \ @@ -340,9 +340,30 @@ test_expect_success \
test_expect_success \
'checkout with --track fakes a sensible -b <name>' '
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' '

Loading…
Cancel
Save