status/commit: show staged submodules regardless of ignore config

Currently setting submodule.<name>.ignore and/or diff.ignoreSubmodules to
"all" suppresses all output of submodule changes for the diff family,
status and commit. For status and commit this is really confusing, as it
even when the user chooses to record a new commit for an ignored submodule
by adding it manually this change won't show up under the to-be-committed
changes. To add insult to injury, a later "git commit" will error out with
"nothing to commit" when only ignored submodules are staged.

Fix that by making wt_status always print staged submodule changes, no
matter what ignore settings are configured. The only exception is when the
user explicitly uses the "--ignore-submodules=all" command line option, in
that case the submodule output is still suppressed. This also makes "git
commit" work again when only modifications of ignored submodules are
staged, as that command uses the "commitable" member of the wt_status
struct to determine if staged changes are present. But this only happens
when the commit command uses the wt_status* functions to produce status
output for human consumption (when forking an editor or with --dry-run),
in all other cases (e.g. when run in a script with '-m') another code path
is taken which uses index_differs_from() to determine if any changes are
staged which still ignores submodules according to their configuration.
This will be fixed in a follow-up commit.

Change t7508 to reflect this new behavior and add three new tests to show
that a single staged submodule configured to be ignored will be committed
when the status output is generated and won't be if not. Also update the
documentation of the ignore config options accordingly.

Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jens Lehmann 2014-04-05 18:59:03 +02:00 committed by Junio C Hamano
parent 5f95c9f850
commit 1d2f393ac9
4 changed files with 92 additions and 6 deletions

View File

@ -2227,7 +2227,9 @@ status.submodulesummary::
--summary-limit option of linkgit:git-submodule[1]). Please note --summary-limit option of linkgit:git-submodule[1]). Please note
that the summary output command will be suppressed for all that the summary output command will be suppressed for all
submodules when `diff.ignoreSubmodules` is set to 'all' or only submodules when `diff.ignoreSubmodules` is set to 'all' or only
for those submodules where `submodule.<name>.ignore=all`. To for those submodules where `submodule.<name>.ignore=all`. The only
exception to that rule is that status and commit will show staged
submodule changes. To
also view the summary for ignored submodules you can either use also view the summary for ignored submodules you can either use
the --ignore-submodules=dirty command line option or the 'git the --ignore-submodules=dirty command line option or the 'git
submodule summary' command, which shows a similar output but does submodule summary' command, which shows a similar output but does
@ -2258,7 +2260,9 @@ submodule.<name>.fetchRecurseSubmodules::
submodule.<name>.ignore:: submodule.<name>.ignore::
Defines under what circumstances "git status" and the diff family show Defines under what circumstances "git status" and the diff family show
a submodule as modified. When set to "all", it will never be considered a submodule as modified. When set to "all", it will never be considered
modified, "dirty" will ignore all changes to the submodules work tree and modified (but it will nonetheless show up in the output of status and
commit when it has been staged), "dirty" will ignore all changes
to the submodules work tree and
takes only differences between the HEAD of the submodule and the commit takes only differences between the HEAD of the submodule and the commit
recorded in the superproject into account. "untracked" will additionally recorded in the superproject into account. "untracked" will additionally
let submodules with modified tracked files in their work tree show up. let submodules with modified tracked files in their work tree show up.

View File

@ -67,7 +67,9 @@ submodule.<name>.fetchRecurseSubmodules::
submodule.<name>.ignore:: submodule.<name>.ignore::
Defines under what circumstances "git status" and the diff family show Defines under what circumstances "git status" and the diff family show
a submodule as modified. When set to "all", it will never be considered a submodule as modified. When set to "all", it will never be considered
modified, "dirty" will ignore all changes to the submodules work tree and modified (but will nonetheless show up in the output of status and
commit when it has been staged), "dirty" will ignore all changes
to the submodules work tree and
takes only differences between the HEAD of the submodule and the commit takes only differences between the HEAD of the submodule and the commit
recorded in the superproject into account. "untracked" will additionally recorded in the superproject into account. "untracked" will additionally
let submodules with modified tracked files in their work tree show up. let submodules with modified tracked files in their work tree show up.

View File

@ -1380,7 +1380,32 @@ EOF
test_i18ncmp expect output test_i18ncmp expect output
' '
test_expect_success '.gitmodules ignore=all suppresses submodule summary' ' test_expect_success '.gitmodules ignore=all suppresses unstaged submodule summary' '
cat > expect << EOF &&
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: sm
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: dir1/modified
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitmodules
dir1/untracked
dir2/modified
dir2/untracked
expect
output
untracked
EOF
git config --add -f .gitmodules submodule.subname.ignore all && git config --add -f .gitmodules submodule.subname.ignore all &&
git config --add -f .gitmodules submodule.subname.path sm && git config --add -f .gitmodules submodule.subname.path sm &&
git status > output && git status > output &&
@ -1388,7 +1413,7 @@ test_expect_success '.gitmodules ignore=all suppresses submodule summary' '
git config -f .gitmodules --remove-section submodule.subname git config -f .gitmodules --remove-section submodule.subname
' '
test_expect_success '.git/config ignore=all suppresses submodule summary' ' test_expect_success '.git/config ignore=all suppresses unstaged submodule summary' '
git config --add -f .gitmodules submodule.subname.ignore none && git config --add -f .gitmodules submodule.subname.ignore none &&
git config --add -f .gitmodules submodule.subname.path sm && git config --add -f .gitmodules submodule.subname.path sm &&
git config --add submodule.subname.ignore all && git config --add submodule.subname.ignore all &&
@ -1461,4 +1486,49 @@ test_expect_success 'Restore default test environment' '
git config --unset status.showUntrackedFiles git config --unset status.showUntrackedFiles
' '
test_expect_success 'git commit will commit a staged but ignored submodule' '
git config --add -f .gitmodules submodule.subname.ignore all &&
git config --add -f .gitmodules submodule.subname.path sm &&
git config --add submodule.subname.ignore all &&
git status -s --ignore-submodules=dirty >output &&
test_i18ngrep "^M. sm" output &&
GIT_EDITOR="echo hello >>\"\$1\"" &&
export GIT_EDITOR &&
git commit -uno &&
git status -s --ignore-submodules=dirty >output &&
test_i18ngrep ! "^M. sm" output
'
test_expect_success 'git commit --dry-run will show a staged but ignored submodule' '
git reset HEAD^ &&
git add sm &&
cat >expect << EOF &&
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: sm
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: dir1/modified
Untracked files not listed (use -u option to show untracked files)
EOF
git commit -uno --dry-run >output &&
test_i18ncmp expect output &&
git status -s --ignore-submodules=dirty >output &&
test_i18ngrep "^M. sm" output
'
test_expect_failure 'git commit -m will commit a staged but ignored submodule' '
git commit -uno -m message &&
git status -s --ignore-submodules=dirty >output &&
test_i18ngrep ! "^M. sm" output &&
git config --remove-section submodule.subname &&
git config -f .gitmodules --remove-section submodule.subname
'
test_done test_done

View File

@ -486,9 +486,19 @@ static void wt_status_collect_changes_index(struct wt_status *s)
opt.def = s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference; opt.def = s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference;
setup_revisions(0, NULL, &rev, &opt); setup_revisions(0, NULL, &rev, &opt);
if (s->ignore_submodule_arg) {
DIFF_OPT_SET(&rev.diffopt, OVERRIDE_SUBMODULE_CONFIG); DIFF_OPT_SET(&rev.diffopt, OVERRIDE_SUBMODULE_CONFIG);
if (s->ignore_submodule_arg) {
handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg); handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg);
} else {
/*
* Unless the user did explicitly request a submodule ignore
* mode by passing a command line option we do not ignore any
* changed submodule SHA-1s when comparing index and HEAD, no
* matter what is configured. Otherwise the user won't be
* shown any submodules she manually added (and which are
* staged to be committed), which would be really confusing.
*/
handle_ignore_submodules_arg(&rev.diffopt, "dirty");
} }
rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK; rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;