Skip to content

Commit cda4ba3

Browse files
committed
Merge branch 'jk/warn-add-gitlink'
Using "git add d/i/r" when d/i/r is the top of the working tree of a separate repository would create a gitlink in the index, which would appear as a not-quite-initialized submodule to others. We learned to give warnings when this happens. * jk/warn-add-gitlink: t: move "git add submodule" into test blocks add: warn when adding an embedded repository
2 parents f31d23a + 17f2f88 commit cda4ba3

10 files changed

+113
-12
lines changed

Documentation/config.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,9 @@ advice.*::
348348
rmHints::
349349
In case of failure in the output of linkgit:git-rm[1],
350350
show directions on how to proceed from the current state.
351+
addEmbeddedRepo::
352+
Advice on what to do when you've accidentally added one
353+
git repo inside of another.
351354
--
352355

353356
core.fileMode::

Documentation/git-add.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,13 @@ for "git add --no-all <pathspec>...", i.e. ignored removed files.
165165
be ignored, no matter if they are already present in the work
166166
tree or not.
167167

168+
--no-warn-embedded-repo::
169+
By default, `git add` will warn when adding an embedded
170+
repository to the index without using `git submodule add` to
171+
create an entry in `.gitmodules`. This option will suppress the
172+
warning (e.g., if you are manually performing operations on
173+
submodules).
174+
168175
--chmod=(+|-)x::
169176
Override the executable bit of the added files. The executable
170177
bit is only changed in the index, the files on disk are left

advice.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ int advice_detached_head = 1;
1616
int advice_set_upstream_failure = 1;
1717
int advice_object_name_warning = 1;
1818
int advice_rm_hints = 1;
19+
int advice_add_embedded_repo = 1;
1920

2021
static struct {
2122
const char *name;
@@ -36,6 +37,7 @@ static struct {
3637
{ "setupstreamfailure", &advice_set_upstream_failure },
3738
{ "objectnamewarning", &advice_object_name_warning },
3839
{ "rmhints", &advice_rm_hints },
40+
{ "addembeddedrepo", &advice_add_embedded_repo },
3941

4042
/* make this an alias for backward compatibility */
4143
{ "pushnonfastforward", &advice_push_update_rejected }

advice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ extern int advice_detached_head;
1818
extern int advice_set_upstream_failure;
1919
extern int advice_object_name_warning;
2020
extern int advice_rm_hints;
21+
extern int advice_add_embedded_repo;
2122

2223
int git_default_advice_config(const char *var, const char *value);
2324
__attribute__((format (printf, 1, 2)))

builtin/add.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ N_("The following paths are ignored by one of your .gitignore files:\n");
250250

251251
static int verbose, show_only, ignored_too, refresh_only;
252252
static int ignore_add_errors, intent_to_add, ignore_missing;
253+
static int warn_on_embedded_repo = 1;
253254

254255
#define ADDREMOVE_DEFAULT 1
255256
static int addremove = ADDREMOVE_DEFAULT;
@@ -283,6 +284,8 @@ static struct option builtin_add_options[] = {
283284
OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
284285
OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
285286
OPT_STRING( 0 , "chmod", &chmod_arg, N_("(+/-)x"), N_("override the executable bit of the listed files")),
287+
OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
288+
N_("warn when adding an embedded repository")),
286289
OPT_END(),
287290
};
288291

@@ -296,6 +299,45 @@ static int add_config(const char *var, const char *value, void *cb)
296299
return git_default_config(var, value, cb);
297300
}
298301

302+
static const char embedded_advice[] = N_(
303+
"You've added another git repository inside your current repository.\n"
304+
"Clones of the outer repository will not contain the contents of\n"
305+
"the embedded repository and will not know how to obtain it.\n"
306+
"If you meant to add a submodule, use:\n"
307+
"\n"
308+
" git submodule add <url> %s\n"
309+
"\n"
310+
"If you added this path by mistake, you can remove it from the\n"
311+
"index with:\n"
312+
"\n"
313+
" git rm --cached %s\n"
314+
"\n"
315+
"See \"git help submodule\" for more information."
316+
);
317+
318+
static void check_embedded_repo(const char *path)
319+
{
320+
struct strbuf name = STRBUF_INIT;
321+
322+
if (!warn_on_embedded_repo)
323+
return;
324+
if (!ends_with(path, "/"))
325+
return;
326+
327+
/* Drop trailing slash for aesthetics */
328+
strbuf_addstr(&name, path);
329+
strbuf_strip_suffix(&name, "/");
330+
331+
warning(_("adding embedded git repository: %s"), name.buf);
332+
if (advice_add_embedded_repo) {
333+
advise(embedded_advice, name.buf, name.buf);
334+
/* there may be multiple entries; advise only once */
335+
advice_add_embedded_repo = 0;
336+
}
337+
338+
strbuf_release(&name);
339+
}
340+
299341
static int add_files(struct dir_struct *dir, int flags)
300342
{
301343
int i, exit_status = 0;
@@ -308,12 +350,14 @@ static int add_files(struct dir_struct *dir, int flags)
308350
exit_status = 1;
309351
}
310352

311-
for (i = 0; i < dir->nr; i++)
353+
for (i = 0; i < dir->nr; i++) {
354+
check_embedded_repo(dir->entries[i]->name);
312355
if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
313356
if (!ignore_add_errors)
314357
die(_("adding files failed"));
315358
exit_status = 1;
316359
}
360+
}
317361
return exit_status;
318362
}
319363

git-submodule.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ cmd_add()
213213
die "$(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
214214
fi
215215

216-
if test -z "$force" && ! git add --dry-run --ignore-missing "$sm_path" > /dev/null 2>&1
216+
if test -z "$force" &&
217+
! git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" > /dev/null 2>&1
217218
then
218219
eval_gettextln "The following path is ignored by one of your .gitignore files:
219220
\$sm_path
@@ -267,7 +268,7 @@ or you are unsure what this means choose another name with the '--name' option."
267268
fi
268269
git config submodule."$sm_name".url "$realrepo"
269270

270-
git add $force "$sm_path" ||
271+
git add --no-warn-embedded-repo $force "$sm_path" ||
271272
die "$(eval_gettext "Failed to add submodule '\$sm_path'")"
272273

273274
git config -f .gitmodules submodule."$sm_name".path "$sm_path" &&

t/t4041-diff-submodule-option.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -430,9 +430,11 @@ test_expect_success 'deleted submodule' '
430430
test_cmp expected actual
431431
'
432432

433-
test_create_repo sm2 &&
434-
head7=$(add_file sm2 foo8 foo9) &&
435-
git add sm2
433+
test_expect_success 'create second submodule' '
434+
test_create_repo sm2 &&
435+
head7=$(add_file sm2 foo8 foo9) &&
436+
git add sm2
437+
'
436438

437439
test_expect_success 'multiple submodules' '
438440
git diff-index -p --submodule=log HEAD >actual &&

t/t4060-diff-submodule-option-diff-format.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -643,9 +643,11 @@ test_expect_success 'deleted submodule' '
643643
test_cmp expected actual
644644
'
645645

646-
test_create_repo sm2 &&
647-
head7=$(add_file sm2 foo8 foo9) &&
648-
git add sm2
646+
test_expect_success 'create second submodule' '
647+
test_create_repo sm2 &&
648+
head7=$(add_file sm2 foo8 foo9) &&
649+
git add sm2
650+
'
649651

650652
test_expect_success 'multiple submodules' '
651653
git diff-index -p --submodule=diff HEAD >actual &&

t/t7401-submodule-summary.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,11 @@ EOF
241241
test_cmp expected actual
242242
"
243243

244-
test_create_repo sm2 &&
245-
head7=$(add_file sm2 foo8 foo9) &&
246-
git add sm2
244+
test_expect_success 'create second submodule' '
245+
test_create_repo sm2 &&
246+
head7=$(add_file sm2 foo8 foo9) &&
247+
git add sm2
248+
'
247249

248250
test_expect_success 'multiple submodules' "
249251
git submodule summary >actual &&

t/t7414-submodule-mistakes.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/bin/sh
2+
3+
test_description='handling of common mistakes people may make with submodules'
4+
. ./test-lib.sh
5+
6+
test_expect_success 'create embedded repository' '
7+
git init embed &&
8+
test_commit -C embed one
9+
'
10+
11+
test_expect_success 'git-add on embedded repository warns' '
12+
test_when_finished "git rm --cached -f embed" &&
13+
git add embed 2>stderr &&
14+
test_i18ngrep warning stderr
15+
'
16+
17+
test_expect_success '--no-warn-embedded-repo suppresses warning' '
18+
test_when_finished "git rm --cached -f embed" &&
19+
git add --no-warn-embedded-repo embed 2>stderr &&
20+
test_i18ngrep ! warning stderr
21+
'
22+
23+
test_expect_success 'no warning when updating entry' '
24+
test_when_finished "git rm --cached -f embed" &&
25+
git add embed &&
26+
git -C embed commit --allow-empty -m two &&
27+
git add embed 2>stderr &&
28+
test_i18ngrep ! warning stderr
29+
'
30+
31+
test_expect_success 'submodule add does not warn' '
32+
test_when_finished "git rm -rf submodule .gitmodules" &&
33+
git submodule add ./embed submodule 2>stderr &&
34+
test_i18ngrep ! warning stderr
35+
'
36+
37+
test_done

0 commit comments

Comments
 (0)