Skip to content

Commit 60b188a

Browse files
committed
Merge branch 'js/branch-track'
* js/branch-track: doc: documentation update for the branch track changes branch: optionally setup branch.*.merge from upstream local branches Conflicts: Documentation/config.txt Documentation/git-branch.txt Documentation/git-checkout.txt builtin-branch.c cache.h t/t7201-co.sh
2 parents 5a4d707 + 572fc81 commit 60b188a

File tree

12 files changed

+131
-73
lines changed

12 files changed

+131
-73
lines changed

Documentation/config.txt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,10 +379,14 @@ apply.whitespace::
379379

380380
branch.autosetupmerge::
381381
Tells `git-branch` and `git-checkout` to setup new branches
382-
so that linkgit:git-pull[1] will appropriately merge from that
383-
remote branch. Note that even if this option is not set,
382+
so that linkgit:git-pull[1] will appropriately merge from the
383+
starting point branch. Note that even if this option is not set,
384384
this behavior can be chosen per-branch using the `--track`
385-
and `--no-track` options. This option defaults to true.
385+
and `--no-track` options. The valid settings are: `false` -- no
386+
automatic setup is done; `true` -- automatic setup is done when the
387+
starting point is a remote branch; `always` -- automatic setup is
388+
done when the starting point is either a local branch or remote
389+
branch. This option defaults to true.
386390

387391
branch.<name>.remote::
388392
When in branch <name>, it tells `git fetch` which remote to fetch.

Documentation/git-branch.txt

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,10 @@ working tree to it; use "git checkout <newbranch>" to switch to the
3535
new branch.
3636

3737
When a local branch is started off a remote branch, git sets up the
38-
branch so that linkgit:git-pull[1] will appropriately merge from that
39-
remote branch. If this behavior is not desired, it is possible to
40-
disable it using the global `branch.autosetupmerge` configuration
41-
flag. That setting can be overridden by using the `--track`
42-
and `--no-track` options.
38+
branch so that linkgit:git-pull[1] will appropriately merge from
39+
the remote branch. This behavior may be changed via the global
40+
`branch.autosetupmerge` configuration flag. That setting can be
41+
overridden by using the `--track` and `--no-track` options.
4342

4443
With a '-m' or '-M' option, <oldbranch> will be renamed to <newbranch>.
4544
If <oldbranch> had a corresponding reflog, it is renamed to match
@@ -105,20 +104,19 @@ OPTIONS
105104
Display the full sha1s in output listing rather than abbreviating them.
106105

107106
--track::
108-
Set up configuration so that git-pull will automatically
109-
retrieve data from the remote branch. Use this if you always
110-
pull from the same remote branch into the new branch, or if you
111-
don't want to use "git pull <repository> <refspec>" explicitly.
112-
This behavior is the default. Set the
113-
branch.autosetupmerge configuration variable to false if you
114-
want git-checkout and git-branch to always behave as if
115-
'--no-track' were given.
107+
When creating a new branch, set up configuration so that git-pull
108+
will automatically retrieve data from the start point, which must be
109+
a branch. Use this if you always pull from the same upstream branch
110+
into the new branch, and if you don't want to use "git pull
111+
<repository> <refspec>" explicitly. This behavior is the default
112+
when the start point is a remote branch. Set the
113+
branch.autosetupmerge configuration variable to `false` if you want
114+
git-checkout and git-branch to always behave as if '--no-track' were
115+
given. Set it to `always` if you want this behavior when the
116+
start-point is either a local or remote branch.
116117

117118
--no-track::
118-
When a branch is created off a remote branch,
119-
set up configuration so that git-pull will not retrieve data
120-
from the remote branch, ignoring the branch.autosetupmerge
121-
configuration variable.
119+
Ignore the branch.autosetupmerge configuration variable.
122120

123121
<branchname>::
124122
The name of the branch to create or delete.

Documentation/git-checkout.txt

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,19 @@ OPTIONS
4848
may restrict the characters allowed in a branch name.
4949

5050
--track::
51-
When -b is given and a branch is created off a remote branch,
52-
set up configuration so that git-pull will automatically
53-
retrieve data from the remote branch. Use this if you always
54-
pull from the same remote branch into the new branch, or if you
55-
don't want to use "git pull <repository> <refspec>" explicitly.
56-
This behavior is the default. Set the
57-
branch.autosetupmerge configuration variable to false if you
58-
want git-checkout and git-branch to always behave as if
59-
'--no-track' were given.
51+
When creating a new branch, set up configuration so that git-pull
52+
will automatically retrieve data from the start point, which must be
53+
a branch. Use this if you always pull from the same upstream branch
54+
into the new branch, and if you don't want to use "git pull
55+
<repository> <refspec>" explicitly. This behavior is the default
56+
when the start point is a remote branch. Set the
57+
branch.autosetupmerge configuration variable to `false` if you want
58+
git-checkout and git-branch to always behave as if '--no-track' were
59+
given. Set it to `always` if you want this behavior when the
60+
start-point is either a local or remote branch.
6061

6162
--no-track::
62-
When -b is given and a branch is created off a remote branch,
63-
set up configuration so that git-pull will not retrieve data
64-
from the remote branch, ignoring the branch.autosetupmerge
65-
configuration variable.
63+
Ignore the branch.autosetupmerge configuration variable.
6664

6765
-l::
6866
Create the new branch's reflog. This activates recording of

branch.c

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ static int find_tracked_branch(struct remote *remote, void *priv)
3737
* to infer the settings for branch.<new_ref>.{remote,merge} from the
3838
* config.
3939
*/
40-
static int setup_tracking(const char *new_ref, const char *orig_ref)
40+
static int setup_tracking(const char *new_ref, const char *orig_ref,
41+
enum branch_track track)
4142
{
4243
char key[1024];
4344
struct tracking tracking;
@@ -48,30 +49,36 @@ static int setup_tracking(const char *new_ref, const char *orig_ref)
4849

4950
memset(&tracking, 0, sizeof(tracking));
5051
tracking.spec.dst = (char *)orig_ref;
51-
if (for_each_remote(find_tracked_branch, &tracking) ||
52-
!tracking.matches)
52+
if (for_each_remote(find_tracked_branch, &tracking))
5353
return 1;
5454

55+
if (!tracking.matches)
56+
switch (track) {
57+
case BRANCH_TRACK_ALWAYS:
58+
case BRANCH_TRACK_EXPLICIT:
59+
break;
60+
default:
61+
return 1;
62+
}
63+
5564
if (tracking.matches > 1)
5665
return error("Not tracking: ambiguous information for ref %s",
5766
orig_ref);
5867

59-
if (tracking.matches == 1) {
60-
sprintf(key, "branch.%s.remote", new_ref);
61-
git_config_set(key, tracking.remote ? tracking.remote : ".");
62-
sprintf(key, "branch.%s.merge", new_ref);
63-
git_config_set(key, tracking.src);
64-
free(tracking.src);
65-
printf("Branch %s set up to track remote branch %s.\n",
66-
new_ref, orig_ref);
67-
}
68+
sprintf(key, "branch.%s.remote", new_ref);
69+
git_config_set(key, tracking.remote ? tracking.remote : ".");
70+
sprintf(key, "branch.%s.merge", new_ref);
71+
git_config_set(key, tracking.src ? tracking.src : orig_ref);
72+
free(tracking.src);
73+
printf("Branch %s set up to track %s branch %s.\n", new_ref,
74+
tracking.remote ? "remote" : "local", orig_ref);
6875

6976
return 0;
7077
}
7178

7279
void create_branch(const char *head,
7380
const char *name, const char *start_name,
74-
int force, int reflog, int track)
81+
int force, int reflog, enum branch_track track)
7582
{
7683
struct ref_lock *lock;
7784
struct commit *commit;
@@ -98,7 +105,8 @@ void create_branch(const char *head,
98105
switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
99106
case 0:
100107
/* Not branching from any existing branch */
101-
real_ref = NULL;
108+
if (track == BRANCH_TRACK_EXPLICIT)
109+
die("Cannot setup tracking information; starting point is not a branch.");
102110
break;
103111
case 1:
104112
/* Unique completion -- good */
@@ -126,17 +134,13 @@ void create_branch(const char *head,
126134
snprintf(msg, sizeof msg, "branch: Created from %s",
127135
start_name);
128136

129-
/* When branching off a remote branch, set up so that git-pull
130-
automatically merges from there. So far, this is only done for
131-
remotes registered via .git/config. */
132137
if (real_ref && track)
133-
setup_tracking(name, real_ref);
138+
setup_tracking(name, real_ref, track);
134139

135140
if (write_ref_sha1(lock, sha1, msg) < 0)
136141
die("Failed to write ref: %s.", strerror(errno));
137142

138-
if (real_ref)
139-
free(real_ref);
143+
free(real_ref);
140144
}
141145

142146
void remove_branch_state(void)

branch.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* branch for (if any).
1414
*/
1515
void create_branch(const char *head, const char *name, const char *start_name,
16-
int force, int reflog, int track);
16+
int force, int reflog, enum branch_track track);
1717

1818
/*
1919
* Remove information about the state of working on the current

builtin-branch.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ static const char * const builtin_branch_usage[] = {
3030
static const char *head;
3131
static unsigned char head_sha1[20];
3232

33-
static int branch_track = 1;
34-
3533
static int branch_use_color = -1;
3634
static char branch_colors[][COLOR_MAXLEN] = {
3735
"\033[m", /* reset */
@@ -76,10 +74,6 @@ static int git_branch_config(const char *var, const char *value)
7674
color_parse(value, var, branch_colors[slot]);
7775
return 0;
7876
}
79-
if (!strcmp(var, "branch.autosetupmerge")) {
80-
branch_track = git_config_bool(var, value);
81-
return 0;
82-
}
8377
return git_color_default_config(var, value);
8478
}
8579

@@ -420,14 +414,16 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
420414
{
421415
int delete = 0, rename = 0, force_create = 0;
422416
int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
423-
int reflog = 0, track;
417+
int reflog = 0;
418+
enum branch_track track;
424419
int kinds = REF_LOCAL_BRANCH;
425420
struct commit_list *with_commit = NULL;
426421

427422
struct option options[] = {
428423
OPT_GROUP("Generic options"),
429424
OPT__VERBOSE(&verbose),
430-
OPT_BOOLEAN( 0 , "track", &track, "set up tracking mode (see git-pull(1))"),
425+
OPT_SET_INT( 0 , "track", &track, "set up tracking mode (see git-pull(1))",
426+
BRANCH_TRACK_EXPLICIT),
431427
OPT_BOOLEAN( 0 , "color", &branch_use_color, "use colored output"),
432428
OPT_SET_INT('r', NULL, &kinds, "act on remote-tracking branches",
433429
REF_REMOTE_BRANCH),
@@ -458,7 +454,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
458454
if (branch_use_color == -1)
459455
branch_use_color = git_use_color_default;
460456

461-
track = branch_track;
457+
track = git_branch_track;
462458
argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
463459
if (!!delete + !!rename + !!force_create > 1)
464460
usage_with_options(builtin_branch_usage, options);

builtin-checkout.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ struct checkout_opts {
186186

187187
char *new_branch;
188188
int new_branch_log;
189-
int track;
189+
enum branch_track track;
190190
};
191191

192192
struct branch_info {
@@ -480,13 +480,8 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
480480
return post_checkout_hook(old.commit, new->commit, 1);
481481
}
482482

483-
static int branch_track = 0;
484-
485483
static int git_checkout_config(const char *var, const char *value)
486484
{
487-
if (!strcmp(var, "branch.autosetupmerge"))
488-
branch_track = git_config_bool(var, value);
489-
490485
return git_default_config(var, value);
491486
}
492487

@@ -501,7 +496,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
501496
OPT__QUIET(&opts.quiet),
502497
OPT_STRING('b', NULL, &opts.new_branch, "new branch", "branch"),
503498
OPT_BOOLEAN('l', NULL, &opts.new_branch_log, "log for new branch"),
504-
OPT_BOOLEAN( 0 , "track", &opts.track, "track"),
499+
OPT_SET_INT( 0 , "track", &opts.track, "track",
500+
BRANCH_TRACK_EXPLICIT),
505501
OPT_BOOLEAN('f', NULL, &opts.force, "force"),
506502
OPT_BOOLEAN('m', NULL, &opts.merge, "merge"),
507503
OPT_END(),
@@ -512,7 +508,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
512508

513509
git_config(git_checkout_config);
514510

515-
opts.track = branch_track;
511+
opts.track = git_branch_track;
516512

517513
argc = parse_options(argc, argv, options, checkout_usage, 0);
518514
if (argc) {
@@ -541,7 +537,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
541537
argc--;
542538
}
543539

544-
if (!opts.new_branch && (opts.track != branch_track))
540+
if (!opts.new_branch && (opts.track != git_branch_track))
545541
die("git checkout: --track and --no-track require -b");
546542

547543
if (opts.force && opts.merge)

cache.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,15 @@ enum safe_crlf {
425425

426426
extern enum safe_crlf safe_crlf;
427427

428+
enum branch_track {
429+
BRANCH_TRACK_NEVER = 0,
430+
BRANCH_TRACK_REMOTE,
431+
BRANCH_TRACK_ALWAYS,
432+
BRANCH_TRACK_EXPLICIT,
433+
};
434+
435+
extern enum branch_track git_branch_track;
436+
428437
#define GIT_REPO_VERSION 0
429438
extern int repository_format_version;
430439
extern int check_repository_format(void);

config.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,14 @@ int git_default_config(const char *var, const char *value)
471471
whitespace_rule_cfg = parse_whitespace_rule(value);
472472
return 0;
473473
}
474+
if (!strcmp(var, "branch.autosetupmerge")) {
475+
if (value && !strcasecmp(value, "always")) {
476+
git_branch_track = BRANCH_TRACK_ALWAYS;
477+
return 0;
478+
}
479+
git_branch_track = git_config_bool(var, value);
480+
return 0;
481+
}
474482

475483
/* Add other config variables here and to Documentation/config.txt. */
476484
return 0;

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const char *excludes_file;
3737
int auto_crlf = 0; /* 1: both ways, -1: only when adding git objects */
3838
enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
3939
unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
40+
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
4041

4142
/* This is set by setup_git_dir_gently() and/or git_default_config() */
4243
char *git_work_tree_cfg;

t/t3200-branch.sh

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ test_expect_success \
1515
'echo Hello > A &&
1616
git update-index --add A &&
1717
git-commit -m "Initial commit." &&
18+
echo World >> A &&
19+
git update-index --add A &&
20+
git-commit -m "Second commit." &&
1821
HEAD=$(git rev-parse --verify HEAD)'
1922

2023
test_expect_success \
@@ -171,7 +174,9 @@ test_expect_success 'test overriding tracking setup via --no-track' \
171174
! test "$(git config branch.my2.merge)" = refs/heads/master'
172175

173176
test_expect_success 'no tracking without .fetch entries' \
174-
'git branch --track my6 s &&
177+
'git config branch.autosetupmerge true &&
178+
git branch my6 s &&
179+
git config branch.automsetupmerge false &&
175180
test -z "$(git config branch.my6.remote)" &&
176181
test -z "$(git config branch.my6.merge)"'
177182

@@ -192,6 +197,21 @@ test_expect_success 'test deleting branch without config' \
192197
'git branch my7 s &&
193198
test "$(git branch -d my7 2>&1)" = "Deleted branch my7."'
194199

200+
test_expect_success 'test --track without .fetch entries' \
201+
'git branch --track my8 &&
202+
test "$(git config branch.my8.remote)" &&
203+
test "$(git config branch.my8.merge)"'
204+
205+
test_expect_success \
206+
'branch from non-branch HEAD w/autosetupmerge=always' \
207+
'git config branch.autosetupmerge always &&
208+
git branch my9 HEAD^ &&
209+
git config branch.autosetupmerge false'
210+
211+
test_expect_success \
212+
'branch from non-branch HEAD w/--track causes failure' \
213+
'!(git branch --track my10 HEAD^)'
214+
195215
# Keep this test last, as it changes the current branch
196216
cat >expect <<EOF
197217
0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master

0 commit comments

Comments
 (0)