submodule init: warn about falling back to a local path

When a submodule is initialized, the config variable 'submodule.<name>.url'
is set depending on the value of the same variable in the .gitmodules
file. When the URL indicates to be relative, then the url is computed
relative to its default remote. The default remote cannot be determined
accurately in all cases, such that it falls back to 'origin'.

The 'origin' remote may not exist, though. In that case we give up looking
for a suitable remote and we'll just assume it to be a local relative path.

This can be confusing to users as there is a lot of guessing involved,
which is not obvious to the user.

So in the corner case of assuming a local autoritative truth, warn the
user to lessen the confusion.

This behavior was introduced in 4d6893200 (submodule add: allow relative
repository path even when no url is set, 2011-06-06), which shared the
code with submodule-init and then ported to C in 3604242f08 (submodule:
port init from shell to C, 2016-04-15).

In case of submodule-add, this behavior makes sense in some use cases[1],
however for submodule-init there does not seem to be an immediate obvious
use case to fall back to a local submodule. However there might be, so
warn instead of die here.

While adding the warning, also clarify the behavior of relative URLs in
the documentation.

[1] e.g. http://stackoverflow.com/questions/8721984/git-ignore-files-for-public-repository-but-not-for-private
"store a secret locally in a submodule, with no intention to publish it"

Reported-by: Shawn Pearce <spearce@spearce.org>
Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Stefan Beller 2017-02-24 17:31:47 -08:00 committed by Junio C Hamano
parent e7e07d5a4f
commit d1b3b81aab
2 changed files with 27 additions and 19 deletions

View File

@ -73,13 +73,17 @@ configuration entries unless `--name` is used to specify a logical name.
+ +
<repository> is the URL of the new submodule's origin repository. <repository> is the URL of the new submodule's origin repository.
This may be either an absolute URL, or (if it begins with ./ This may be either an absolute URL, or (if it begins with ./
or ../), the location relative to the superproject's origin or ../), the location relative to the superproject's default remote
repository (Please note that to specify a repository 'foo.git' repository (Please note that to specify a repository 'foo.git'
which is located right next to a superproject 'bar.git', you'll which is located right next to a superproject 'bar.git', you'll
have to use '../foo.git' instead of './foo.git' - as one might expect have to use '../foo.git' instead of './foo.git' - as one might expect
when following the rules for relative URLs - because the evaluation when following the rules for relative URLs - because the evaluation
of relative URLs in Git is identical to that of relative directories). of relative URLs in Git is identical to that of relative directories).
If the superproject doesn't have an origin configured +
The default remote is the remote of the remote tracking branch
of the current branch. If no such remote tracking branch exists or
the HEAD is detached, "origin" is assumed to be the default remote.
If the superproject doesn't have a default remote configured
the superproject is its own authoritative upstream and the current the superproject is its own authoritative upstream and the current
working directory is used instead. working directory is used instead.
+ +
@ -118,18 +122,24 @@ too (and can also report changes to a submodule's work tree).
init [--] [<path>...]:: init [--] [<path>...]::
Initialize the submodules recorded in the index (which were Initialize the submodules recorded in the index (which were
added and committed elsewhere) by copying submodule added and committed elsewhere) by setting `submodule.$name.url`
names and urls from .gitmodules to .git/config. in .git/config. It uses the same setting from .gitmodules as
Optional <path> arguments limit which submodules will be initialized. a template. If the URL is relative, it will be resolved using
It will also copy the value of `submodule.$name.update` into the default remote. If there is no default remote, the current
.git/config. repository will be assumed to be upstream.
The key used in .git/config is `submodule.$name.url`. +
This command does not alter existing information in .git/config. Optional <path> arguments limit which submodules will be initialized.
You can then customize the submodule clone URLs in .git/config If no path is specified, all submodules are initialized.
for your local setup and proceed to `git submodule update`; +
you can also just use `git submodule update --init` without When present, it will also copy the value of `submodule.$name.update`.
the explicit 'init' step if you do not intend to customize This command does not alter existing information in .git/config.
any submodule locations. You can then customize the submodule clone URLs in .git/config
for your local setup and proceed to `git submodule update`;
you can also just use `git submodule update --init` without
the explicit 'init' step if you do not intend to customize
any submodule locations.
+
See the add subcommand for the defintion of default remote.
deinit [-f|--force] (--all|[--] <path>...):: deinit [-f|--force] (--all|[--] <path>...)::
Unregister the given submodules, i.e. remove the whole Unregister the given submodules, i.e. remove the whole

View File

@ -356,12 +356,10 @@ static void init_submodule(const char *path, const char *prefix, int quiet)
strbuf_addf(&remotesb, "remote.%s.url", remote); strbuf_addf(&remotesb, "remote.%s.url", remote);
free(remote); free(remote);
if (git_config_get_string(remotesb.buf, &remoteurl)) if (git_config_get_string(remotesb.buf, &remoteurl)) {
/* warning(_("could not lookup configuration '%s'. Assuming this repository is its own authoritative upstream."), remotesb.buf);
* The repository is its own
* authoritative upstream
*/
remoteurl = xgetcwd(); remoteurl = xgetcwd();
}
relurl = relative_url(remoteurl, url, NULL); relurl = relative_url(remoteurl, url, NULL);
strbuf_release(&remotesb); strbuf_release(&remotesb);
free(remoteurl); free(remoteurl);