
The -d flag pre-dated git-clean's ability to have paths specified. As
such, the default for git-clean was to only remove untracked files in
the current directory, and -d existed to allow it to recurse into
subdirectories.
The interaction of paths and the -d option appears to not have been
carefully considered, as evidenced by numerous bugs and a dearth of
tests covering such pairings in the testsuite. The definition turns out
to be important, so let's look at some of the various ways one could
interpret the -d option:
A) Without -d, only look in subdirectories which contain tracked
files under them; with -d, also look in subdirectories which
are untracked for files to clean.
B) Without specified paths from the user for us to delete, we need to
have some kind of default, so...without -d, only look in
subdirectories which contain tracked files under them; with -d,
also look in subdirectories which are untracked for files to clean.
The important distinction here is that choice B says that the presence
or absence of '-d' is irrelevant if paths are specified. The logic
behind option B is that if a user explicitly asked us to clean a
specified pathspec, then we should clean anything that matches that
pathspec. Some examples may clarify. Should
git clean -f untracked_dir/file
remove untracked_dir/file or not? It seems crazy not to, but a strict
reading of option A says it shouldn't be removed. How about
git clean -f untracked_dir/file1 tracked_dir/file2
or
git clean -f untracked_dir_1/file1 untracked_dir_2/file2
? Should it remove either or both of these files? Should it require
multiple runs to remove both the files listed? (If this sounds like a
crazy question to even ask, see the commit message of "t7300: Add some
testcases showing failure to clean specified pathspecs" added earlier in
this patch series.) What if -ffd were used instead of -f -- should that
allow these to be removed? Should it take multiple invocations with
-ffd? What if a glob (such as '*tracked*') were used instead of
spelling out the directory names? What if the filenames involved globs,
such as
git clean -f '*.o'
or
git clean -f '*/*.o'
?
The current documentation actually suggests a definition that is
slightly different than choice A, and the implementation prior to this
series provided something radically different than either choices A or
B. (The implementation, though, was clearly just buggy). There may be
other choices as well. However, for almost any given choice of
definition for -d that I can think of, some of the examples above will
appear buggy to the user. The only case that doesn't have negative
surprises is choice B: treat a user-specified path as a request to clean
all untracked files which match that path specification, including
recursing into any untracked directories.
Change the documentation and basic implementation to use this
definition.
There were two regression tests that indirectly depended on the current
implementation, but neither was about subdirectory handling. These two
tests were introduced in commit 5b7570cfb4
("git-clean: add tests for
relative path", 2008-03-07) which was solely created to add coverage for
the changes in commit fb328947c8e ("git-clean: correct printing relative
path", 2008-03-07). Both tests specified a directory that happened to
have an untracked subdirectory, but both were only checking that the
resulting printout of a file that was removed was shown with a relative
path. Update these tests appropriately.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
143 lines
4.2 KiB
Plaintext
143 lines
4.2 KiB
Plaintext
git-clean(1)
|
|
============
|
|
|
|
NAME
|
|
----
|
|
git-clean - Remove untracked files from the working tree
|
|
|
|
SYNOPSIS
|
|
--------
|
|
[verse]
|
|
'git clean' [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <path>...
|
|
|
|
DESCRIPTION
|
|
-----------
|
|
|
|
Cleans the working tree by recursively removing files that are not
|
|
under version control, starting from the current directory.
|
|
|
|
Normally, only files unknown to Git are removed, but if the `-x`
|
|
option is specified, ignored files are also removed. This can, for
|
|
example, be useful to remove all build products.
|
|
|
|
If any optional `<path>...` arguments are given, only those paths
|
|
are affected.
|
|
|
|
OPTIONS
|
|
-------
|
|
-d::
|
|
Normally, when no <path> is specified, git clean will not
|
|
recurse into untracked directories to avoid removing too much.
|
|
Specify -d to have it recurse into such directories as well.
|
|
If any paths are specified, -d is irrelevant; all untracked
|
|
files matching the specified paths (with exceptions for nested
|
|
git directories mentioned under `--force`) will be removed.
|
|
|
|
-f::
|
|
--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.
|
|
|
|
-i::
|
|
--interactive::
|
|
Show what would be done and clean files interactively. See
|
|
``Interactive mode'' for details.
|
|
|
|
-n::
|
|
--dry-run::
|
|
Don't actually remove anything, just show what would be done.
|
|
|
|
-q::
|
|
--quiet::
|
|
Be quiet, only report errors, but not the files that are
|
|
successfully removed.
|
|
|
|
-e <pattern>::
|
|
--exclude=<pattern>::
|
|
Use the given exclude pattern in addition to the standard ignore rules
|
|
(see linkgit:gitignore[5]).
|
|
|
|
-x::
|
|
Don't use the standard ignore rules (see linkgit:gitignore[5]), but
|
|
still use the ignore rules given with `-e` options from the command
|
|
line. This allows removing all untracked
|
|
files, including build products. This can be used (possibly in
|
|
conjunction with 'git reset') to create a pristine
|
|
working directory to test a clean build.
|
|
|
|
-X::
|
|
Remove only files ignored by Git. This may be useful to rebuild
|
|
everything from scratch, but keep manually created files.
|
|
|
|
Interactive mode
|
|
----------------
|
|
When the command enters the interactive mode, it shows the
|
|
files and directories to be cleaned, and goes into its
|
|
interactive command loop.
|
|
|
|
The command loop shows the list of subcommands available, and
|
|
gives a prompt "What now> ". In general, when the prompt ends
|
|
with a single '>', you can pick only one of the choices given
|
|
and type return, like this:
|
|
|
|
------------
|
|
*** Commands ***
|
|
1: clean 2: filter by pattern 3: select by numbers
|
|
4: ask each 5: quit 6: help
|
|
What now> 1
|
|
------------
|
|
|
|
You also could say `c` or `clean` above as long as the choice is unique.
|
|
|
|
The main command loop has 6 subcommands.
|
|
|
|
clean::
|
|
|
|
Start cleaning files and directories, and then quit.
|
|
|
|
filter by pattern::
|
|
|
|
This shows the files and directories to be deleted and issues an
|
|
"Input ignore patterns>>" prompt. You can input space-separated
|
|
patterns to exclude files and directories from deletion.
|
|
E.g. "*.c *.h" will excludes files end with ".c" and ".h" from
|
|
deletion. When you are satisfied with the filtered result, press
|
|
ENTER (empty) back to the main menu.
|
|
|
|
select by numbers::
|
|
|
|
This shows the files and directories to be deleted and issues an
|
|
"Select items to delete>>" prompt. When the prompt ends with double
|
|
'>>' like this, you can make more than one selection, concatenated
|
|
with whitespace or comma. Also you can say ranges. E.g. "2-5 7,9"
|
|
to choose 2,3,4,5,7,9 from the list. If the second number in a
|
|
range is omitted, all remaining items are selected. E.g. "7-" to
|
|
choose 7,8,9 from the list. You can say '*' to choose everything.
|
|
Also when you are satisfied with the filtered result, press ENTER
|
|
(empty) back to the main menu.
|
|
|
|
ask each::
|
|
|
|
This will start to clean, and you must confirm one by one in order
|
|
to delete items. Please note that this action is not as efficient
|
|
as the above two actions.
|
|
|
|
quit::
|
|
|
|
This lets you quit without do cleaning.
|
|
|
|
help::
|
|
|
|
Show brief usage of interactive git-clean.
|
|
|
|
SEE ALSO
|
|
--------
|
|
linkgit:gitignore[5]
|
|
|
|
GIT
|
|
---
|
|
Part of the linkgit:git[1] suite
|