submodule: fall back to remote's HEAD for missing remote.<name>.branch

When `remote.<name>.branch` is not configured, `git submodule update`
currently falls back to using the branch name `master`. A much better
idea, however, is to use the remote `HEAD`: on all Git servers running
reasonably recent Git versions, the symref `HEAD` points to the main
branch.

Note: t7419 demonstrates that there _might_ be use cases out there that
_expect_ `git submodule update --remote` to update submodules to the
remote `master` branch even if the remote `HEAD` points to another
branch. Arguably, this patch makes the behavior more intuitive, but
there is a slight possibility that this might cause regressions in
obscure setups.

Even so, it should be okay to fix this behavior without anything like a
longer transition period:

- The `git submodule update --remote` command is not really common.

- Current Git's behavior when running this command is outright
  confusing, unless the remote repository's current branch _is_ `master`
  (in which case the proposed behavior matches the old behavior).

- If a user encounters a regression due to the changed behavior, the fix
  is actually trivial: setting `submodule.<name>.branch` to `master`
  will reinstate the old behavior.

Helped-by: Philippe Blain <levraiphilippeblain@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Johannes Schindelin 2020-06-24 14:46:30 +00:00 committed by Junio C Hamano
parent 4d04658d8b
commit f0a96e8d4c
5 changed files with 31 additions and 12 deletions

View File

@ -183,7 +183,7 @@ set-branch (-d|--default) [--] <path>::
Sets the default remote tracking branch for the submodule. The
`--branch` option allows the remote branch to be specified. The
`--default` option removes the submodule.<name>.branch configuration
key, which causes the tracking branch to default to 'master'.
key, which causes the tracking branch to default to the remote 'HEAD'.
set-url [--] <path> <newurl>::
Sets the URL of the specified submodule to <newurl>. Then, it will
@ -284,7 +284,7 @@ OPTIONS
`.gitmodules` for `update --remote`. A special value of `.` is used to
indicate that the name of the branch in the submodule should be the
same name as the current branch in the current repository. If the
option is not specified, it defaults to 'master'.
option is not specified, it defaults to the remote 'HEAD'.
-f::
--force::
@ -322,10 +322,10 @@ OPTIONS
the superproject's recorded SHA-1 to update the submodule, use the
status of the submodule's remote-tracking branch. The remote used
is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
The remote branch used defaults to `master`, but the branch name may
be overridden by setting the `submodule.<name>.branch` option in
either `.gitmodules` or `.git/config` (with `.git/config` taking
precedence).
The remote branch used defaults to the remote `HEAD`, but the branch
name may be overridden by setting the `submodule.<name>.branch`
option in either `.gitmodules` or `.git/config` (with `.git/config`
taking precedence).
+
This works for any of the supported update procedures (`--checkout`,
`--rebase`, etc.). The only change is the source of the target SHA-1.

View File

@ -49,9 +49,9 @@ submodule.<name>.update::
submodule.<name>.branch::
A remote branch name for tracking updates in the upstream submodule.
If the option is not specified, it defaults to 'master'. A special
value of `.` is used to indicate that the name of the branch in the
submodule should be the same name as the current branch in the
If the option is not specified, it defaults to the remote 'HEAD'.
A special value of `.` is used to indicate that the name of the branch
in the submodule should be the same name as the current branch in the
current repository. See the `--remote` documentation in
linkgit:git-submodule[1] for details.

View File

@ -1981,7 +1981,7 @@ static const char *remote_submodule_branch(const char *path)
free(key);
if (!branch)
return "master";
return "HEAD";
if (!strcmp(branch, ".")) {
const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);

View File

@ -70,6 +70,22 @@ test_expect_success 'setup a submodule tree' '
)
'
test_expect_success 'update --remote falls back to using HEAD' '
test_create_repo main-branch-submodule &&
test_commit -C main-branch-submodule initial &&
test_create_repo main-branch &&
git -C main-branch submodule add ../main-branch-submodule &&
git -C main-branch commit -m add-submodule &&
git -C main-branch-submodule switch -c hello &&
test_commit -C main-branch-submodule world &&
git clone --recursive main-branch main-branch-clone &&
git -C main-branch-clone submodule update --remote main-branch-submodule &&
test_path_exists main-branch-clone/main-branch-submodule/world.t
'
test_expect_success 'submodule update detaching the HEAD ' '
(cd super/submodule &&
git reset --hard HEAD~1

View File

@ -52,12 +52,13 @@ test_expect_success 'test submodule set-branch --branch' '
'
test_expect_success 'test submodule set-branch --default' '
test_commit -C submodule c &&
(cd super &&
git submodule set-branch --default submodule &&
! grep branch .gitmodules &&
git submodule update --remote &&
cat <<-\EOF >expect &&
a
c
EOF
git -C submodule show -s --pretty=%s >actual &&
test_cmp expect actual
@ -65,6 +66,7 @@ test_expect_success 'test submodule set-branch --default' '
'
test_expect_success 'test submodule set-branch -b' '
test_commit -C submodule b &&
(cd super &&
git submodule set-branch -b topic submodule &&
grep "branch = topic" .gitmodules &&
@ -78,12 +80,13 @@ test_expect_success 'test submodule set-branch -b' '
'
test_expect_success 'test submodule set-branch -d' '
test_commit -C submodule d &&
(cd super &&
git submodule set-branch -d submodule &&
! grep branch .gitmodules &&
git submodule update --remote &&
cat <<-\EOF >expect &&
a
d
EOF
git -C submodule show -s --pretty=%s >actual &&
test_cmp expect actual