2006-04-05 08:00:48 +02:00
|
|
|
git-clean(1)
|
|
|
|
============
|
|
|
|
|
|
|
|
NAME
|
|
|
|
----
|
|
|
|
git-clean - Remove untracked files from the working tree
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
--------
|
|
|
|
[verse]
|
2022-10-13 17:39:21 +02:00
|
|
|
'git clean' [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] [<pathspec>...]
|
2006-04-05 08:00:48 +02:00
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
-----------
|
2009-04-25 17:13:41 +02:00
|
|
|
|
2009-05-06 19:48:26 +02:00
|
|
|
Cleans the working tree by recursively removing files that are not
|
|
|
|
under version control, starting from the current directory.
|
2009-04-25 17:13:41 +02:00
|
|
|
|
2016-06-28 13:40:10 +02:00
|
|
|
Normally, only files unknown to Git are removed, but if the `-x`
|
2009-04-25 17:13:41 +02:00
|
|
|
option is specified, ignored files are also removed. This can, for
|
|
|
|
example, be useful to remove all build products.
|
|
|
|
|
2022-10-13 17:39:10 +02:00
|
|
|
If any optional `<pathspec>...` arguments are given, only those paths
|
|
|
|
that match the pathspec are affected.
|
2006-05-08 21:02:44 +02:00
|
|
|
|
2006-04-05 08:00:48 +02:00
|
|
|
OPTIONS
|
|
|
|
-------
|
|
|
|
-d::
|
2022-10-13 17:39:10 +02:00
|
|
|
Normally, when no <pathspec> is specified, git clean will not
|
clean: disambiguate the definition of -d
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 5b7570cfb41c ("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>
2019-09-17 18:35:01 +02:00
|
|
|
recurse into untracked directories to avoid removing too much.
|
|
|
|
Specify -d to have it recurse into such directories as well.
|
2022-10-13 17:39:10 +02:00
|
|
|
If a <pathspec> is specified, -d is irrelevant; all untracked
|
clean: disambiguate the definition of -d
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 5b7570cfb41c ("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>
2019-09-17 18:35:01 +02:00
|
|
|
files matching the specified paths (with exceptions for nested
|
|
|
|
git directories mentioned under `--force`) will be removed.
|
2006-04-05 08:00:48 +02:00
|
|
|
|
2007-04-24 02:18:16 +02:00
|
|
|
-f::
|
2009-08-29 11:05:00 +02:00
|
|
|
--force::
|
2013-01-21 20:17:53 +01:00
|
|
|
If the Git configuration variable clean.requireForce is not set
|
2015-02-26 14:16:49 +01:00
|
|
|
to false, 'git clean' will refuse to delete files or directories
|
clean: avoid removing untracked files in a nested git repository
Users expect files in a nested git repository to be left alone unless
sufficiently forced (with two -f's). Unfortunately, in certain
circumstances, git would delete both tracked (and possibly dirty) files
and untracked files within a nested repository. To explain how this
happens, let's contrast a couple cases. First, take the following
example setup (which assumes we are already within a git repo):
git init nested
cd nested
>tracked
git add tracked
git commit -m init
>untracked
cd ..
In this setup, everything works as expected; running 'git clean -fd'
will result in fill_directory() returning the following paths:
nested/
nested/tracked
nested/untracked
and then correct_untracked_entries() would notice this can be compressed
to
nested/
and then since "nested/" is a directory, we would call
remove_dirs("nested/", ...), which would
check is_nonbare_repository_dir() and then decide to skip it.
However, if someone also creates an ignored file:
>nested/ignored
then running 'git clean -fd' would result in fill_directory() returning
the same paths:
nested/
nested/tracked
nested/untracked
but correct_untracked_entries() will notice that we had ignored entries
under nested/ and thus simplify this list to
nested/tracked
nested/untracked
Since these are not directories, we do not call remove_dirs() which was
the only place that had the is_nonbare_repository_dir() safety check --
resulting in us deleting both the untracked file and the tracked (and
possibly dirty) file.
One possible fix for this issue would be walking the parent directories
of each path and checking if they represent nonbare repositories, but
that would be wasteful. Even if we added caching of some sort, it's
still a waste because we should have been able to check that "nested/"
represented a nonbare repository before even descending into it in the
first place. Add a DIR_SKIP_NESTED_GIT flag to dir_struct.flags and use
it to prevent fill_directory() and friends from descending into nested
git repos.
With this change, we also modify two regression tests added in commit
91479b9c72f1 ("t7300: add tests to document behavior of clean and nested
git", 2015-06-15). That commit, nor its series, nor the six previous
iterations of that series on the mailing list discussed why those tests
coded the expectation they did. In fact, it appears their purpose was
simply to test _existing_ behavior to make sure that the performance
changes didn't change the behavior. However, these two tests directly
contradicted the manpage's claims that two -f's were required to delete
files/directories under a nested git repository. While one could argue
that the user gave an explicit path which matched files/directories that
were within a nested repository, there's a slippery slope that becomes
very difficult for users to understand once you go down that route (e.g.
what if they specified "git clean -f -d '*.c'"?) It would also be hard
to explain what the exact behavior was; avoid such problems by making it
really simple.
Also, clean up some grammar errors describing this functionality in the
git-clean manpage.
Finally, there are still a couple bugs with -ffd not cleaning out enough
(e.g. missing the nested .git) and with -ffdX possibly cleaning out the
wrong files (paying attention to outer .gitignore instead of inner).
This patch does not address these cases at all (and does not change the
behavior relative to those flags), it only fixes the handling when given
a single -f. See
https://public-inbox.org/git/20190905212043.GC32087@szeder.dev/ for more
discussion of the -ffd[X?] bugs.
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-09-17 18:35:02 +02:00
|
|
|
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.
|
2013-06-25 17:53:48 +02:00
|
|
|
|
|
|
|
-i::
|
|
|
|
--interactive::
|
2013-06-25 17:53:55 +02:00
|
|
|
Show what would be done and clean files interactively. See
|
|
|
|
``Interactive mode'' for details.
|
2007-04-24 02:18:16 +02:00
|
|
|
|
2006-04-05 08:00:48 +02:00
|
|
|
-n::
|
2008-06-08 03:36:10 +02:00
|
|
|
--dry-run::
|
2006-04-05 08:00:48 +02:00
|
|
|
Don't actually remove anything, just show what would be done.
|
|
|
|
|
|
|
|
-q::
|
2008-06-08 03:36:10 +02:00
|
|
|
--quiet::
|
2006-04-05 08:00:48 +02:00
|
|
|
Be quiet, only report errors, but not the files that are
|
|
|
|
successfully removed.
|
|
|
|
|
2010-07-20 21:35:56 +02:00
|
|
|
-e <pattern>::
|
|
|
|
--exclude=<pattern>::
|
2019-03-07 09:25:28 +01:00
|
|
|
Use the given exclude pattern in addition to the standard ignore rules
|
|
|
|
(see linkgit:gitignore[5]).
|
2010-07-20 21:35:56 +02:00
|
|
|
|
2006-04-05 08:00:48 +02:00
|
|
|
-x::
|
2019-03-07 09:25:28 +01:00
|
|
|
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
|
2006-04-05 08:00:48 +02:00
|
|
|
files, including build products. This can be used (possibly in
|
2019-04-25 11:45:58 +02:00
|
|
|
conjunction with 'git restore' or 'git reset') to create a pristine
|
2006-04-05 08:00:48 +02:00
|
|
|
working directory to test a clean build.
|
|
|
|
|
|
|
|
-X::
|
2013-01-21 20:17:53 +01:00
|
|
|
Remove only files ignored by Git. This may be useful to rebuild
|
2006-04-05 08:00:48 +02:00
|
|
|
everything from scratch, but keep manually created files.
|
|
|
|
|
2013-06-25 17:53:55 +02:00
|
|
|
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
|
2014-11-03 21:37:07 +01:00
|
|
|
"Input ignore patterns>>" prompt. You can input space-separated
|
2013-06-25 17:53:55 +02:00
|
|
|
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
|
2013-07-24 00:22:43 +02:00
|
|
|
range is omitted, all remaining items are selected. E.g. "7-" to
|
2013-06-25 17:53:55 +02:00
|
|
|
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.
|
|
|
|
|
2022-09-07 10:27:04 +02:00
|
|
|
CONFIGURATION
|
|
|
|
-------------
|
|
|
|
|
|
|
|
include::includes/cmd-config-section-all.txt[]
|
|
|
|
|
|
|
|
include::config/clean.txt[]
|
|
|
|
|
2012-09-19 01:25:33 +02:00
|
|
|
SEE ALSO
|
|
|
|
--------
|
|
|
|
linkgit:gitignore[5]
|
|
|
|
|
2006-04-05 08:00:48 +02:00
|
|
|
GIT
|
|
|
|
---
|
2008-06-06 09:07:32 +02:00
|
|
|
Part of the linkgit:git[1] suite
|