diff: do not show submodule with untracked files as "-dirty"

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. And also make `--ignore-submodules=none` the default for `git status` so that the user doesn't end up deleting a submodule that has uncommitted (untracked) files. Signed-off-by: Sangeeta Jain <sangunb09@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Sangeeta Jain committed Nov 10, 2020 at 14:09 UTC 8ef93124645f89c45c9ec3edd3b268b38154061a
9 files changed +42 -19
Documentation/config/diff.txt
+2
@@ -85,6 +85,8 @@ diff.ignoreSubmodules::
85 and 'git status' when `status.submoduleSummary` is set unless it is
86 overridden by using the --ignore-submodules command-line option.
87 The 'git submodule' commands are not affected by this setting.
88 + By default this is set to untracked so that any untracked
89 + submodules are ignored.
90
91 diff.mnemonicPrefix::
92 If set, 'git diff' uses a prefix pair that is different from the
diff.c
+3
@@ -4586,6 +4586,9 @@ void repo_diff_setup(struct repository *r, struct diff_options *options)
4586
4587 options->orderfile = diff_order_file_cfg;
4588
4589 + if (!options->flags.ignore_submodule_set)
4590 + options->flags.ignore_untracked_in_submodules = 1;
4591 +
4592 if (diff_no_prefix) {
4593 options->a_prefix = options->b_prefix = "";
4594 } else if (!diff_mnemonic_prefix) {
diff.h
+1
@@ -178,6 +178,7 @@ struct diff_flags {
178 unsigned diff_from_contents;
179 unsigned dirty_submodules;
180 unsigned ignore_untracked_in_submodules;
181 + unsigned ignore_submodule_set;
182 unsigned ignore_dirty_submodules;
183 unsigned override_submodule_config;
184 unsigned dirstat_by_line;
submodule.c
+1
@@ -420,6 +420,7 @@ const char *submodule_strategy_to_string(const struct submodule_update_strategy
420 void handle_ignore_submodules_arg(struct diff_options *diffopt,
421 const char *arg)
422 {
423 + diffopt->flags.ignore_submodule_set = 1;
424 diffopt->flags.ignore_submodules = 0;
425 diffopt->flags.ignore_untracked_in_submodules = 0;
426 diffopt->flags.ignore_dirty_submodules = 0;
t/t3701-add-interactive.sh
+6
@@ -765,6 +765,12 @@ test_expect_success 'setup different kinds of dirty submodules' '
765 cat >expected <<-\EOF &&
766 dirty-both-ways
767 dirty-head
768 + EOF
769 + test_cmp expected actual &&
770 + git -C for-submodules diff-files --name-only --ignore-submodules=none >actual &&
771 + cat >expected <<-\EOF &&
772 + dirty-both-ways
773 + dirty-head
774 dirty-otherwise
775 EOF
776 test_cmp expected actual &&
t/t4027-diff-submodule.sh
+10 -2
@@ -93,6 +93,14 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked)' '
93 ) &&
94 git diff HEAD >actual &&
95 sed -e "1,/^@@/d" actual >actual.body &&
96 + expect_from_to >expect.body $subtip $subprev &&
97 + test_cmp expect.body actual.body
98 +'
99 +
100 +test_expect_success 'git diff HEAD with dirty submodule (untracked) (none ignored)' '
101 + test_config diff.ignoreSubmodules none &&
102 + git diff HEAD >actual &&
103 + sed -e "1,/^@@/d" actual >actual.body &&
104 expect_from_to >expect.body $subtip $subprev-dirty &&
105 test_cmp expect.body actual.body
106 '
@@ -168,13 +176,13 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)'
176 git clean -qfdx &&
177 >cruft
178 ) &&
171 - git diff HEAD >actual &&
179 + git diff --ignore-submodules=none HEAD >actual &&
180 sed -e "1,/^@@/d" actual >actual.body &&
181 expect_from_to >expect.body $subprev $subprev-dirty &&
182 test_cmp expect.body actual.body &&
183 git diff --ignore-submodules=all HEAD >actual2 &&
184 test_must_be_empty actual2 &&
177 - git diff --ignore-submodules=untracked HEAD >actual3 &&
185 + git diff HEAD >actual3 &&
186 test_must_be_empty actual3 &&
187 git diff --ignore-submodules=dirty HEAD >actual4 &&
188 test_must_be_empty actual4
t/t4041-diff-submodule-option.sh
+8 -8
@@ -262,7 +262,7 @@ test_expect_success 'submodule is up to date' '
262
263 test_expect_success 'submodule contains untracked content' '
264 echo new > sm1/new-file &&
265 - git diff-index -p --submodule=log HEAD >actual &&
265 + git diff-index -p --ignore-submodules=none --submodule=log HEAD >actual &&
266 cat >expected <<-EOF &&
267 Submodule sm1 contains untracked content
268 EOF
@@ -270,7 +270,7 @@ test_expect_success 'submodule contains untracked content' '
270 '
271
272 test_expect_success 'submodule contains untracked content (untracked ignored)' '
273 - git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
273 + git diff-index -p --submodule=log HEAD >actual &&
274 test_must_be_empty actual
275 '
276
@@ -286,7 +286,7 @@ test_expect_success 'submodule contains untracked content (all ignored)' '
286
287 test_expect_success 'submodule contains untracked and modified content' '
288 echo new > sm1/foo6 &&
289 - git diff-index -p --submodule=log HEAD >actual &&
289 + git diff-index -p --ignore-submodules=none --submodule=log HEAD >actual &&
290 cat >expected <<-EOF &&
291 Submodule sm1 contains untracked content
292 Submodule sm1 contains modified content
@@ -296,7 +296,7 @@ test_expect_success 'submodule contains untracked and modified content' '
296
297 test_expect_success 'submodule contains untracked and modified content (untracked ignored)' '
298 echo new > sm1/foo6 &&
299 - git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
299 + git diff-index -p --submodule=log HEAD >actual &&
300 cat >expected <<-EOF &&
301 Submodule sm1 contains modified content
302 EOF
@@ -337,7 +337,7 @@ test_expect_success 'submodule is modified' '
337
338 test_expect_success 'modified submodule contains untracked content' '
339 echo new > sm1/new-file &&
340 - git diff-index -p --submodule=log HEAD >actual &&
340 + git diff-index -p --ignore-submodules=none --submodule=log HEAD >actual &&
341 cat >expected <<-EOF &&
342 Submodule sm1 contains untracked content
343 Submodule sm1 $head6..$head8:
@@ -347,7 +347,7 @@ test_expect_success 'modified submodule contains untracked content' '
347 '
348
349 test_expect_success 'modified submodule contains untracked content (untracked ignored)' '
350 - git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
350 + git diff-index -p --submodule=log HEAD >actual &&
351 cat >expected <<-EOF &&
352 Submodule sm1 $head6..$head8:
353 > change
@@ -371,7 +371,7 @@ test_expect_success 'modified submodule contains untracked content (all ignored)
371
372 test_expect_success 'modified submodule contains untracked and modified content' '
373 echo modification >> sm1/foo6 &&
374 - git diff-index -p --submodule=log HEAD >actual &&
374 + git diff-index -p --ignore-submodules=none --submodule=log HEAD >actual &&
375 cat >expected <<-EOF &&
376 Submodule sm1 contains untracked content
377 Submodule sm1 contains modified content
@@ -383,7 +383,7 @@ test_expect_success 'modified submodule contains untracked and modified content'
383
384 test_expect_success 'modified submodule contains untracked and modified content (untracked ignored)' '
385 echo modification >> sm1/foo6 &&
386 - git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
386 + git diff-index -p --submodule=log HEAD >actual &&
387 cat >expected <<-EOF &&
388 Submodule sm1 contains modified content
389 Submodule sm1 $head6..$head8:
t/t4060-diff-submodule-option-diff-format.sh
+8 -8
@@ -409,7 +409,7 @@ test_expect_success 'submodule is up to date' '
409
410 test_expect_success 'submodule contains untracked content' '
411 echo new > sm1/new-file &&
412 - git diff-index -p --submodule=diff HEAD >actual &&
412 + git diff-index -p --ignore-submodules=none --submodule=diff HEAD >actual &&
413 cat >expected <<-EOF &&
414 Submodule sm1 contains untracked content
415 EOF
@@ -417,7 +417,7 @@ test_expect_success 'submodule contains untracked content' '
417 '
418
419 test_expect_success 'submodule contains untracked content (untracked ignored)' '
420 - git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
420 + git diff-index -p --submodule=diff HEAD >actual &&
421 test_must_be_empty actual
422 '
423
@@ -433,7 +433,7 @@ test_expect_success 'submodule contains untracked content (all ignored)' '
433
434 test_expect_success 'submodule contains untracked and modified content' '
435 echo new > sm1/foo6 &&
436 - git diff-index -p --submodule=diff HEAD >actual &&
436 + git diff-index -p --ignore-submodules=none --submodule=diff HEAD >actual &&
437 cat >expected <<-EOF &&
438 Submodule sm1 contains untracked content
439 Submodule sm1 contains modified content
@@ -451,7 +451,7 @@ test_expect_success 'submodule contains untracked and modified content' '
451 # NOT OK
452 test_expect_success 'submodule contains untracked and modified content (untracked ignored)' '
453 echo new > sm1/foo6 &&
454 - git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
454 + git diff-index -p --submodule=diff HEAD >actual &&
455 cat >expected <<-EOF &&
456 Submodule sm1 contains modified content
457 diff --git a/sm1/foo6 b/sm1/foo6
@@ -512,7 +512,7 @@ test_expect_success 'submodule is modified' '
512
513 test_expect_success 'modified submodule contains untracked content' '
514 echo new > sm1/new-file &&
515 - git diff-index -p --submodule=diff HEAD >actual &&
515 + git diff-index -p --ignore-submodules=none --submodule=diff HEAD >actual &&
516 cat >expected <<-EOF &&
517 Submodule sm1 contains untracked content
518 Submodule sm1 $head7..$head8:
@@ -528,7 +528,7 @@ test_expect_success 'modified submodule contains untracked content' '
528 '
529
530 test_expect_success 'modified submodule contains untracked content (untracked ignored)' '
531 - git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
531 + git diff-index -p --submodule=diff HEAD >actual &&
532 cat >expected <<-EOF &&
533 Submodule sm1 $head7..$head8:
534 diff --git a/sm1/foo6 b/sm1/foo6
@@ -564,7 +564,7 @@ test_expect_success 'modified submodule contains untracked content (all ignored)
564
565 test_expect_success 'modified submodule contains untracked and modified content' '
566 echo modification >> sm1/foo6 &&
567 - git diff-index -p --submodule=diff HEAD >actual &&
567 + git diff-index -p --ignore-submodules=none --submodule=diff HEAD >actual &&
568 cat >expected <<-EOF &&
569 Submodule sm1 contains untracked content
570 Submodule sm1 contains modified content
@@ -583,7 +583,7 @@ test_expect_success 'modified submodule contains untracked and modified content'
583
584 test_expect_success 'modified submodule contains untracked and modified content (untracked ignored)' '
585 echo modification >> sm1/foo6 &&
586 - git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
586 + git diff-index -p --submodule=diff HEAD >actual &&
587 cat >expected <<-EOF &&
588 Submodule sm1 contains modified content
589 Submodule sm1 $head7..$head8:
wt-status.c
+3 -1
@@ -606,7 +606,9 @@ static void wt_status_collect_changes_worktree(struct wt_status *s)
606 if (s->ignore_submodule_arg) {
607 rev.diffopt.flags.override_submodule_config = 1;
608 handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg);
609 - }
609 + } else if (!rev.diffopt.flags.ignore_submodule_set &&
610 + s->show_untracked_files != SHOW_NO_UNTRACKED_FILES)
611 + handle_ignore_submodules_arg(&rev.diffopt, "none");
612 rev.diffopt.format_callback = wt_status_collect_changed_cb;
613 rev.diffopt.format_callback_data = s;
614 rev.diffopt.detect_rename = s->detect_rename >= 0 ? s->detect_rename : rev.diffopt.detect_rename;