diff --git a/Documentation/config.txt b/Documentation/config.txt
index 0510ac7..048465f 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1769,6 +1769,12 @@ submodule.<name>.update::
URL and other values found in the `.gitmodules` file. See
linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
+submodule.<name>.fetch::
+ A boolean to enable/disable recursive fetching of this submodule. It can
+ be overriden by using the --[no-]recursive command line option to "git
+ fetch" and "git pull". This setting overrides any setting made in
+ .gitmodules for this submodule.
+
submodule.<name>.ignore::
Defines under what circumstances "git status" and the diff family show
a submodule as modified. When set to "all", it will never be considered
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 1d875be..aff4daf 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -67,7 +67,8 @@ endif::git-pull[]
--[no-]recursive::
By default new commits of all populated submodules will be fetched
too. This option can be used to disable/enable recursive fetching of
- submodules.
+ submodules regardless of the 'fetch' configuration setting (see
+ linkgit:git-config[1] or linkgit:gitmodules[5]).
-u::
--update-head-ok::
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index bcffd95..febfef4 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -44,6 +44,14 @@ submodule.<name>.update::
This config option is overridden if 'git submodule update' is given
the '--merge' or '--rebase' options.
+submodule.<name>.fetch::
+ A boolean to enable/disable recursive fetching of this submodule.
+ If this option is also present in the submodules entry in .git/config of
+ the superproject, the setting there will override the one found in
+ .gitmodules.
+ Both settings can be overriden on the command line by using the
+ "--[no-]recursive" option to "git fetch" and "git pull"..
+
submodule.<name>.ignore::
Defines under what circumstances "git status" and the diff family show
a submodule as modified. When set to "all", it will never be considered
diff --git a/builtin/fetch.c b/builtin/fetch.c
index da5fc9a..17759b5 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -28,7 +28,13 @@ enum {
TAGS_SET = 2
};
-static int all, append, dry_run, force, keep, multiple, prune, recursive = -1, update_head_ok, verbosity;
+enum {
+ RECURSIVE_UNSET = 0,
+ RECURSIVE_DEFAULT = 1,
+ RECURSIVE_SET = 2
+};
+
+static int all, append, dry_run, force, keep, multiple, prune, recursive = RECURSIVE_DEFAULT, update_head_ok, verbosity;
static int progress;
static int tags = TAGS_DEFAULT;
static const char *depth;@@ -54,8 +60,8 @@ static struct option builtin_fetch_options[] = {
"do not fetch all tags (--no-tags)", TAGS_UNSET),
OPT_BOOLEAN('p', "prune", &prune,
"prune tracking branches no longer on remote"),
- OPT_BOOLEAN(0, "recursive", &recursive,
- "control recursive fetching of submodules"),
+ OPT_SET_INT(0, "recursive", &recursive,
+ "control recursive fetching of submodules", RECURSIVE_SET),
OPT_BOOLEAN(0, "dry-run", &dry_run,
"dry run"),
OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),@@ -927,7 +933,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
if (!result && recursive) {
gitmodules_config();
git_config(submodule_config, NULL);
- result = fetch_populated_submodules();
+ result = fetch_populated_submodules(recursive == RECURSIVE_SET);
}
/* All names were strdup()ed or strndup()ed */diff --git a/submodule.c b/submodule.c
index e4f2419..2380638 100644
--- a/submodule.c
+++ b/submodule.c
@@ -10,6 +10,7 @@
#include "string-list.h"
struct string_list config_name_for_path;
+struct string_list config_fetch_for_name;
struct string_list config_ignore_for_name;
static int add_submodule_odb(const char *path)
@@ -100,6 +101,14 @@ int parse_submodule_config_option(const char *var, const char *value)
config = string_list_append(&config_name_for_path, xstrdup(value));
config->util = strbuf_detach(&submodname, NULL);
strbuf_release(&submodname);
+ } else if ((len > 5) && !strcmp(var + len - 6, ".fetch")) {
+ strbuf_add(&submodname, var, len - 6);
+ config = unsorted_string_list_lookup(&config_fetch_for_name, submodname.buf);
+ if (!config)
+ config = string_list_append(&config_fetch_for_name,
+ strbuf_detach(&submodname, NULL));
+ config->util = git_config_bool(var, value) ? (void *)1 : NULL;
+ strbuf_release(&submodname);
} else if ((len > 7) && !strcmp(var + len - 7, ".ignore")) {
if (strcmp(value, "untracked") && strcmp(value, "dirty") &&
strcmp(value, "all") && strcmp(value, "none")) {@@ -229,7 +238,7 @@ void show_submodule_summary(FILE *f, const char *path,
strbuf_release(&sb);
}
-int fetch_populated_submodules()
+int fetch_populated_submodules(int forced)
{
int result = 0;
struct child_process cp;@@ -253,6 +262,14 @@ int fetch_populated_submodules()
struct strbuf submodule_path = STRBUF_INIT;
struct strbuf submodule_git_dir = STRBUF_INIT;
const char *git_dir;
+
+ if (!forced) {
+ struct string_list_item *fetch_option;
+ fetch_option = unsorted_string_list_lookup(&config_fetch_for_name, name_for_path->util);
+ if (fetch_option && !fetch_option->util)
+ continue;
+ }
+
strbuf_addf(&submodule_path, "%s/%s", work_tree, name_for_path->string);
strbuf_addf(&submodule_git_dir, "%s/.git", submodule_path.buf);
git_dir = read_gitfile_gently(submodule_git_dir.buf);diff --git a/submodule.h b/submodule.h
index 380878c..9e6257e 100644
--- a/submodule.h
+++ b/submodule.h
@@ -13,7 +13,7 @@ void show_submodule_summary(FILE *f, const char *path,
unsigned char one[20], unsigned char two[20],
unsigned dirty_submodule,
const char *del, const char *add, const char *reset);
-int fetch_populated_submodules();
+int fetch_populated_submodules(int forced);
unsigned is_submodule_modified(const char *path, int ignore_untracked);
int merge_submodule(unsigned char result[20], const char *path, const unsigned char base[20],
const unsigned char a[20], const unsigned char b[20]);
diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh
index da5d5fd..489ef1a 100755
--- a/t/t5526-fetch-submodules.sh
+++ b/t/t5526-fetch-submodules.sh
@@ -52,6 +52,46 @@ test_expect_success "fetch recurses into submodules" '
'
test_expect_success "fetch --no-recursive only fetches superproject" '
+ (
+ cd downstream &&
+ git fetch --no-recursive >../actual.out 2>../actual.err
+ ) &&
+ ! test -s actual.out &&
+ ! test -s actual.err
+'
+
+test_expect_success "using fetch=false in .gitmodules only fetches superproject" '
+ (
+ cd downstream &&
+ git config -f .gitmodules submodule.submodule.fetch false &&
+ git fetch >../actual.out 2>../actual.err
+ ) &&
+ ! test -s actual.out &&
+ ! test -s actual.err
+'
+
+test_expect_success "--recursive overrides .gitmodules config" '
+ add_upstream_commit &&
+ (
+ cd downstream &&
+ git fetch --recursive >../actual.out 2>../actual.err
+ ) &&
+ test_cmp expect.out actual.out &&
+ test_cmp expect.err actual.err
+'
+
+test_expect_success "using fetch=true in .git/config overrides setting in .gitmodules" '
+ add_upstream_commit &&
+ (
+ cd downstream &&
+ git config submodule.submodule.fetch true &&
+ git fetch >../actual.out 2>../actual.err
+ ) &&
+ test_cmp expect.out actual.out &&
+ test_cmp expect.err actual.err
+'
+
+test_expect_success "--no-recursive overrides fetch setting from .git/config" '
add_upstream_commit &&
(
cd downstream &&
--
1.7.2.2.527.gacca9