tests: t2206-add-submodule-ignored: ignore=all and add --force tests

The tests verify that the submodule behavior is intact and updating the config with ignore=all also behaves as intended with configuration in .gitmodules and configuration given on the command line. The usage of --force is showcased and tested in the test suite. The test file is added to meson.build for execution. Signed-off-by: Claus Schneider(Eficode) <claus.schneider@eficode.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Claus Schneider(Eficode) committed Feb 6, 2026 at 13:22 UTC 297a27fdf2f68e95d7e344a22f20d9053b74b3ac
2 files changed +135
t/meson.build
+1
@@ -292,6 +292,7 @@ integration_tests = [
292 't2203-add-intent.sh',
293 't2204-add-ignored.sh',
294 't2205-add-worktree-config.sh',
295 + 't2206-add-submodule-ignored.sh',
296 't2300-cd-to-toplevel.sh',
297 't2400-worktree-add.sh',
298 't2401-worktree-prune.sh',
t/t2206-add-submodule-ignored.sh new
+134
@@ -0,0 +1,134 @@
1 +#!/bin/sh
2 +# shellcheck disable=SC2016
3 +
4 +# shellcheck disable=SC2034
5 +test_description='git add respects submodule ignore=all and explicit pathspec'
6 +
7 +# This test covers the behavior of "git add", "git status" and "git log" when
8 +# dealing with submodules that have the ignore=all setting in
9 +# .gitmodules. It ensures that changes in such submodules are
10 +# ignored by default, but can be staged with "git add --force".
11 +
12 +# shellcheck disable=SC1091
13 +. ./test-lib.sh
14 +
15 +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
16 +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
17 +
18 +base_path=$(pwd -P)
19 +
20 +#1
21 +test_expect_success 'setup: create origin repos' '
22 + cd "${base_path}" &&
23 + git config --global protocol.file.allow always &&
24 + git init sub &&
25 + pwd &&
26 + cd sub &&
27 + test_commit sub_file1 &&
28 + git tag v1.0 &&
29 + test_commit sub_file2 &&
30 + git tag v2.0 &&
31 + test_commit sub_file3 &&
32 + git tag v3.0 &&
33 + cd "${base_path}" &&
34 + git init main &&
35 + cd main &&
36 + test_commit first &&
37 + cd "${base_path}"
38 +'
39 +#2
40 +# add submodule with default config (ignore=none) and
41 +# check log that is contains a path entry for the submodule 'sub'
42 +# change the commit in the submodule and check that 'git status' shows it as modified
43 +test_expect_success 'main: add submodule with default config' '
44 + cd "${base_path}" &&
45 + cd main &&
46 + git submodule add ../sub &&
47 + git commit -m "add submodule" &&
48 + git log --oneline --name-only | grep "^sub$" &&
49 + git -C sub reset --hard v2.0 &&
50 + git status --porcelain | grep "^ M sub$" &&
51 + echo
52 +'
53 +#3
54 +# change the submodule config to ignore=all and check that status and log do not show changes
55 +test_expect_success 'main: submodule config ignore=all' '
56 + cd "${base_path}" &&
57 + cd main &&
58 + git config -f .gitmodules submodule.sub.ignore all &&
59 + GIT_TRACE=1 git add . &&
60 + git commit -m "update submodule config sub.ignore all" &&
61 + ! git status --porcelain | grep "^.*$" &&
62 + ! git log --oneline --name-only | grep "^sub$" &&
63 + echo
64 +'
65 +#4
66 +# change the commit in the submodule and check that 'git status' does not show it as modified
67 +# but 'git status --ignore-submodules=none' does show it as modified
68 +test_expect_success 'sub: change to different sha1 and check status in main' '
69 + cd "${base_path}" &&
70 + cd main &&
71 + git -C sub reset --hard v1.0 &&
72 + ! git status --porcelain | grep "^ M sub$" &&
73 + git status --ignore-submodules=none --porcelain | grep "^ M sub$" &&
74 + echo
75 +'
76 +
77 +#5
78 +# check that normal 'git add' does not stage the change in the submodule
79 +test_expect_success 'main: check normal add and status' '
80 + cd "${base_path}" &&
81 + cd main &&
82 + GIT_TRACE=1 git add . &&
83 + ! git status --porcelain | grep "^ M sub$" &&
84 + echo
85 +'
86 +
87 +#6
88 +# check that 'git add --force .' does not stage the change in the submodule
89 +# and that 'git status' does not show it as modified
90 +test_expect_success 'main: check --force add . and status' '
91 + cd "${base_path}" &&
92 + cd main &&
93 + GIT_TRACE=1 git add --force . &&
94 + ! git status --porcelain | grep "^M sub$" &&
95 + echo
96 +'
97 +
98 +#7
99 +# check that 'git add .' does not stage the change in the submodule
100 +# and that 'git status' does not show it as modified
101 +test_expect_success 'main: check _add sub_ and status' '
102 + cd "${base_path}" &&
103 + cd main &&
104 + GIT_TRACE=1 git add sub 2>&1 | grep "Skipping submodule due to ignore=all: sub" &&
105 + ! git status --porcelain | grep "^M sub$" &&
106 + echo
107 +'
108 +
109 +#8
110 +# check that 'git add --force sub' does stage the change in the submodule
111 +# check that 'git add --force ./sub/' does stage the change in the submodule
112 +# and that 'git status --porcelain' does show it as modified
113 +# commit it..
114 +# check that 'git log --ignore-submodules=none' shows the submodule change
115 +# in the log
116 +test_expect_success 'main: check force add sub and ./sub/ and status' '
117 + cd "${base_path}" &&
118 + cd main &&
119 + echo "Adding with --force should work: git add --force sub" &&
120 + GIT_TRACE=1 git add --force sub &&
121 + git status --porcelain | grep "^M sub$" &&
122 + git restore --staged sub &&
123 + ! git status --porcelain | grep "^M sub$" &&
124 + echo "Adding with --force should work: git add --force ./sub/" &&
125 + GIT_TRACE=1 git add --force ./sub/ &&
126 + git status --porcelain | grep "^M sub$" &&
127 + git commit -m "update submodule pointer" &&
128 + ! git status --porcelain | grep "^ M sub$" &&
129 + git log --ignore-submodules=none --name-only --oneline | grep "^sub$" &&
130 + echo
131 +'
132 +
133 +test_done
134 +exit 0