summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/git-clean.txt6
-rw-r--r--builtin/clean.c2
-rw-r--r--dir.c10
-rw-r--r--dir.h3
-rwxr-xr-xt/t7300-clean.sh10
5 files changed, 22 insertions, 9 deletions
diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index 3ab749b921..ba31d8d166 100644
--- a/Documentation/git-clean.txt
+++ b/Documentation/git-clean.txt
@@ -37,9 +37,9 @@ OPTIONS
--force::
If the Git configuration variable clean.requireForce is not set
to false, 'git clean' will refuse to delete files or directories
- unless given -f or -i. Git will refuse to delete directories
- with .git sub directory or file unless a second -f
- is given.
+ unless given -f or -i. Git will refuse to modify untracked
+ nested git repositories (directories with a .git subdirectory)
+ unless a second -f is given.
-i::
--interactive::
diff --git a/builtin/clean.c b/builtin/clean.c
index 68d70e41c0..3a7a63ae71 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -946,6 +946,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (force > 1)
rm_flags = 0;
+ else
+ dir.flags |= DIR_SKIP_NESTED_GIT;
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
diff --git a/dir.c b/dir.c
index 3b2fe1701c..7ff79170fc 100644
--- a/dir.c
+++ b/dir.c
@@ -1451,6 +1451,16 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
return path_none;
case index_nonexistent:
+ if (dir->flags & DIR_SKIP_NESTED_GIT) {
+ int nested_repo;
+ struct strbuf sb = STRBUF_INIT;
+ strbuf_addstr(&sb, dirname);
+ nested_repo = is_nonbare_repository_dir(&sb);
+ strbuf_release(&sb);
+ if (nested_repo)
+ return path_none;
+ }
+
if (dir->flags & DIR_SHOW_OTHER_DIRECTORIES)
break;
if (exclude &&
diff --git a/dir.h b/dir.h
index 46c238ab49..739aea7c96 100644
--- a/dir.h
+++ b/dir.h
@@ -156,7 +156,8 @@ struct dir_struct {
DIR_SHOW_IGNORED_TOO = 1<<5,
DIR_COLLECT_KILLED_ONLY = 1<<6,
DIR_KEEP_UNTRACKED_CONTENTS = 1<<7,
- DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8
+ DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8,
+ DIR_SKIP_NESTED_GIT = 1<<9
} flags;
struct dir_entry **entries;
struct dir_entry **ignored;
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 530dfdab34..6e6d24c1c3 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -549,7 +549,7 @@ test_expect_failure 'nested (non-empty) bare repositories should be cleaned even
test_path_is_missing strange_bare
'
-test_expect_success 'giving path in nested git work tree will remove it' '
+test_expect_success 'giving path in nested git work tree will NOT remove it' '
rm -fr repo &&
mkdir repo &&
(
@@ -561,7 +561,7 @@ test_expect_success 'giving path in nested git work tree will remove it' '
git clean -f -d repo/bar/baz &&
test_path_is_file repo/.git/HEAD &&
test_path_is_dir repo/bar/ &&
- test_path_is_missing repo/bar/baz
+ test_path_is_file repo/bar/baz/hello.world
'
test_expect_success 'giving path to nested .git will not remove it' '
@@ -579,7 +579,7 @@ test_expect_success 'giving path to nested .git will not remove it' '
test_path_is_dir untracked/
'
-test_expect_success 'giving path to nested .git/ will remove contents' '
+test_expect_success 'giving path to nested .git/ will NOT remove contents' '
rm -fr repo untracked &&
mkdir repo untracked &&
(
@@ -589,7 +589,7 @@ test_expect_success 'giving path to nested .git/ will remove contents' '
) &&
git clean -f -d repo/.git/ &&
test_path_is_dir repo/.git &&
- test_dir_is_empty repo/.git &&
+ test_path_is_file repo/.git/HEAD &&
test_path_is_dir untracked/
'
@@ -671,7 +671,7 @@ test_expect_success 'git clean -d skips untracked dirs containing ignored files'
test_path_is_missing foo/b/bb
'
-test_expect_failure 'git clean -d skips nested repo containing ignored files' '
+test_expect_success 'git clean -d skips nested repo containing ignored files' '
test_when_finished "rm -rf nested-repo-with-ignored-file" &&
git init nested-repo-with-ignored-file &&