Skip to content

Commit

Permalink
Merge branch 'tk/simple-autosetupmerge' into jch
Browse files Browse the repository at this point in the history
"git -c branch.autosetupmerge=simple branch $A $B" will set the $B
as $A's upstream only when $A and $B shares the same name, and "git
-c push.default=simple" on branch $A would push to update the
branch $A at the remote $B came from.

* tk/simple-autosetupmerge:
  t3200: tests for new branch.autosetupmerge option "simple"
  merge: new autosetupmerge option 'simple' for matching branches
  • Loading branch information
gitster committed Feb 26, 2022
2 parents 2731c2e + 7095267 commit 52b3240
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 8 deletions.
4 changes: 3 additions & 1 deletion Documentation/config/branch.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ branch.autoSetupMerge::
automatic setup is done when the starting point is either a
local branch or remote-tracking branch; `inherit` -- if the starting point
has a tracking configuration, it is copied to the new
branch. This option defaults to true.
branch; `simple` -- automatic setup is done only when the starting point
is a remote-tracking branch and the new branch has the same name as the
remote branch. This option defaults to true.

branch.autoSetupRebase::
When a new branch is created with 'git branch', 'git switch' or 'git checkout'
Expand Down
18 changes: 11 additions & 7 deletions Documentation/git-branch.txt
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,17 @@ The exact upstream branch is chosen depending on the optional argument:
itself as the upstream; `--track=inherit` means to copy the upstream
configuration of the start-point branch.
+
`--track=direct` is the default when the start point is a remote-tracking branch.
Set the branch.autoSetupMerge configuration variable to `false` if you
want `git switch`, `git checkout` and `git branch` to always behave as if `--no-track`
were given. Set it to `always` if you want this behavior when the
start-point is either a local or remote-tracking branch. Set it to
`inherit` if you want to copy the tracking configuration from the
branch point.
The branch.autoSetupMerge configuration variable specifies how `git switch`,
`git checkout` and `git branch` should behave when neither `--track` nor
`--no-track` are specified:
+
The default option, `true`, behaves as though `--track=direct`
were given whenever the start-point is a remote-tracking branch.
`false` behaves as if `--no-track` were given. `always` behaves as though
`--track=direct` were given. `inherit` behaves as though `--track=inherit`
were given. `simple` behaves as though `--track=direct` were given only when
the start-point is a remote-tracking branch and the new branch has the same
name as the remote branch.
+
See linkgit:git-pull[1] and linkgit:git-config[1] for additional discussion on
how the `branch.<name>.remote` and `branch.<name>.merge` options are used.
Expand Down
19 changes: 19 additions & 0 deletions branch.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,29 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
goto cleanup;
}

/*
* This check does not apply to the BRANCH_TRACK_INHERIT
* option; you can inherit one or more tracking entries
* and the tracking.matches counter is not incremented.
*/
if (tracking.matches > 1)
die(_("not tracking: ambiguous information for ref %s"),
orig_ref);

if (track == BRANCH_TRACK_SIMPLE) {
/*
* Only track if remote branch name matches.
* Reaching into items[0].string is safe because
* we know there is at least one and not more than
* one entry (because not BRANCH_TRACK_INHERIT).
*/
const char *tracked_branch;
if (!skip_prefix(tracking.srcs->items[0].string,
"refs/heads/", &tracked_branch) ||
strcmp(tracked_branch, new_ref))
return;
}

if (tracking.srcs->nr < 1)
string_list_append(tracking.srcs, orig_ref);
if (install_branch_config_multiple_remotes(config_flags, new_ref,
Expand Down
1 change: 1 addition & 0 deletions branch.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ enum branch_track {
BRANCH_TRACK_EXPLICIT,
BRANCH_TRACK_OVERRIDE,
BRANCH_TRACK_INHERIT,
BRANCH_TRACK_SIMPLE,
};

extern enum branch_track git_branch_track;
Expand Down
3 changes: 3 additions & 0 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1686,6 +1686,9 @@ static int git_default_branch_config(const char *var, const char *value)
} else if (value && !strcmp(value, "inherit")) {
git_branch_track = BRANCH_TRACK_INHERIT;
return 0;
} else if (value && !strcmp(value, "simple")) {
git_branch_track = BRANCH_TRACK_SIMPLE;
return 0;
}
git_branch_track = git_config_bool(var, value);
return 0;
Expand Down
35 changes: 35 additions & 0 deletions t/t3200-branch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,41 @@ test_expect_success 'branch from tag w/--track causes failure' '
test_must_fail git branch --track my11 foobar
'

test_expect_success 'simple tracking works when remote branch name matches' '
test_create_repo otherserver &&
test_commit -C otherserver my_commit 1 &&
git -C otherserver branch feature &&
git config branch.autosetupmerge simple &&
git config remote.otherserver.url otherserver &&
git config remote.otherserver.fetch refs/heads/*:refs/remotes/otherserver/* &&
git fetch otherserver &&
git branch feature otherserver/feature &&
rm -fr otherserver &&
test $(git config branch.feature.remote) = otherserver &&
test $(git config branch.feature.merge) = refs/heads/feature
'

test_expect_success 'simple tracking skips when remote branch name does not match' '
git config branch.autosetupmerge simple &&
git config remote.local.url . &&
git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
(git show-ref -q refs/remotes/local/main || git fetch local) &&
git branch my-other local/main &&
test -z "$(git config branch.my-other.remote)" &&
test -z "$(git config branch.my-other.merge)"
'

test_expect_success 'simple tracking skips when remote ref is not a branch' '
git config branch.autosetupmerge simple &&
git tag mytag12 main &&
git config remote.localtags.url . &&
git config remote.localtags.fetch refs/tags/*:refs/remotes/localtags/* &&
(git show-ref -q refs/remotes/localtags/mytag12 || git fetch localtags) &&
git branch mytag12 localtags/mytag12 &&
test -z "$(git config branch.mytag12.remote)" &&
test -z "$(git config branch.mytag12.merge)"
'

test_expect_success '--set-upstream-to fails on multiple branches' '
echo "fatal: too many arguments to set new upstream" >expect &&
test_must_fail git branch --set-upstream-to main a b c 2>err &&
Expand Down

0 comments on commit 52b3240

Please sign in to comment.