Skip to content

Commit 58a9142

Browse files
committed
Merge branch 'cs/add-skip-submodule-ignore-all' into seen
"git add <submodule>" has been taught to honor submodule.<name>.ignore that is set to "all" (and requires "git add -f" to override it). Comments? * cs/add-skip-submodule-ignore-all: Documentation: update add --force option + ignore=all config tests: fix existing tests when add an ignore=all submodule tests: t2206-add-submodule-ignored: ignore=all and add --force tests read-cache: submodule add need --force given ignore=all configuration read-cache: update add_files_to_cache take param ignored_too
2 parents fd1e43c + 6cc6d1b commit 58a9142

File tree

12 files changed

+235
-19
lines changed

12 files changed

+235
-19
lines changed

Documentation/config/submodule.adoc

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,16 @@ submodule.<name>.fetchRecurseSubmodules::
3232

3333
submodule.<name>.ignore::
3434
Defines under what circumstances "git status" and the diff family show
35-
a submodule as modified. When set to "all", it will never be considered
36-
modified (but it will nonetheless show up in the output of status and
37-
commit when it has been staged), "dirty" will ignore all changes
38-
to the submodule's work tree and
35+
a submodule as modified.
36+
When set to "all" will never consider the submodule modified. It can
37+
nevertheless be staged using the option --force and it will then show up
38+
in the output of status.
39+
When set to "dirty" will ignore all changes to the submodule's work tree and
3940
takes only differences between the HEAD of the submodule and the commit
4041
recorded in the superproject into account. "untracked" will additionally
4142
let submodules with modified tracked files in their work tree show up.
42-
Using "none" (the default when this option is not set) also shows
43-
submodules that have untracked files in their work tree as changed.
43+
When set to "none"(default) It also show submodules as changed if they have
44+
untracked files in their work tree.
4445
This setting overrides any setting made in .gitmodules for this submodule,
4546
both settings can be overridden on the command line by using the
4647
"--ignore-submodules" option. The 'git submodule' commands are not

Documentation/git-add.adoc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ in linkgit:gitglossary[7].
7575
7676
`-f`::
7777
`--force`::
78-
Allow adding otherwise ignored files.
78+
Allow adding otherwise ignored files. The option is also used when
79+
`submodule.<name>.ignore=all` is set, but you want to stage an
80+
update of the submodule. The `path` to the submodule must be explicitly
81+
specified.
7982
8083
`--sparse`::
8184
Allow updating index entries outside of the sparse-checkout cone.

Documentation/gitmodules.adoc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@ submodule.<name>.ignore::
7070
--
7171
all;; The submodule will never be considered modified (but will
7272
nonetheless show up in the output of status and commit when it has
73-
been staged).
73+
been staged). Add `(new commits)` can be overruled using the
74+
`git add --force <submodule.path>`.
75+
The setting affects `status`, `update-index`, `diff` and `log`(due
76+
to underlaying `diff`).
7477

7578
dirty;; All changes to the submodule's work tree will be ignored, only
7679
committed differences between the `HEAD` of the submodule and its

builtin/add.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ int cmd_add(int argc,
588588
else
589589
exit_status |= add_files_to_cache(repo, prefix,
590590
&pathspec, ps_matched,
591-
include_sparse, flags);
591+
include_sparse, flags, ignored_too);
592592

593593
if (take_worktree_changes && !add_renormalize && !ignore_add_errors &&
594594
report_path_error(ps_matched, &pathspec))

builtin/checkout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
888888
*/
889889

890890
add_files_to_cache(the_repository, NULL, NULL, NULL, 0,
891-
0);
891+
0, 0);
892892
init_ui_merge_options(&o, the_repository);
893893
o.verbosity = 0;
894894
work = write_in_core_index_as_tree(the_repository);

builtin/commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
456456
repo_hold_locked_index(the_repository, &index_lock,
457457
LOCK_DIE_ON_ERROR);
458458
add_files_to_cache(the_repository, also ? prefix : NULL,
459-
&pathspec, ps_matched, 0, 0);
459+
&pathspec, ps_matched, 0, 0, 0 );
460460
if (!all && report_path_error(ps_matched, &pathspec))
461461
exit(128);
462462

read-cache-ll.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ int cmp_cache_name_compare(const void *a_, const void *b_);
481481

482482
int add_files_to_cache(struct repository *repo, const char *prefix,
483483
const struct pathspec *pathspec, char *ps_matched,
484-
int include_sparse, int flags);
484+
int include_sparse, int flags, int ignored_too );
485485

486486
void overlay_tree_on_index(struct index_state *istate,
487487
const char *tree_name, const char *prefix);

read-cache.c

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
#include "csum-file.h"
4848
#include "promisor-remote.h"
4949
#include "hook.h"
50+
#include "submodule.h"
51+
#include "submodule-config.h"
52+
#include "advice.h"
5053

5154
/* Mask for the name length in ce_flags in the on-disk index */
5255

@@ -3889,9 +3892,12 @@ void overlay_tree_on_index(struct index_state *istate,
38893892

38903893
struct update_callback_data {
38913894
struct index_state *index;
3895+
struct repository *repo;
3896+
struct pathspec *pathspec;
38923897
int include_sparse;
38933898
int flags;
38943899
int add_errors;
3900+
int ignored_too;
38953901
};
38963902

38973903
static int fix_unmerged_status(struct diff_filepair *p,
@@ -3915,8 +3921,68 @@ static int fix_unmerged_status(struct diff_filepair *p,
39153921
return DIFF_STATUS_MODIFIED;
39163922
}
39173923

3924+
static int skip_submodule(const char *path,
3925+
struct repository *repo,
3926+
struct pathspec *pathspec,
3927+
int ignored_too)
3928+
{
3929+
struct stat st;
3930+
const struct submodule *sub;
3931+
int pathspec_matches = 0;
3932+
int ps_i;
3933+
char *norm_pathspec = NULL;
3934+
3935+
/* Only consider if path is a directory */
3936+
if (lstat(path, &st) || !S_ISDIR(st.st_mode))
3937+
return 0;
3938+
3939+
/* Check if it's a submodule with ignore=all */
3940+
sub = submodule_from_path(repo, null_oid(the_hash_algo), path);
3941+
if (!sub || !sub->name || !sub->ignore || strcmp(sub->ignore, "all"))
3942+
return 0;
3943+
3944+
trace_printf("ignore=all: %s\n", path);
3945+
trace_printf("pathspec %s\n", (pathspec && pathspec->nr)
3946+
? "has pathspec"
3947+
: "no pathspec");
3948+
3949+
/* Check if submodule path is explicitly mentioned in pathspec */
3950+
if (pathspec) {
3951+
for (ps_i = 0; ps_i < pathspec->nr; ps_i++) {
3952+
const char *m = pathspec->items[ps_i].match;
3953+
if (!m)
3954+
continue;
3955+
norm_pathspec = xstrdup(m);
3956+
strip_dir_trailing_slashes(norm_pathspec);
3957+
if (!strcmp(path, norm_pathspec)) {
3958+
pathspec_matches = 1;
3959+
FREE_AND_NULL(norm_pathspec);
3960+
break;
3961+
}
3962+
FREE_AND_NULL(norm_pathspec);
3963+
}
3964+
}
3965+
3966+
/* If explicitly matched and forced, allow adding */
3967+
if (pathspec_matches) {
3968+
if (ignored_too && ignored_too > 0) {
3969+
trace_printf("Add submodule due to --force: %s\n", path);
3970+
return 0;
3971+
} else {
3972+
advise_if_enabled(ADVICE_ADD_IGNORED_FILE,
3973+
_("Skipping submodule due to ignore=all: %s\n"
3974+
"Use --force if you really want to add the submodule."), path);
3975+
return 1;
3976+
}
3977+
}
3978+
3979+
/* No explicit pathspec match -> skip silently */
3980+
trace_printf("Pathspec to submodule does not match explicitly: %s\n", path);
3981+
return 1;
3982+
}
3983+
39183984
static void update_callback(struct diff_queue_struct *q,
3919-
struct diff_options *opt UNUSED, void *cbdata)
3985+
struct diff_options *opt UNUSED, void *cbdata)
39203986
{
39213987
int i;
39223988
struct update_callback_data *data = cbdata;
@@ -3926,14 +3992,19 @@ static void update_callback(struct diff_queue_struct *q,
39263992
const char *path = p->one->path;
39273993

39283994
if (!data->include_sparse &&
3929-
!path_in_sparse_checkout(path, data->index))
3995+
!path_in_sparse_checkout(path, data->index))
39303996
continue;
39313997

39323998
switch (fix_unmerged_status(p, data)) {
39333999
default:
39344000
die(_("unexpected diff status %c"), p->status);
39354001
case DIFF_STATUS_MODIFIED:
39364002
case DIFF_STATUS_TYPE_CHANGED:
4003+
if (skip_submodule(path, data->repo,
4004+
data->pathspec,
4005+
data->ignored_too))
4006+
continue;
4007+
39374008
if (add_file_to_index(data->index, path, data->flags)) {
39384009
if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
39394010
die(_("updating files failed"));
@@ -3954,7 +4025,7 @@ static void update_callback(struct diff_queue_struct *q,
39544025

39554026
int add_files_to_cache(struct repository *repo, const char *prefix,
39564027
const struct pathspec *pathspec, char *ps_matched,
3957-
int include_sparse, int flags)
4028+
int include_sparse, int flags, int ignored_too )
39584029
{
39594030
struct odb_transaction *transaction;
39604031
struct update_callback_data data;
@@ -3964,6 +4035,9 @@ int add_files_to_cache(struct repository *repo, const char *prefix,
39644035
data.index = repo->index;
39654036
data.include_sparse = include_sparse;
39664037
data.flags = flags;
4038+
data.repo = repo;
4039+
data.ignored_too = ignored_too;
4040+
data.pathspec = (struct pathspec *)pathspec;
39674041

39684042
repo_init_revisions(repo, &rev, prefix);
39694043
setup_revisions(0, NULL, &rev, NULL);

t/lib-submodule-update.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,14 @@ create_lib_submodule_repo () {
9595
git commit -m "modified file2 and added file3" &&
9696
git push origin modifications
9797
) &&
98-
git add sub1 &&
98+
git add --force sub1 &&
9999
git commit -m "Modify sub1" &&
100100

101101
git checkout -b add_nested_sub modify_sub1 &&
102102
git -C sub1 checkout -b "add_nested_sub" &&
103103
git -C sub1 submodule add --branch no_submodule ../submodule_update_sub2 sub2 &&
104104
git -C sub1 commit -a -m "add a nested submodule" &&
105-
git add sub1 &&
105+
git add --force sub1 &&
106106
git commit -a -m "update submodule, that updates a nested submodule" &&
107107
git checkout -b modify_sub1_recursively &&
108108
git -C sub1 checkout -b modify_sub1_recursively &&
@@ -112,7 +112,7 @@ create_lib_submodule_repo () {
112112
git -C sub1/sub2 commit -m "make a change in nested sub" &&
113113
git -C sub1 add sub2 &&
114114
git -C sub1 commit -m "update nested sub" &&
115-
git add sub1 &&
115+
git add --force sub1 &&
116116
git commit -m "update sub1, that updates nested sub" &&
117117
git -C sub1 push origin modify_sub1_recursively &&
118118
git -C sub1/sub2 push origin modify_sub1_recursively &&

t/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ integration_tests = [
296296
't2203-add-intent.sh',
297297
't2204-add-ignored.sh',
298298
't2205-add-worktree-config.sh',
299+
't2206-add-submodule-ignored.sh',
299300
't2300-cd-to-toplevel.sh',
300301
't2400-worktree-add.sh',
301302
't2401-worktree-prune.sh',

0 commit comments

Comments
 (0)