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>
Alex Riesen committed
Aug 21, 2008 at 19:23 UTC
9188ed8962ed47c0f41c24eb1317aa07037da545
4 files changed
+46
-17
Documentation/git-checkout.txt
+10
-3
@@ -64,9 +64,16 @@ OPTIONS
64
given. Set it to `always` if you want this behavior when the
65
start-point is either a local or remote branch.
66
+
67
-If no '-b' option was given, a name will be made up for you, by stripping
68
-the part up to the first slash of the tracked branch. For example, if you
69
-called 'git checkout --track origin/next', the branch name will be 'next'.
67
+If no '-b' option was given, the name of the new branch will be
68
+derived from the remote branch, by attempting to guess the name
69
+of the branch on remote system. If "remotes/" or "refs/remotes/"
70
+are prefixed, it is stripped away, and then the part up to the
71
+next slash (which would be the nickname of the remote) is removed.
72
+This would tell us to use "hack" as the local branch when branching
73
+off of "origin/hack" (or "remotes/origin/hack", or even
74
+"refs/remotes/origin/hack"). If the given name has no slash, or the above
75
+guessing results in an empty name, the guessing is aborted. You can
76
+exlicitly give a name with '-b' in such a case.
77
78
--no-track::
79
Ignore the branch.autosetupmerge configuration variable.
builtin-checkout.c
+13
-13
@@ -157,7 +157,7 @@ struct checkout_opts {
157
int force;
158
int writeout_error;
159
160
- char *new_branch;
160
+ const char *new_branch;
161
int new_branch_log;
162
enum branch_track track;
163
};
@@ -437,27 +437,27 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
437
438
git_config(git_default_config, NULL);
439
440
- opts.track = -1;
440
+ opts.track = BRANCH_TRACK_UNSPECIFIED;
441
442
argc = parse_options(argc, argv, options, checkout_usage,
443
PARSE_OPT_KEEP_DASHDASH);
444
445
/* --track without -b should DWIM */
446
- if (opts.track && opts.track != -1 && !opts.new_branch) {
447
- char *slash;
448
- if (!argc || !strcmp(argv[0], "--"))
446
+ if (0 < opts.track && !opts.new_branch) {
447
+ const char *argv0 = argv[0];
448
+ if (!argc || !strcmp(argv0, "--"))
449
die ("--track needs a branch name");
450
- slash = strchr(argv[0], '/');
451
- if (slash && !prefixcmp(argv[0], "refs/"))
452
- slash = strchr(slash + 1, '/');
453
- if (slash && !prefixcmp(argv[0], "remotes/"))
454
- slash = strchr(slash + 1, '/');
455
- if (!slash || !slash[1])
450
+ if (!prefixcmp(argv0, "refs/"))
451
+ argv0 += 5;
452
+ if (!prefixcmp(argv0, "remotes/"))
453
+ argv0 += 8;
454
+ argv0 = strchr(argv0, '/');
455
+ if (!argv0 || !argv0[1])
456
die ("Missing branch name; try -b");
457
- opts.new_branch = slash + 1;
457
+ opts.new_branch = argv0 + 1;
458
}
459
460
- if (opts.track == -1)
460
+ if (opts.track == BRANCH_TRACK_UNSPECIFIED)
461
opts.track = git_branch_track;
462
463
if (opts.force && opts.merge)
cache.h
+1
@@ -451,6 +451,7 @@ enum safe_crlf {
451
extern enum safe_crlf safe_crlf;
452
453
enum branch_track {
454
+ BRANCH_TRACK_UNSPECIFIED = -1,
455
BRANCH_TRACK_NEVER = 0,
456
BRANCH_TRACK_REMOTE,
457
BRANCH_TRACK_ALWAYS,
t/t7201-co.sh
+22
-1
@@ -340,9 +340,30 @@ test_expect_success \
340
test_expect_success \
341
'checkout with --track fakes a sensible -b <name>' '
342
git update-ref refs/remotes/origin/koala/bear renamer &&
343
+ git update-ref refs/new/koala/bear renamer &&
344
+
345
git checkout --track origin/koala/bear &&
346
test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
345
- test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"'
347
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
348
+
349
+ git checkout master && git branch -D koala/bear &&
350
+
351
+ git checkout --track refs/remotes/origin/koala/bear &&
352
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
353
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
354
+
355
+ git checkout master && git branch -D koala/bear &&
356
+
357
+ git checkout --track remotes/origin/koala/bear &&
358
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
359
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
360
+
361
+ git checkout master && git branch -D koala/bear &&
362
+
363
+ git checkout --track refs/new/koala/bear &&
364
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
365
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
366
+'
367
368
test_expect_success \
369
'checkout with --track, but without -b, fails with too short tracked name' '