diff mbox series

[Outreachy,v6] diff: do not show submodule with untracked files as "-dirty"

Message ID 20201026175742.33356-1-sangunb09@gmail.com (mailing list archive)
State Superseded
Headers show
Series [Outreachy,v6] diff: do not show submodule with untracked files as "-dirty" | expand

Commit Message

Sangeeta Oct. 26, 2020, 5:57 p.m. UTC
Git diff reports a submodule directory as -dirty even when there are
only untracked files in the submodule directory. This is inconsistent
with what `git describe --dirty` says when run in the submodule
directory in that state.

Make `--ignore-submodules=untracked` the default for `git diff` when
there is no configuration variable or command line option, so that the
command would not give '-dirty' suffix to a submodule whose working
tree has untracked files, to make it consistent with `git
describe --dirty` that is run in the submodule working tree.

Signed-off-by: Sangeeta Jain <sangunb09@gmail.com>
---
 diff.c                                       |   3 +
 diff.h                                       |   1 +
 submodule.c                                  |   3 +
 t/t3701-add-interactive.sh                   |   5 +
 t/t4027-diff-submodule.sh                    |  12 ++-
 t/t4041-diff-submodule-option.sh             |  16 +--
 t/t4060-diff-submodule-option-diff-format.sh |  16 +--
 t/t7064-wtstatus-pv2.sh                      |  52 ++++++++++
 t/t7506-status-submodule.sh                  | 102 ++++++++++++++++---
 9 files changed, 180 insertions(+), 30 deletions(-)

Comments

Sangeeta Nov. 3, 2020, 10:46 a.m. UTC | #1
Hey Johannes and Junio,

In continuation of the discussion from here[1]

[1] https://lore.kernel.org/git/nycvar.QRO.7.76.6.2011020251520.18437@tvgsbejvaqbjf.bet/

> >> * sj/untracked-files-in-submodule-directory-is-not-dirty (2020-10-26) 1 commit
> >>  - diff: do not show submodule with untracked files as "-dirty"
> >>
> >>  "git diff" showed a submodule working tree with untracked cruft as
> >>  "Submodule commit <objectname>-dirty", but a natural expectation is
> >>  that the "-dirty" indicator would align with "git describe --dirty",
> >>  which does not consider having untracked files in the working tree
> >>  as source of dirtiness.  The inconsistency has been fixed.
> >>
> >>  Needs doc update.

Do I need to add the doc update in the same patch?

> > I *think* the original rationale for marking submodules with untracked
> > (_un-ignored_) files was to avoid deleting a submodule that has
> > uncommitted (because untracked) files.
>
> I agree with you that that the motivation was exactly that, but I
> have a suspicion that its execution was misguided.

I am really very sorry if I ended up adding some unwanted code.

>
> When one has a subdirectory D where one might or might not have an
> untracked new file that one does not want to lose, but one otherwise
> would want to clean up (perhaps an errant process created tons of
> garbage files in the directory), one would not
>
>         git diff D
>
> to see if there are important changes in that directory before doing
>
>         rm -rf D && git checkout D
>
> to bring it back to pristine state, exactly because one would not
> want to lose newly-created but not added files.  One would instead
> use
>
>         git status D
>
> for checking.  Why would a user change the habit when D happens to
> be a submodule?
>
> So I would say that "git status [D]", if it does not let the user
> notice that there is untracked contents in the submodule working
> tree, would be a bad idea.  "git diff" that ignores untracked paths
> in the submodule working tree, on the other hand, is a good thing.
>
> Now, the patch as-is may change the behaviour of "git status D" in
> this case, and the internal invocation of diff-files made somewhere
> in wt-status.c may have to be adjusted to keep such a submodule with
> forgotten newly created files shown as modified.
>
> Further discussion on this should be done on the original review
> thread for continuity, not here, in any case.
>

So we want that `git status` should behave in the same way as it was
behaving before? Can we do this by passing --ignore-submodules=none as
the default args for status? Another approach might be to figure out
how the diff is being called(like is this being called from git status
or git diff) and then add the --ignore-submodules=untracked behavior
to it accordingly. Though I have no idea how to do that now.

Please correct me if I am completely going in the wrong direction. As
it is my first time contributing to git, so any help would be greatly
beneficial for me.

Thanks and regards,
Sangeeta
Junio C Hamano Nov. 3, 2020, 5:55 p.m. UTC | #2
Sangeeta <sangunb09@gmail.com> writes:

> Hey Johannes and Junio,
>
> In continuation of the discussion from here[1]
>
> [1] https://lore.kernel.org/git/nycvar.QRO.7.76.6.2011020251520.18437@tvgsbejvaqbjf.bet/
>
>> >> * sj/untracked-files-in-submodule-directory-is-not-dirty (2020-10-26) 1 commit
>> >>  - diff: do not show submodule with untracked files as "-dirty"
>> >>
>> >>  "git diff" showed a submodule working tree with untracked cruft as
>> >>  "Submodule commit <objectname>-dirty", but a natural expectation is
>> >>  that the "-dirty" indicator would align with "git describe --dirty",
>> >>  which does not consider having untracked files in the working tree
>> >>  as source of dirtiness.  The inconsistency has been fixed.
>> >>
>> >>  Needs doc update.
>
> Do I need to add the doc update in the same patch?

It is ideal if code change, tests and documentation are done
atomically.  For a large series the story may be different, but I
thought a single commit would be sufficient for this topic?

>> > I *think* the original rationale for marking submodules with untracked
>> > (_un-ignored_) files was to avoid deleting a submodule that has
>> > uncommitted (because untracked) files.
>>
>> I agree with you that that the motivation was exactly that, but I
>> have a suspicion that its execution was misguided.
>
> I am really very sorry if I ended up adding some unwanted code.

But you did not.  The "motivation" and "execution" are both from
long time ago, back when submodule support was invented and "git
diff" in the superproject was taught to pay attention to submodules.

Dscho suspects that "git diff" were taught to add "-dirty" to
submodules with untracked files in their working tree in order to
protect them from those who are about to delete them as a way to
check if it is safe.  I agreed that the motivation may have been so,
i.e. they wanted to protect users from losing untracked files that
they forgot to add and commit in the submodule, but the execution
was wrong, i.e. "git diff" is not the right tool to achieve that
protection.

See that you didn't add any unwanted code---it all happened long
time ago ;-)

> So we want that `git status` should behave in the same way as it was
> behaving before? Can we do this by passing --ignore-submodules=none as
> the default args for status?

Yes, I do not recall offhand where in wt-status.c "git status" does so,
but there should be an internal invocation of diff-files somewhere, and
I suspect it is not passing any --ignore-submodules bit.  Just like
wt_status_collect_changes_index() calls handle_ignore_submodules_arg()
with hardcoded "dirty", we may have to unignore untracked files in
submodule working trees when checking the working tree changes.

> Another approach might be to figure out
> how the diff is being called(like is this being called from git status
> or git diff) and then add the --ignore-submodules=untracked behavior
> to it accordingly. Though I have no idea how to do that now.

No, callee shouldn't have knowledge of its caller to perform a
special case action.  The caller should say how it wants its callees
to behave.

Thanks.
Sangeeta Nov. 7, 2020, 10:47 a.m. UTC | #3
Hey,

I worked on passing --ignore-submodules=none as the default behavior
of git status so that the user doesn't end up deleting a submodule
that has uncommitted (untracked) files.

The following changes make git status pass the ignoreSubmodules none
argument as default.

@@ -4587,7 +4587,7 @@ void repo_diff_setup(struct repository *r,
struct diff_options *options)
        options->orderfile = diff_order_file_cfg;

        if (!options->flags.ignore_submodule_set)
-               handle_ignore_submodules_arg(options, "untracked");
+               options->flags.ignore_untracked_in_submodules = 1;

        if (diff_no_prefix) {
                options->a_prefix = options->b_prefix = "";


@@ -607,6 +607,9 @@ static void
wt_status_collect_changes_worktree(struct wt_status *s)
                rev.diffopt.flags.override_submodule_config = 1;
                handle_ignore_submodules_arg(&rev.diffopt,
s->ignore_submodule_arg);
        }
+       else if(!rev.diffopt.flags.ignore_submodule_set){
+               handle_ignore_submodules_arg(&rev.diffopt, "none");
+       }

I have had to set the flag manually in diff.c because when we call
handle_ignore_submodules_arg() with "untracked" arg,
options->flags.ignore_submodule_set is set to 1 and therefore when we
check for it in wt-status.c it appears that user has already set some
config and therefore we shouldn't add "none" as ignoreSubmodules arg.

Another way to do that is to have one more flag in diff_options that
can let us know whether options->flags.ignore_submodule_set was set by
the user or by diff passing untracked as the default argument.

Can someone please help me with what might be the right way to proceed?

Thanks!
Đoàn Trần Công Danh Nov. 7, 2020, 11:10 a.m. UTC | #4
Hi Sangeeta,

On 2020-10-26 23:27:42+0530, Sangeeta Jain <sangunb09@gmail.com> wrote:
> diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
> index ca04fac417..9104d1946d 100755
> --- a/t/t3701-add-interactive.sh
> +++ b/t/t3701-add-interactive.sh
> @@ -765,6 +765,11 @@ test_expect_success 'setup different kinds of dirty submodules' '
>  	cat >expected <<-\EOF &&
>  	dirty-both-ways
>  	dirty-head
> +	EOF
> +	git -C for-submodules diff-files --name-only --ignore-submodules=none >actual &&
> +	cat >expected <<-\EOF &&
> +	dirty-both-ways
> +	dirty-head

This will throw-away above change to "expected", I think this is not
what you expected to write!

>  	dirty-otherwise
>  	EOF
>  	test_cmp expected actual &&
> diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh
> index d7145ccca4..894a11b224 100755
> --- a/t/t4027-diff-submodule.sh
> +++ b/t/t4027-diff-submodule.sh
> @@ -93,6 +93,14 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked)' '
>  	) &&
>  	git diff HEAD >actual &&
>  	sed -e "1,/^@@/d" actual >actual.body &&
> +	expect_from_to >expect.body $subtip $subprev &&
> +	test_cmp expect.body actual.body
> +'
> +
> +test_expect_success 'git diff HEAD with dirty submodule (untracked) (none ignored)' '
> +	test_config diff.ignoreSubmodules none &&
> +	git diff HEAD >actual &&
> +	sed -e "1,/^@@/d" actual >actual.body &&
>  	expect_from_to >expect.body $subtip $subprev-dirty &&
>  	test_cmp expect.body actual.body
>  '
> @@ -168,13 +176,13 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)'
>  		git clean -qfdx &&
>  		>cruft
>  	) &&
> -	git diff HEAD >actual &&
> +	git diff --ignore-submodules=none HEAD >actual &&
>  	sed -e "1,/^@@/d" actual >actual.body &&
>  	expect_from_to >expect.body $subprev $subprev-dirty &&
>  	test_cmp expect.body actual.body &&
>  	git diff --ignore-submodules=all HEAD >actual2 &&
>  	test_must_be_empty actual2 &&
> -	git diff --ignore-submodules=untracked HEAD >actual3 &&
> +	git diff HEAD >actual3 &&
>  	test_must_be_empty actual3 &&
>  	git diff --ignore-submodules=dirty HEAD >actual4 &&
>  	test_must_be_empty actual4
> diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh
> index f852136585..bb368b685d 100755
> --- a/t/t4041-diff-submodule-option.sh
> +++ b/t/t4041-diff-submodule-option.sh
> @@ -262,7 +262,7 @@ test_expect_success 'submodule is up to date' '
>  
>  test_expect_success 'submodule contains untracked content' '
>  	echo new > sm1/new-file &&
> -	git diff-index -p --submodule=log HEAD >actual &&
> +	git diff-index -p --submodule=log HEAD --ignore-submodules=none >actual &&

Nit:

I suspect that we're in favour of writing all optional argument before
all committish here.

IOW, I think we're better move HEAD after --ignore-submodules=none

>  	cat >expected <<-EOF &&
>  	Submodule sm1 contains untracked content
>  	EOF
> @@ -270,7 +270,7 @@ test_expect_success 'submodule contains untracked content' '
>  '
>  
>  test_expect_success 'submodule contains untracked content (untracked ignored)' '
> -	git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
> +	git diff-index -p --submodule=log HEAD >actual &&
>  	test_must_be_empty actual
>  '
>  
> @@ -286,7 +286,7 @@ test_expect_success 'submodule contains untracked content (all ignored)' '
>  
>  test_expect_success 'submodule contains untracked and modified content' '
>  	echo new > sm1/foo6 &&
> -	git diff-index -p --submodule=log HEAD >actual &&
> +	git diff-index -p --submodule=log HEAD --ignore-submodules=none >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 contains untracked content
>  	Submodule sm1 contains modified content
> @@ -296,7 +296,7 @@ test_expect_success 'submodule contains untracked and modified content' '
>  
>  test_expect_success 'submodule contains untracked and modified content (untracked ignored)' '
>  	echo new > sm1/foo6 &&
> -	git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
> +	git diff-index -p --submodule=log HEAD >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 contains modified content
>  	EOF
> @@ -337,7 +337,7 @@ test_expect_success 'submodule is modified' '
>  
>  test_expect_success 'modified submodule contains untracked content' '
>  	echo new > sm1/new-file &&
> -	git diff-index -p --submodule=log HEAD >actual &&
> +	git diff-index -p  --ignore-submodules=none --submodule=log HEAD >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 contains untracked content
>  	Submodule sm1 $head6..$head8:
> @@ -347,7 +347,7 @@ test_expect_success 'modified submodule contains untracked content' '
>  '
>  
>  test_expect_success 'modified submodule contains untracked content (untracked ignored)' '
> -	git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
> +	git diff-index -p --submodule=log HEAD >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 $head6..$head8:
>  	  > change
> @@ -371,7 +371,7 @@ test_expect_success 'modified submodule contains untracked content (all ignored)
>  
>  test_expect_success 'modified submodule contains untracked and modified content' '
>  	echo modification >> sm1/foo6 &&
> -	git diff-index -p --submodule=log HEAD >actual &&
> +	git diff-index -p --ignore-submodules=none --submodule=log HEAD >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 contains untracked content
>  	Submodule sm1 contains modified content
> @@ -383,7 +383,7 @@ test_expect_success 'modified submodule contains untracked and modified content'
>  
>  test_expect_success 'modified submodule contains untracked and modified content (untracked ignored)' '
>  	echo modification >> sm1/foo6 &&
> -	git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
> +	git diff-index -p --submodule=log HEAD >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 contains modified content
>  	Submodule sm1 $head6..$head8:
> diff --git a/t/t4060-diff-submodule-option-diff-format.sh b/t/t4060-diff-submodule-option-diff-format.sh
> index fc8229c726..dc7b242697 100755
> --- a/t/t4060-diff-submodule-option-diff-format.sh
> +++ b/t/t4060-diff-submodule-option-diff-format.sh
> @@ -409,7 +409,7 @@ test_expect_success 'submodule is up to date' '
>  
>  test_expect_success 'submodule contains untracked content' '
>  	echo new > sm1/new-file &&
> -	git diff-index -p --submodule=diff HEAD >actual &&
> +	git diff-index -p --ignore-submodules=none --submodule=diff HEAD >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 contains untracked content
>  	EOF
> @@ -417,7 +417,7 @@ test_expect_success 'submodule contains untracked content' '
>  '
>  
>  test_expect_success 'submodule contains untracked content (untracked ignored)' '
> -	git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
> +	git diff-index -p --submodule=diff HEAD >actual &&
>  	test_must_be_empty actual
>  '
>  
> @@ -433,7 +433,7 @@ test_expect_success 'submodule contains untracked content (all ignored)' '
>  
>  test_expect_success 'submodule contains untracked and modified content' '
>  	echo new > sm1/foo6 &&
> -	git diff-index -p --submodule=diff HEAD >actual &&
> +	git diff-index -p --ignore-submodules=none --submodule=diff HEAD >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 contains untracked content
>  	Submodule sm1 contains modified content
> @@ -451,7 +451,7 @@ test_expect_success 'submodule contains untracked and modified content' '
>  # NOT OK
>  test_expect_success 'submodule contains untracked and modified content (untracked ignored)' '
>  	echo new > sm1/foo6 &&
> -	git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
> +	git diff-index -p --submodule=diff HEAD >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 contains modified content
>  	diff --git a/sm1/foo6 b/sm1/foo6
> @@ -512,7 +512,7 @@ test_expect_success 'submodule is modified' '
>  
>  test_expect_success 'modified submodule contains untracked content' '
>  	echo new > sm1/new-file &&
> -	git diff-index -p --submodule=diff HEAD >actual &&
> +	git diff-index -p --ignore-submodules=none --submodule=diff HEAD >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 contains untracked content
>  	Submodule sm1 $head7..$head8:
> @@ -528,7 +528,7 @@ test_expect_success 'modified submodule contains untracked content' '
>  '
>  
>  test_expect_success 'modified submodule contains untracked content (untracked ignored)' '
> -	git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
> +	git diff-index -p --submodule=diff HEAD >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 $head7..$head8:
>  	diff --git a/sm1/foo6 b/sm1/foo6
> @@ -564,7 +564,7 @@ test_expect_success 'modified submodule contains untracked content (all ignored)
>  
>  test_expect_success 'modified submodule contains untracked and modified content' '
>  	echo modification >> sm1/foo6 &&
> -	git diff-index -p --submodule=diff HEAD >actual &&
> +	git diff-index -p --ignore-submodules=none --submodule=diff HEAD >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 contains untracked content
>  	Submodule sm1 contains modified content
> @@ -583,7 +583,7 @@ test_expect_success 'modified submodule contains untracked and modified content'
>  
>  test_expect_success 'modified submodule contains untracked and modified content (untracked ignored)' '
>  	echo modification >> sm1/foo6 &&
> -	git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
> +	git diff-index -p --submodule=diff HEAD >actual &&
>  	cat >expected <<-EOF &&
>  	Submodule sm1 contains modified content
>  	Submodule sm1 $head7..$head8:
> diff --git a/t/t7064-wtstatus-pv2.sh b/t/t7064-wtstatus-pv2.sh
> index 537787e598..78cd86be3a 100755
> --- a/t/t7064-wtstatus-pv2.sh
> +++ b/t/t7064-wtstatus-pv2.sh
> @@ -503,6 +503,31 @@ test_expect_success 'untracked changes in added submodule (AM S..U)' '
>  		1 AM S..U 000000 160000 160000 $ZERO_OID $HSUB sub1
>  		EOF
>  
> +		git status --porcelain=v2 --branch --untracked-files=all --ignore-submodules=none >actual &&
> +		test_cmp expect actual
> +	)
> +'
> +
> +test_expect_success 'untracked changes in added submodule (A. S...) (untracked ignored)' '
> +	(	cd super_repo &&
> +		## create untracked file in the submodule.
> +		(	cd sub1 &&
> +			echo "xxxx" >file_in_sub
> +		) &&

Another nit: I think we can avoid subshell by:
	
	echo "xxxx" >sub1/file_in_sub

In general, I think other usages of subshell in this patch could be
replaced by above syntax for echo and "git -C subdir" for git.

> +
> +		HMOD=$(git hash-object -t blob -- .gitmodules) &&
> +		HSUP=$(git rev-parse HEAD) &&
> +		HSUB=$HSUP &&
> +
> +		cat >expect <<-EOF &&
> +		# branch.oid $HSUP
> +		# branch.head master
> +		# branch.upstream origin/master
> +		# branch.ab +0 -0
> +		1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
> +		1 A. S... 000000 160000 160000 $ZERO_OID $HSUB sub1
> +		EOF
> +
>  		git status --porcelain=v2 --branch --untracked-files=all >actual &&
>  		test_cmp expect actual
>  	)
> @@ -582,6 +607,33 @@ test_expect_success 'staged and untracked changes in added submodule (AM S.MU)'
>  		1 AM S.MU 000000 160000 160000 $ZERO_OID $HSUB sub1
>  		EOF
>  
> +		git status --porcelain=v2 --branch --untracked-files=all --ignore-submodules=none >actual &&
> +		test_cmp expect actual
> +	)
> +'
> +
> +test_expect_success 'staged and untracked changes in added submodule (AM S.M.) (untracked ignored)' '
> +	(	cd super_repo &&
> +		(	cd sub1 &&
> +			## stage new changes in tracked file.
> +			git add file_in_sub &&
> +			## create new untracked file.
> +			echo "yyyy" >>another_file_in_sub
> +		) &&
> +
> +		HMOD=$(git hash-object -t blob -- .gitmodules) &&
> +		HSUP=$(git rev-parse HEAD) &&
> +		HSUB=$HSUP &&
> +
> +		cat >expect <<-EOF &&
> +		# branch.oid $HSUP
> +		# branch.head master
> +		# branch.upstream origin/master
> +		# branch.ab +0 -0
> +		1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
> +		1 AM S.M. 000000 160000 160000 $ZERO_OID $HSUB sub1
> +		EOF
> +
>  		git status --porcelain=v2 --branch --untracked-files=all >actual &&
>  		test_cmp expect actual
>  	)
> diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh
> index 3fcb44767f..72da00a962 100755
> --- a/t/t7506-status-submodule.sh
> +++ b/t/t7506-status-submodule.sh
> @@ -94,36 +94,60 @@ test_expect_success 'status with added file in submodule (short)' '
>  test_expect_success 'status with untracked file in submodule' '
>  	(cd sub && git reset --hard) &&
>  	echo "content" >sub/new-file &&
> -	git status >output &&
> +	git status --ignore-submodules=none >output &&
>  	test_i18ngrep "modified:   sub (untracked content)" output
>  '
>  
> +test_expect_success 'status with untracked file in submodule (untracked ignored)' '
> +	(cd sub && git reset --hard) &&
> +	echo "content" >sub/new-file &&
> +	git status >output &&
> +	test_i18ngrep "^nothing to commit" output
> +'
> +
>  test_expect_success 'status -uno with untracked file in submodule' '
>  	git status -uno >output &&
>  	test_i18ngrep "^nothing to commit" output
>  '
>  
>  test_expect_success 'status with untracked file in submodule (porcelain)' '
> -	git status --porcelain >output &&
> +	git status --porcelain --ignore-submodules=none >output &&
>  	diff output - <<-\EOF
>  	 M sub
>  	EOF
>  '
>  
> +test_expect_success 'status with untracked file in submodule (porcelain) (untracked ignored)' '
> +	git status --porcelain >output &&
> +	test_must_be_empty output
> +'
> +
>  test_expect_success 'status with untracked file in submodule (short)' '
> -	git status --short >output &&
> +	git status --short --ignore-submodules=none >output &&
>  	diff output - <<-\EOF
>  	 ? sub
>  	EOF
>  '
>  
> +test_expect_success 'status with untracked file in submodule (short) (untracked ignored)' '
> +	git status --short >output &&
> +	test_must_be_empty output
> +'
> +
>  test_expect_success 'status with added and untracked file in submodule' '
>  	(cd sub && git reset --hard && echo >foo && git add foo) &&
>  	echo "content" >sub/new-file &&
> -	git status >output &&
> +	git status --ignore-submodules=none >output &&
>  	test_i18ngrep "modified:   sub (modified content, untracked content)" output
>  '
>  
> +test_expect_success 'status with added and untracked file in submodule (untracked ignored)' '
> +	(cd sub && git reset --hard && echo >foo && git add foo) &&
> +	echo "content" >sub/new-file &&
> +	git status >output &&
> +	test_i18ngrep "modified:   sub (modified content)" output
> +'
> +
>  test_expect_success 'status with added and untracked file in submodule (porcelain)' '
>  	(cd sub && git reset --hard && echo >foo && git add foo) &&
>  	echo "content" >sub/new-file &&
> @@ -168,10 +192,17 @@ test_expect_success 'status with added file in modified submodule (porcelain)' '
>  test_expect_success 'status with untracked file in modified submodule' '
>  	(cd sub && git reset --hard) &&
>  	echo "content" >sub/new-file &&
> -	git status >output &&
> +	git status --ignore-submodules=none >output &&
>  	test_i18ngrep "modified:   sub (new commits, untracked content)" output
>  '
>  
> +test_expect_success 'status with untracked file in modified submodule (untracked ignored)' '
> +	(cd sub && git reset --hard) &&
> +	echo "content" >sub/new-file &&
> +	git status >output &&
> +	test_i18ngrep "modified:   sub (new commits)" output
> +'
> +
>  test_expect_success 'status with untracked file in modified submodule (porcelain)' '
>  	git status --porcelain >output &&
>  	diff output - <<-\EOF
> @@ -182,10 +213,17 @@ test_expect_success 'status with untracked file in modified submodule (porcelain
>  test_expect_success 'status with added and untracked file in modified submodule' '
>  	(cd sub && git reset --hard && echo >foo && git add foo) &&
>  	echo "content" >sub/new-file &&
> -	git status >output &&
> +	git status --ignore-submodules=none >output &&
>  	test_i18ngrep "modified:   sub (new commits, modified content, untracked content)" output
>  '
>  
> +test_expect_success 'status with added and untracked file in modified submodule (untracked ignored)' '
> +	(cd sub && git reset --hard && echo >foo && git add foo) &&
> +	echo "content" >sub/new-file &&
> +	git status >output &&
> +	test_i18ngrep "modified:   sub (new commits, modified content)" output
> +'
> +
>  test_expect_success 'status with added and untracked file in modified submodule (porcelain)' '
>  	(cd sub && git reset --hard && echo >foo && git add foo) &&
>  	echo "content" >sub/new-file &&
> @@ -349,7 +387,7 @@ test_expect_success 'setup superproject with untracked file in nested submodule'
>  '
>  
>  test_expect_success 'status with untracked file in nested submodule (porcelain)' '
> -	git -C super status --porcelain >output &&
> +	git -C super status --porcelain --ignore-submodules=none >output &&
>  	diff output - <<-\EOF
>  	 M sub1
>  	 M sub2
> @@ -357,8 +395,13 @@ test_expect_success 'status with untracked file in nested submodule (porcelain)'
>  	EOF
>  '
>  
> +test_expect_success 'status with untracked file in nested submodule (porcelain) (untracked ignored)' '
> +	git -C super status --porcelain >output &&
> +	test_must_be_empty output
> +'
> +
>  test_expect_success 'status with untracked file in nested submodule (porcelain=2)' '
> -	git -C super status --porcelain=2 >output &&
> +	git -C super status --porcelain=2 --ignore-submodules=none >output &&
>  	sanitize_output output &&
>  	diff output - <<-\EOF
>  	1 .M S..U 160000 160000 160000 HASH HASH sub1
> @@ -367,8 +410,13 @@ test_expect_success 'status with untracked file in nested submodule (porcelain=2
>  	EOF
>  '
>  
> +test_expect_success 'status with untracked file in nested submodule (porcelain=2) (untracked ignored)' '
> +	git -C super status --porcelain=2 >output &&
> +	test_must_be_empty output
> +'
> +
>  test_expect_success 'status with untracked file in nested submodule (short)' '
> -	git -C super status --short >output &&
> +	git -C super status --short --ignore-submodules=none >output &&
>  	diff output - <<-\EOF
>  	 ? sub1
>  	 ? sub2
> @@ -376,13 +424,18 @@ test_expect_success 'status with untracked file in nested submodule (short)' '
>  	EOF
>  '
>  
> +test_expect_success 'status with untracked file in nested submodule (short) (untracked ignored)' '
> +	git -C super status --short >output &&
> +	test_must_be_empty output
> +'
> +
>  test_expect_success 'setup superproject with modified file in nested submodule' '
>  	git -C super/sub1/sub2 add file &&
>  	git -C super/sub2 add file
>  '
>  
>  test_expect_success 'status with added file in nested submodule (porcelain)' '
> -	git -C super status --porcelain >output &&
> +	git -C super status --porcelain --ignore-submodules=none >output &&
>  	diff output - <<-\EOF
>  	 M sub1
>  	 M sub2
> @@ -390,8 +443,16 @@ test_expect_success 'status with added file in nested submodule (porcelain)' '
>  	EOF
>  '
>  
> +test_expect_success 'status with added file in nested submodule (porcelain) (untracked ignored)' '
> +	git -C super status --porcelain >output &&
> +	diff output - <<-\EOF
> +	 M sub1
> +	 M sub2
> +	EOF
> +'
> +
>  test_expect_success 'status with added file in nested submodule (porcelain=2)' '
> -	git -C super status --porcelain=2 >output &&
> +	git -C super status --porcelain=2 --ignore-submodules=none >output &&
>  	sanitize_output output &&
>  	diff output - <<-\EOF
>  	1 .M S.M. 160000 160000 160000 HASH HASH sub1
> @@ -400,8 +461,17 @@ test_expect_success 'status with added file in nested submodule (porcelain=2)' '
>  	EOF
>  '
>  
> +test_expect_success 'status with added file in nested submodule (porcelain=2) (untracked ignored)' '
> +	git -C super status --porcelain=2 >output &&
> +	sanitize_output output &&
> +	diff output - <<-\EOF
> +	1 .M S.M. 160000 160000 160000 HASH HASH sub1
> +	1 .M S.M. 160000 160000 160000 HASH HASH sub2
> +	EOF
> +'
> +
>  test_expect_success 'status with added file in nested submodule (short)' '
> -	git -C super status --short >output &&
> +	git -C super status --short --ignore-submodules=none >output &&
>  	diff output - <<-\EOF
>  	 m sub1
>  	 m sub2
> @@ -409,4 +479,12 @@ test_expect_success 'status with added file in nested submodule (short)' '
>  	EOF
>  '
>  
> +test_expect_success 'status with added file in nested submodule (short) (untracked ignored)' '
> +	git -C super status --short >output &&
> +	diff output - <<-\EOF
> +	 m sub1
> +	 m sub2
> +	EOF
> +'
> +
>  test_done
> -- 
> 2.21.1 (Apple Git-122.3)
>
Sangeeta Nov. 9, 2020, 3:19 p.m. UTC | #5
Hey Danh,


> > diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
> > index ca04fac417..9104d1946d 100755
> > --- a/t/t3701-add-interactive.sh
> > +++ b/t/t3701-add-interactive.sh
> > @@ -765,6 +765,11 @@ test_expect_success 'setup different kinds of dirty submodules' '
> >       cat >expected <<-\EOF &&
> >       dirty-both-ways
> >       dirty-head
> > +     EOF
> > +     git -C for-submodules diff-files --name-only --ignore-submodules=none >actual &&
> > +     cat >expected <<-\EOF &&
> > +     dirty-both-ways
> > +     dirty-head
>
> This will throw-away above change to "expected", I think this is not
> what you expected to write!

I am sorry I couldn't understand what you mean by that. I think that
is what I expected to write. I want those changes to be in "expected".

Thanks,
Sangeeta
Junio C Hamano Nov. 9, 2020, 5:01 p.m. UTC | #6
Sangeeta <sangunb09@gmail.com> writes:

>> > diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
>> > index ca04fac417..9104d1946d 100755
>> > --- a/t/t3701-add-interactive.sh
>> > +++ b/t/t3701-add-interactive.sh
>> > @@ -765,6 +765,11 @@ test_expect_success 'setup different kinds of dirty submodules' '
>> >       cat >expected <<-\EOF &&
>> >       dirty-both-ways
>> >       dirty-head
>> > +     EOF
>> > +     git -C for-submodules diff-files --name-only --ignore-submodules=none >actual &&
>> > +     cat >expected <<-\EOF &&
>> > +     dirty-both-ways
>> > +     dirty-head
>>
>> This will throw-away above change to "expected", I think this is not
>> what you expected to write!
>
> I am sorry I couldn't understand what you mean by that. I think that
> is what I expected to write. I want those changes to be in "expected".

Looking at the above quoted part again...

	cat >expected <<-\EOF &&
		... content 1 ...
	EOF
        git ... >actual &&
	cat >expected <<-\EOF &&
		... content 2 ...
	EOF

I think Đoàn Trần Công Danh wants to say is that expected originally
has content 1, and that is discarded because you overwrite the same
file with content 2.  So either

 - if content1 and content2 are identical, perhaps you do not have
   to write content2 into expected at all, or

 - if content1 and content2 are different, perhaps you forgot to
   consume content1 before overwriting it.

THe latter is quite plausible, as the original test without your
addition must be consuming content1 after the part you added.
Junio C Hamano Dec. 8, 2020, 9:02 p.m. UTC | #7
Sangeeta <sangunb09@gmail.com> writes:

> Hey,
>
> I worked on passing --ignore-submodules=none as the default behavior
> of git status so that the user doesn't end up deleting a submodule
> that has uncommitted (untracked) files.
>
> The following changes make git status pass the ignoreSubmodules none
> argument as default.
>
> @@ -4587,7 +4587,7 @@ void repo_diff_setup(struct repository *r,
> struct diff_options *options)
>         options->orderfile = diff_order_file_cfg;
>
>         if (!options->flags.ignore_submodule_set)
> -               handle_ignore_submodules_arg(options, "untracked");
> +               options->flags.ignore_untracked_in_submodules = 1;
>
>         if (diff_no_prefix) {
>                 options->a_prefix = options->b_prefix = "";
>
>
> @@ -607,6 +607,9 @@ static void
> wt_status_collect_changes_worktree(struct wt_status *s)
>                 rev.diffopt.flags.override_submodule_config = 1;
>                 handle_ignore_submodules_arg(&rev.diffopt,
> s->ignore_submodule_arg);
>         }
> +       else if(!rev.diffopt.flags.ignore_submodule_set){
> +               handle_ignore_submodules_arg(&rev.diffopt, "none");
> +       }
>
> I have had to set the flag manually in diff.c because when we call
> handle_ignore_submodules_arg() with "untracked" arg,
> options->flags.ignore_submodule_set is set to 1 and therefore when we
> check for it in wt-status.c it appears that user has already set some
> config and therefore we shouldn't add "none" as ignoreSubmodules arg.
>
> Another way to do that is to have one more flag in diff_options that
> can let us know whether options->flags.ignore_submodule_set was set by
> the user or by diff passing untracked as the default argument.
>
> Can someone please help me with what might be the right way to proceed?

Hmph, neither sounds "right"---having to circumvent the assignment
to _set flag made in the handle_ helper by either manually setting
the underlying flag, or by introducing another flag that stops from
the _set flag getting updated, sounds like working around a flaw of
the approach to use _set flag and set it in the handle_ helper in
the first place...
diff mbox series

Patch

diff --git a/diff.c b/diff.c
index 2bb2f8f57e..5d69c2bb1c 100644
--- a/diff.c
+++ b/diff.c
@@ -4585,6 +4585,9 @@  void repo_diff_setup(struct repository *r, struct diff_options *options)
 		DIFF_XDL_SET(options, INDENT_HEURISTIC);
 
 	options->orderfile = diff_order_file_cfg;
+	
+	if (!options->flags.ignore_submodule_set)
+		handle_ignore_submodules_arg(options, "untracked");
 
 	if (diff_no_prefix) {
 		options->a_prefix = options->b_prefix = "";
diff --git a/diff.h b/diff.h
index 11de52e9e9..1e18e6b1c3 100644
--- a/diff.h
+++ b/diff.h
@@ -178,6 +178,7 @@  struct diff_flags {
 	unsigned diff_from_contents;
 	unsigned dirty_submodules;
 	unsigned ignore_untracked_in_submodules;
+	unsigned ignore_submodule_set;
 	unsigned ignore_dirty_submodules;
 	unsigned override_submodule_config;
 	unsigned dirstat_by_line;
diff --git a/submodule.c b/submodule.c
index b3bb59f066..afeb754079 100644
--- a/submodule.c
+++ b/submodule.c
@@ -420,6 +420,7 @@  const char *submodule_strategy_to_string(const struct submodule_update_strategy
 void handle_ignore_submodules_arg(struct diff_options *diffopt,
 				  const char *arg)
 {
+	diffopt->flags.ignore_submodule_set = 1;
 	diffopt->flags.ignore_submodules = 0;
 	diffopt->flags.ignore_untracked_in_submodules = 0;
 	diffopt->flags.ignore_dirty_submodules = 0;
@@ -1678,6 +1679,8 @@  unsigned is_submodule_modified(const char *path, int ignore_untracked)
 	strvec_pushl(&cp.args, "status", "--porcelain=2", NULL);
 	if (ignore_untracked)
 		strvec_push(&cp.args, "-uno");
+	else
+		strvec_push(&cp.args, "--ignore-submodules=none");
 
 	prepare_submodule_repo_env(&cp.env_array);
 	cp.git_cmd = 1;
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index ca04fac417..9104d1946d 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -765,6 +765,11 @@  test_expect_success 'setup different kinds of dirty submodules' '
 	cat >expected <<-\EOF &&
 	dirty-both-ways
 	dirty-head
+	EOF
+	git -C for-submodules diff-files --name-only --ignore-submodules=none >actual &&
+	cat >expected <<-\EOF &&
+	dirty-both-ways
+	dirty-head
 	dirty-otherwise
 	EOF
 	test_cmp expected actual &&
diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh
index d7145ccca4..894a11b224 100755
--- a/t/t4027-diff-submodule.sh
+++ b/t/t4027-diff-submodule.sh
@@ -93,6 +93,14 @@  test_expect_success 'git diff HEAD with dirty submodule (untracked)' '
 	) &&
 	git diff HEAD >actual &&
 	sed -e "1,/^@@/d" actual >actual.body &&
+	expect_from_to >expect.body $subtip $subprev &&
+	test_cmp expect.body actual.body
+'
+
+test_expect_success 'git diff HEAD with dirty submodule (untracked) (none ignored)' '
+	test_config diff.ignoreSubmodules none &&
+	git diff HEAD >actual &&
+	sed -e "1,/^@@/d" actual >actual.body &&
 	expect_from_to >expect.body $subtip $subprev-dirty &&
 	test_cmp expect.body actual.body
 '
@@ -168,13 +176,13 @@  test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)'
 		git clean -qfdx &&
 		>cruft
 	) &&
-	git diff HEAD >actual &&
+	git diff --ignore-submodules=none HEAD >actual &&
 	sed -e "1,/^@@/d" actual >actual.body &&
 	expect_from_to >expect.body $subprev $subprev-dirty &&
 	test_cmp expect.body actual.body &&
 	git diff --ignore-submodules=all HEAD >actual2 &&
 	test_must_be_empty actual2 &&
-	git diff --ignore-submodules=untracked HEAD >actual3 &&
+	git diff HEAD >actual3 &&
 	test_must_be_empty actual3 &&
 	git diff --ignore-submodules=dirty HEAD >actual4 &&
 	test_must_be_empty actual4
diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh
index f852136585..bb368b685d 100755
--- a/t/t4041-diff-submodule-option.sh
+++ b/t/t4041-diff-submodule-option.sh
@@ -262,7 +262,7 @@  test_expect_success 'submodule is up to date' '
 
 test_expect_success 'submodule contains untracked content' '
 	echo new > sm1/new-file &&
-	git diff-index -p --submodule=log HEAD >actual &&
+	git diff-index -p --submodule=log HEAD --ignore-submodules=none >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 contains untracked content
 	EOF
@@ -270,7 +270,7 @@  test_expect_success 'submodule contains untracked content' '
 '
 
 test_expect_success 'submodule contains untracked content (untracked ignored)' '
-	git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
+	git diff-index -p --submodule=log HEAD >actual &&
 	test_must_be_empty actual
 '
 
@@ -286,7 +286,7 @@  test_expect_success 'submodule contains untracked content (all ignored)' '
 
 test_expect_success 'submodule contains untracked and modified content' '
 	echo new > sm1/foo6 &&
-	git diff-index -p --submodule=log HEAD >actual &&
+	git diff-index -p --submodule=log HEAD --ignore-submodules=none >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 contains untracked content
 	Submodule sm1 contains modified content
@@ -296,7 +296,7 @@  test_expect_success 'submodule contains untracked and modified content' '
 
 test_expect_success 'submodule contains untracked and modified content (untracked ignored)' '
 	echo new > sm1/foo6 &&
-	git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
+	git diff-index -p --submodule=log HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 contains modified content
 	EOF
@@ -337,7 +337,7 @@  test_expect_success 'submodule is modified' '
 
 test_expect_success 'modified submodule contains untracked content' '
 	echo new > sm1/new-file &&
-	git diff-index -p --submodule=log HEAD >actual &&
+	git diff-index -p  --ignore-submodules=none --submodule=log HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 contains untracked content
 	Submodule sm1 $head6..$head8:
@@ -347,7 +347,7 @@  test_expect_success 'modified submodule contains untracked content' '
 '
 
 test_expect_success 'modified submodule contains untracked content (untracked ignored)' '
-	git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
+	git diff-index -p --submodule=log HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 $head6..$head8:
 	  > change
@@ -371,7 +371,7 @@  test_expect_success 'modified submodule contains untracked content (all ignored)
 
 test_expect_success 'modified submodule contains untracked and modified content' '
 	echo modification >> sm1/foo6 &&
-	git diff-index -p --submodule=log HEAD >actual &&
+	git diff-index -p --ignore-submodules=none --submodule=log HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 contains untracked content
 	Submodule sm1 contains modified content
@@ -383,7 +383,7 @@  test_expect_success 'modified submodule contains untracked and modified content'
 
 test_expect_success 'modified submodule contains untracked and modified content (untracked ignored)' '
 	echo modification >> sm1/foo6 &&
-	git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
+	git diff-index -p --submodule=log HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 contains modified content
 	Submodule sm1 $head6..$head8:
diff --git a/t/t4060-diff-submodule-option-diff-format.sh b/t/t4060-diff-submodule-option-diff-format.sh
index fc8229c726..dc7b242697 100755
--- a/t/t4060-diff-submodule-option-diff-format.sh
+++ b/t/t4060-diff-submodule-option-diff-format.sh
@@ -409,7 +409,7 @@  test_expect_success 'submodule is up to date' '
 
 test_expect_success 'submodule contains untracked content' '
 	echo new > sm1/new-file &&
-	git diff-index -p --submodule=diff HEAD >actual &&
+	git diff-index -p --ignore-submodules=none --submodule=diff HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 contains untracked content
 	EOF
@@ -417,7 +417,7 @@  test_expect_success 'submodule contains untracked content' '
 '
 
 test_expect_success 'submodule contains untracked content (untracked ignored)' '
-	git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
+	git diff-index -p --submodule=diff HEAD >actual &&
 	test_must_be_empty actual
 '
 
@@ -433,7 +433,7 @@  test_expect_success 'submodule contains untracked content (all ignored)' '
 
 test_expect_success 'submodule contains untracked and modified content' '
 	echo new > sm1/foo6 &&
-	git diff-index -p --submodule=diff HEAD >actual &&
+	git diff-index -p --ignore-submodules=none --submodule=diff HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 contains untracked content
 	Submodule sm1 contains modified content
@@ -451,7 +451,7 @@  test_expect_success 'submodule contains untracked and modified content' '
 # NOT OK
 test_expect_success 'submodule contains untracked and modified content (untracked ignored)' '
 	echo new > sm1/foo6 &&
-	git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
+	git diff-index -p --submodule=diff HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 contains modified content
 	diff --git a/sm1/foo6 b/sm1/foo6
@@ -512,7 +512,7 @@  test_expect_success 'submodule is modified' '
 
 test_expect_success 'modified submodule contains untracked content' '
 	echo new > sm1/new-file &&
-	git diff-index -p --submodule=diff HEAD >actual &&
+	git diff-index -p --ignore-submodules=none --submodule=diff HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 contains untracked content
 	Submodule sm1 $head7..$head8:
@@ -528,7 +528,7 @@  test_expect_success 'modified submodule contains untracked content' '
 '
 
 test_expect_success 'modified submodule contains untracked content (untracked ignored)' '
-	git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
+	git diff-index -p --submodule=diff HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 $head7..$head8:
 	diff --git a/sm1/foo6 b/sm1/foo6
@@ -564,7 +564,7 @@  test_expect_success 'modified submodule contains untracked content (all ignored)
 
 test_expect_success 'modified submodule contains untracked and modified content' '
 	echo modification >> sm1/foo6 &&
-	git diff-index -p --submodule=diff HEAD >actual &&
+	git diff-index -p --ignore-submodules=none --submodule=diff HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 contains untracked content
 	Submodule sm1 contains modified content
@@ -583,7 +583,7 @@  test_expect_success 'modified submodule contains untracked and modified content'
 
 test_expect_success 'modified submodule contains untracked and modified content (untracked ignored)' '
 	echo modification >> sm1/foo6 &&
-	git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
+	git diff-index -p --submodule=diff HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 contains modified content
 	Submodule sm1 $head7..$head8:
diff --git a/t/t7064-wtstatus-pv2.sh b/t/t7064-wtstatus-pv2.sh
index 537787e598..78cd86be3a 100755
--- a/t/t7064-wtstatus-pv2.sh
+++ b/t/t7064-wtstatus-pv2.sh
@@ -503,6 +503,31 @@  test_expect_success 'untracked changes in added submodule (AM S..U)' '
 		1 AM S..U 000000 160000 160000 $ZERO_OID $HSUB sub1
 		EOF
 
+		git status --porcelain=v2 --branch --untracked-files=all --ignore-submodules=none >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'untracked changes in added submodule (A. S...) (untracked ignored)' '
+	(	cd super_repo &&
+		## create untracked file in the submodule.
+		(	cd sub1 &&
+			echo "xxxx" >file_in_sub
+		) &&
+
+		HMOD=$(git hash-object -t blob -- .gitmodules) &&
+		HSUP=$(git rev-parse HEAD) &&
+		HSUB=$HSUP &&
+
+		cat >expect <<-EOF &&
+		# branch.oid $HSUP
+		# branch.head master
+		# branch.upstream origin/master
+		# branch.ab +0 -0
+		1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
+		1 A. S... 000000 160000 160000 $ZERO_OID $HSUB sub1
+		EOF
+
 		git status --porcelain=v2 --branch --untracked-files=all >actual &&
 		test_cmp expect actual
 	)
@@ -582,6 +607,33 @@  test_expect_success 'staged and untracked changes in added submodule (AM S.MU)'
 		1 AM S.MU 000000 160000 160000 $ZERO_OID $HSUB sub1
 		EOF
 
+		git status --porcelain=v2 --branch --untracked-files=all --ignore-submodules=none >actual &&
+		test_cmp expect actual
+	)
+'
+
+test_expect_success 'staged and untracked changes in added submodule (AM S.M.) (untracked ignored)' '
+	(	cd super_repo &&
+		(	cd sub1 &&
+			## stage new changes in tracked file.
+			git add file_in_sub &&
+			## create new untracked file.
+			echo "yyyy" >>another_file_in_sub
+		) &&
+
+		HMOD=$(git hash-object -t blob -- .gitmodules) &&
+		HSUP=$(git rev-parse HEAD) &&
+		HSUB=$HSUP &&
+
+		cat >expect <<-EOF &&
+		# branch.oid $HSUP
+		# branch.head master
+		# branch.upstream origin/master
+		# branch.ab +0 -0
+		1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
+		1 AM S.M. 000000 160000 160000 $ZERO_OID $HSUB sub1
+		EOF
+
 		git status --porcelain=v2 --branch --untracked-files=all >actual &&
 		test_cmp expect actual
 	)
diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh
index 3fcb44767f..72da00a962 100755
--- a/t/t7506-status-submodule.sh
+++ b/t/t7506-status-submodule.sh
@@ -94,36 +94,60 @@  test_expect_success 'status with added file in submodule (short)' '
 test_expect_success 'status with untracked file in submodule' '
 	(cd sub && git reset --hard) &&
 	echo "content" >sub/new-file &&
-	git status >output &&
+	git status --ignore-submodules=none >output &&
 	test_i18ngrep "modified:   sub (untracked content)" output
 '
 
+test_expect_success 'status with untracked file in submodule (untracked ignored)' '
+	(cd sub && git reset --hard) &&
+	echo "content" >sub/new-file &&
+	git status >output &&
+	test_i18ngrep "^nothing to commit" output
+'
+
 test_expect_success 'status -uno with untracked file in submodule' '
 	git status -uno >output &&
 	test_i18ngrep "^nothing to commit" output
 '
 
 test_expect_success 'status with untracked file in submodule (porcelain)' '
-	git status --porcelain >output &&
+	git status --porcelain --ignore-submodules=none >output &&
 	diff output - <<-\EOF
 	 M sub
 	EOF
 '
 
+test_expect_success 'status with untracked file in submodule (porcelain) (untracked ignored)' '
+	git status --porcelain >output &&
+	test_must_be_empty output
+'
+
 test_expect_success 'status with untracked file in submodule (short)' '
-	git status --short >output &&
+	git status --short --ignore-submodules=none >output &&
 	diff output - <<-\EOF
 	 ? sub
 	EOF
 '
 
+test_expect_success 'status with untracked file in submodule (short) (untracked ignored)' '
+	git status --short >output &&
+	test_must_be_empty output
+'
+
 test_expect_success 'status with added and untracked file in submodule' '
 	(cd sub && git reset --hard && echo >foo && git add foo) &&
 	echo "content" >sub/new-file &&
-	git status >output &&
+	git status --ignore-submodules=none >output &&
 	test_i18ngrep "modified:   sub (modified content, untracked content)" output
 '
 
+test_expect_success 'status with added and untracked file in submodule (untracked ignored)' '
+	(cd sub && git reset --hard && echo >foo && git add foo) &&
+	echo "content" >sub/new-file &&
+	git status >output &&
+	test_i18ngrep "modified:   sub (modified content)" output
+'
+
 test_expect_success 'status with added and untracked file in submodule (porcelain)' '
 	(cd sub && git reset --hard && echo >foo && git add foo) &&
 	echo "content" >sub/new-file &&
@@ -168,10 +192,17 @@  test_expect_success 'status with added file in modified submodule (porcelain)' '
 test_expect_success 'status with untracked file in modified submodule' '
 	(cd sub && git reset --hard) &&
 	echo "content" >sub/new-file &&
-	git status >output &&
+	git status --ignore-submodules=none >output &&
 	test_i18ngrep "modified:   sub (new commits, untracked content)" output
 '
 
+test_expect_success 'status with untracked file in modified submodule (untracked ignored)' '
+	(cd sub && git reset --hard) &&
+	echo "content" >sub/new-file &&
+	git status >output &&
+	test_i18ngrep "modified:   sub (new commits)" output
+'
+
 test_expect_success 'status with untracked file in modified submodule (porcelain)' '
 	git status --porcelain >output &&
 	diff output - <<-\EOF
@@ -182,10 +213,17 @@  test_expect_success 'status with untracked file in modified submodule (porcelain
 test_expect_success 'status with added and untracked file in modified submodule' '
 	(cd sub && git reset --hard && echo >foo && git add foo) &&
 	echo "content" >sub/new-file &&
-	git status >output &&
+	git status --ignore-submodules=none >output &&
 	test_i18ngrep "modified:   sub (new commits, modified content, untracked content)" output
 '
 
+test_expect_success 'status with added and untracked file in modified submodule (untracked ignored)' '
+	(cd sub && git reset --hard && echo >foo && git add foo) &&
+	echo "content" >sub/new-file &&
+	git status >output &&
+	test_i18ngrep "modified:   sub (new commits, modified content)" output
+'
+
 test_expect_success 'status with added and untracked file in modified submodule (porcelain)' '
 	(cd sub && git reset --hard && echo >foo && git add foo) &&
 	echo "content" >sub/new-file &&
@@ -349,7 +387,7 @@  test_expect_success 'setup superproject with untracked file in nested submodule'
 '
 
 test_expect_success 'status with untracked file in nested submodule (porcelain)' '
-	git -C super status --porcelain >output &&
+	git -C super status --porcelain --ignore-submodules=none >output &&
 	diff output - <<-\EOF
 	 M sub1
 	 M sub2
@@ -357,8 +395,13 @@  test_expect_success 'status with untracked file in nested submodule (porcelain)'
 	EOF
 '
 
+test_expect_success 'status with untracked file in nested submodule (porcelain) (untracked ignored)' '
+	git -C super status --porcelain >output &&
+	test_must_be_empty output
+'
+
 test_expect_success 'status with untracked file in nested submodule (porcelain=2)' '
-	git -C super status --porcelain=2 >output &&
+	git -C super status --porcelain=2 --ignore-submodules=none >output &&
 	sanitize_output output &&
 	diff output - <<-\EOF
 	1 .M S..U 160000 160000 160000 HASH HASH sub1
@@ -367,8 +410,13 @@  test_expect_success 'status with untracked file in nested submodule (porcelain=2
 	EOF
 '
 
+test_expect_success 'status with untracked file in nested submodule (porcelain=2) (untracked ignored)' '
+	git -C super status --porcelain=2 >output &&
+	test_must_be_empty output
+'
+
 test_expect_success 'status with untracked file in nested submodule (short)' '
-	git -C super status --short >output &&
+	git -C super status --short --ignore-submodules=none >output &&
 	diff output - <<-\EOF
 	 ? sub1
 	 ? sub2
@@ -376,13 +424,18 @@  test_expect_success 'status with untracked file in nested submodule (short)' '
 	EOF
 '
 
+test_expect_success 'status with untracked file in nested submodule (short) (untracked ignored)' '
+	git -C super status --short >output &&
+	test_must_be_empty output
+'
+
 test_expect_success 'setup superproject with modified file in nested submodule' '
 	git -C super/sub1/sub2 add file &&
 	git -C super/sub2 add file
 '
 
 test_expect_success 'status with added file in nested submodule (porcelain)' '
-	git -C super status --porcelain >output &&
+	git -C super status --porcelain --ignore-submodules=none >output &&
 	diff output - <<-\EOF
 	 M sub1
 	 M sub2
@@ -390,8 +443,16 @@  test_expect_success 'status with added file in nested submodule (porcelain)' '
 	EOF
 '
 
+test_expect_success 'status with added file in nested submodule (porcelain) (untracked ignored)' '
+	git -C super status --porcelain >output &&
+	diff output - <<-\EOF
+	 M sub1
+	 M sub2
+	EOF
+'
+
 test_expect_success 'status with added file in nested submodule (porcelain=2)' '
-	git -C super status --porcelain=2 >output &&
+	git -C super status --porcelain=2 --ignore-submodules=none >output &&
 	sanitize_output output &&
 	diff output - <<-\EOF
 	1 .M S.M. 160000 160000 160000 HASH HASH sub1
@@ -400,8 +461,17 @@  test_expect_success 'status with added file in nested submodule (porcelain=2)' '
 	EOF
 '
 
+test_expect_success 'status with added file in nested submodule (porcelain=2) (untracked ignored)' '
+	git -C super status --porcelain=2 >output &&
+	sanitize_output output &&
+	diff output - <<-\EOF
+	1 .M S.M. 160000 160000 160000 HASH HASH sub1
+	1 .M S.M. 160000 160000 160000 HASH HASH sub2
+	EOF
+'
+
 test_expect_success 'status with added file in nested submodule (short)' '
-	git -C super status --short >output &&
+	git -C super status --short --ignore-submodules=none >output &&
 	diff output - <<-\EOF
 	 m sub1
 	 m sub2
@@ -409,4 +479,12 @@  test_expect_success 'status with added file in nested submodule (short)' '
 	EOF
 '
 
+test_expect_success 'status with added file in nested submodule (short) (untracked ignored)' '
+	git -C super status --short >output &&
+	diff output - <<-\EOF
+	 m sub1
+	 m sub2
+	EOF
+'
+
 test_done