Skip to content

Commit

Permalink
Extend "checkout --track" DWIM to support more cases
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alex Riesen authored and Junio C Hamano committed Aug 23, 2008
1 parent a19a424 commit 9188ed8
Showing 4 changed files with 46 additions and 17 deletions.
13 changes: 10 additions & 3 deletions Documentation/git-checkout.txt
Original file line number Diff line number Diff line change
@@ -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 changes: 13 additions & 13 deletions builtin-checkout.c
Original file line number Diff line number Diff line change
@@ -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)
1 change: 1 addition & 0 deletions cache.h
Original file line number Diff line number Diff line change
@@ -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 changes: 22 additions & 1 deletion t/t7201-co.sh
Original file line number Diff line number Diff line change
@@ -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' '

0 comments on commit 9188ed8

Please sign in to comment.