Skip to content

Commit 46a958b

Browse files
jlehmanngitster
authored andcommitted
Add the option "--ignore-submodules" to "git status"
In some use cases it is not desirable that "git status" considers submodules that only contain untracked content as dirty. This may happen e.g. when the submodule is not under the developers control and not all build generated files have been added to .gitignore by the upstream developers. Using the "untracked" parameter for the "--ignore-submodules" option disables checking for untracked content and lets git diff report them as changed only when they have new commits or modified content. Sometimes it is not wanted to have submodules show up as changed when they just contain changes to their work tree (this was the behavior before 1.7.0). An example for that are scripts which just want to check for submodule commits while ignoring any changes to the work tree. Also users having large submodules known not to change might want to use this option, as the - sometimes substantial - time it takes to scan the submodule work tree(s) is saved when using the "dirty" parameter. And if you want to ignore any changes to submodules, you can now do that by using this option without parameters or with "all" (when the config option status.submodulesummary is set, using "all" will also suppress the output of the submodule summary). A new function handle_ignore_submodules_arg() is introduced to parse this option new to "git status" in a single location, as "git diff" already knew it. Signed-off-by: Jens Lehmann <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1807650 commit 46a958b

File tree

8 files changed

+174
-13
lines changed

8 files changed

+174
-13
lines changed

Documentation/git-status.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ See linkgit:git-config[1] for configuration variable
4949
used to change the default for when the option is not
5050
specified.
5151

52+
--ignore-submodules[=<when>]::
53+
Ignore changes to submodules when looking for changes. <when> can be
54+
either "untracked", "dirty" or "all", which is the default. When
55+
"untracked" is used submodules are not considered dirty when they only
56+
contain untracked content (but they are still scanned for modified
57+
content). Using "dirty" ignores all changes to the work tree of submodules,
58+
only changes to the commits stored in the superproject are shown (this was
59+
the behavior before 1.7.0). Using "all" hides all changes to submodules
60+
(and suppresses the output of submodule summaries when the config option
61+
`status.submodulesummary` is set).
62+
5263
-z::
5364
Terminate entries with NUL, instead of LF. This implies
5465
the `--porcelain` output format if no other format is given.

builtin/commit.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ static char *author_name, *author_email, *author_date;
6767
static int all, edit_flag, also, interactive, only, amend, signoff;
6868
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
6969
static int no_post_rewrite;
70-
static char *untracked_files_arg, *force_date;
70+
static char *untracked_files_arg, *force_date, *ignore_submodule_arg;
7171
/*
7272
* The default commit message cleanup mode will remove the lines
7373
* beginning with # (shell comments) and leading and trailing
@@ -1031,6 +1031,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)
10311031
"mode",
10321032
"show untracked files, optional modes: all, normal, no. (Default: all)",
10331033
PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
1034+
{ OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, "when",
1035+
"ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)",
1036+
PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
10341037
OPT_END(),
10351038
};
10361039

@@ -1052,6 +1055,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
10521055
refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, s.pathspec, NULL, NULL);
10531056
s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
10541057
s.in_merge = in_merge;
1058+
s.ignore_submodule_arg = ignore_submodule_arg;
10551059
wt_status_collect(&s);
10561060

10571061
if (s.relative_paths)
@@ -1070,6 +1074,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
10701074
break;
10711075
case STATUS_FORMAT_LONG:
10721076
s.verbose = verbose;
1077+
s.ignore_submodule_arg = ignore_submodule_arg;
10731078
wt_status_print(&s);
10741079
break;
10751080
}

diff.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2866,17 +2866,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
28662866
else if (!strcmp(arg, "--no-textconv"))
28672867
DIFF_OPT_CLR(options, ALLOW_TEXTCONV);
28682868
else if (!strcmp(arg, "--ignore-submodules"))
2869-
DIFF_OPT_SET(options, IGNORE_SUBMODULES);
2870-
else if (!prefixcmp(arg, "--ignore-submodules=")) {
2871-
if (!strcmp(arg + 20, "all"))
2872-
DIFF_OPT_SET(options, IGNORE_SUBMODULES);
2873-
else if (!strcmp(arg + 20, "untracked"))
2874-
DIFF_OPT_SET(options, IGNORE_UNTRACKED_IN_SUBMODULES);
2875-
else if (!strcmp(arg + 20, "dirty"))
2876-
DIFF_OPT_SET(options, IGNORE_DIRTY_SUBMODULES);
2877-
else
2878-
die("bad --ignore-submodules argument: %s", arg + 20);
2879-
} else if (!strcmp(arg, "--submodule"))
2869+
handle_ignore_submodules_arg(options, "all");
2870+
else if (!prefixcmp(arg, "--ignore-submodules="))
2871+
handle_ignore_submodules_arg(options, arg + 20);
2872+
else if (!strcmp(arg, "--submodule"))
28802873
DIFF_OPT_SET(options, SUBMODULE_LOG);
28812874
else if (!prefixcmp(arg, "--submodule=")) {
28822875
if (!strcmp(arg + 12, "log"))

submodule.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,19 @@ static int add_submodule_odb(const char *path)
4646
return ret;
4747
}
4848

49+
void handle_ignore_submodules_arg(struct diff_options *diffopt,
50+
const char *arg)
51+
{
52+
if (!strcmp(arg, "all"))
53+
DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES);
54+
else if (!strcmp(arg, "untracked"))
55+
DIFF_OPT_SET(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES);
56+
else if (!strcmp(arg, "dirty"))
57+
DIFF_OPT_SET(diffopt, IGNORE_DIRTY_SUBMODULES);
58+
else
59+
die("bad --ignore-submodules argument: %s", arg);
60+
}
61+
4962
void show_submodule_summary(FILE *f, const char *path,
5063
unsigned char one[20], unsigned char two[20],
5164
unsigned dirty_submodule,

submodule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#ifndef SUBMODULE_H
22
#define SUBMODULE_H
33

4+
struct diff_options;
5+
6+
void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
47
void show_submodule_summary(FILE *f, const char *path,
58
unsigned char one[20], unsigned char two[20],
69
unsigned dirty_submodule,

t/t7508-status.sh

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,4 +693,131 @@ test_expect_success 'commit --dry-run submodule summary (--amend)' '
693693
test_cmp expect output
694694
'
695695

696+
cat > expect << EOF
697+
# On branch master
698+
# Changed but not updated:
699+
# (use "git add <file>..." to update what will be committed)
700+
# (use "git checkout -- <file>..." to discard changes in working directory)
701+
#
702+
# modified: dir1/modified
703+
#
704+
# Untracked files:
705+
# (use "git add <file>..." to include in what will be committed)
706+
#
707+
# dir1/untracked
708+
# dir2/modified
709+
# dir2/untracked
710+
# expect
711+
# output
712+
# untracked
713+
no changes added to commit (use "git add" and/or "git commit -a")
714+
EOF
715+
716+
test_expect_success '--ignore-submodules=untracked suppresses submodules with untracked content' '
717+
echo modified > sm/untracked &&
718+
git status --ignore-submodules=untracked > output &&
719+
test_cmp expect output
720+
'
721+
722+
test_expect_success '--ignore-submodules=dirty suppresses submodules with untracked content' '
723+
git status --ignore-submodules=dirty > output &&
724+
test_cmp expect output
725+
'
726+
727+
test_expect_success '--ignore-submodules=dirty suppresses submodules with modified content' '
728+
echo modified > sm/foo &&
729+
git status --ignore-submodules=dirty > output &&
730+
test_cmp expect output
731+
'
732+
733+
cat > expect << EOF
734+
# On branch master
735+
# Changed but not updated:
736+
# (use "git add <file>..." to update what will be committed)
737+
# (use "git checkout -- <file>..." to discard changes in working directory)
738+
# (commit or discard the untracked or modified content in submodules)
739+
#
740+
# modified: dir1/modified
741+
# modified: sm (modified content)
742+
#
743+
# Untracked files:
744+
# (use "git add <file>..." to include in what will be committed)
745+
#
746+
# dir1/untracked
747+
# dir2/modified
748+
# dir2/untracked
749+
# expect
750+
# output
751+
# untracked
752+
no changes added to commit (use "git add" and/or "git commit -a")
753+
EOF
754+
755+
test_expect_success "--ignore-submodules=untracked doesn't suppress submodules with modified content" '
756+
git status --ignore-submodules=untracked > output &&
757+
test_cmp expect output
758+
'
759+
760+
head2=$(cd sm && git commit -q -m "2nd commit" foo && git rev-parse --short=7 --verify HEAD)
761+
762+
cat > expect << EOF
763+
# On branch master
764+
# Changed but not updated:
765+
# (use "git add <file>..." to update what will be committed)
766+
# (use "git checkout -- <file>..." to discard changes in working directory)
767+
#
768+
# modified: dir1/modified
769+
# modified: sm (new commits)
770+
#
771+
# Submodules changed but not updated:
772+
#
773+
# * sm $head...$head2 (1):
774+
# > 2nd commit
775+
#
776+
# Untracked files:
777+
# (use "git add <file>..." to include in what will be committed)
778+
#
779+
# dir1/untracked
780+
# dir2/modified
781+
# dir2/untracked
782+
# expect
783+
# output
784+
# untracked
785+
no changes added to commit (use "git add" and/or "git commit -a")
786+
EOF
787+
788+
test_expect_success "--ignore-submodules=untracked doesn't suppress submodule summary" '
789+
git status --ignore-submodules=untracked > output &&
790+
test_cmp expect output
791+
'
792+
793+
test_expect_success "--ignore-submodules=dirty doesn't suppress submodule summary" '
794+
git status --ignore-submodules=dirty > output &&
795+
test_cmp expect output
796+
'
797+
798+
cat > expect << EOF
799+
# On branch master
800+
# Changed but not updated:
801+
# (use "git add <file>..." to update what will be committed)
802+
# (use "git checkout -- <file>..." to discard changes in working directory)
803+
#
804+
# modified: dir1/modified
805+
#
806+
# Untracked files:
807+
# (use "git add <file>..." to include in what will be committed)
808+
#
809+
# dir1/untracked
810+
# dir2/modified
811+
# dir2/untracked
812+
# expect
813+
# output
814+
# untracked
815+
no changes added to commit (use "git add" and/or "git commit -a")
816+
EOF
817+
818+
test_expect_success "--ignore-submodules=all suppresses submodule summary" '
819+
git status --ignore-submodules=all > output &&
820+
test_cmp expect output
821+
'
822+
696823
test_done

wt-status.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "quote.h"
1010
#include "run-command.h"
1111
#include "remote.h"
12+
#include "submodule.h"
1213

1314
static char default_wt_status_colors[][COLOR_MAXLEN] = {
1415
GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
@@ -306,6 +307,8 @@ static void wt_status_collect_changes_worktree(struct wt_status *s)
306307
DIFF_OPT_SET(&rev.diffopt, DIRTY_SUBMODULES);
307308
if (!s->show_untracked_files)
308309
DIFF_OPT_SET(&rev.diffopt, IGNORE_UNTRACKED_IN_SUBMODULES);
310+
if (s->ignore_submodule_arg)
311+
handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg);
309312
rev.diffopt.format_callback = wt_status_collect_changed_cb;
310313
rev.diffopt.format_callback_data = s;
311314
rev.prune_data = s->pathspec;
@@ -322,6 +325,9 @@ static void wt_status_collect_changes_index(struct wt_status *s)
322325
opt.def = s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference;
323326
setup_revisions(0, NULL, &rev, &opt);
324327

328+
if (s->ignore_submodule_arg)
329+
handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg);
330+
325331
rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
326332
rev.diffopt.format_callback = wt_status_collect_updated_cb;
327333
rev.diffopt.format_callback_data = s;
@@ -618,7 +624,9 @@ void wt_status_print(struct wt_status *s)
618624
wt_status_print_updated(s);
619625
wt_status_print_unmerged(s);
620626
wt_status_print_changed(s);
621-
if (s->submodule_summary) {
627+
if (s->submodule_summary &&
628+
(!s->ignore_submodule_arg ||
629+
strcmp(s->ignore_submodule_arg, "all"))) {
622630
wt_status_print_submodule_summary(s, 0); /* staged */
623631
wt_status_print_submodule_summary(s, 1); /* unstaged */
624632
}

wt-status.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct wt_status {
4242
int relative_paths;
4343
int submodule_summary;
4444
enum untracked_status_type show_untracked_files;
45+
const char *ignore_submodule_arg;
4546
char color_palette[WT_STATUS_UNMERGED+1][COLOR_MAXLEN];
4647

4748
/* These are computed during processing of the individual sections */

0 commit comments

Comments
 (0)