Skip to content

Commit 0fa2eb5

Browse files
moygitster
authored andcommitted
add: warn when -u or -A is used without pathspec
Most Git commands that can be used with or without pathspec operate tree-wide by default, the pathspec being used to restrict their scope. A few exceptions are: 'git grep', 'git clean', 'git add -u' and 'git add -A'. When run in a subdirectory without pathspec, they operate only on paths in the current directory. The inconsistency of 'git add -u' and 'git add -A' is particularly problematic since other 'git add' subcommands (namely 'git add -p' and 'git add -e') are tree-wide by default. It also means that "git add -u && git commit" will record a state that is different from what is recorded with "git commit -a". Flipping the default now is unacceptable, so let's start training users to type 'git add -u|-A :/' or 'git add -u|-A .' explicitly, to prepare for the next steps: * forbid 'git add -u|-A' without pathspec (like 'git add' without option) * much later, maybe, re-allow 'git add -u|-A' without pathspec, that will add all tracked and modified files, or all files, tree-wide. A nice side effect of this patch is that it makes the :/ magic pathspec easier to discover for users. When the command is called from the root of the tree, there is no ambiguity and no need to change the behavior, hence no need to warn. Signed-off-by: Matthieu Moy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b344bb1 commit 0fa2eb5

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

Documentation/git-add.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,10 @@ apply to the index. See EDITING PATCHES below.
107107
from the index if the corresponding files in the working tree
108108
have been removed.
109109
+
110-
If no <filepattern> is given, default to "."; in other words,
111-
update all tracked files in the current directory and its
112-
subdirectories.
110+
If no <filepattern> is given, the current version of Git defaults to
111+
"."; in other words, update all tracked files in the current directory
112+
and its subdirectories. This default will change in a future version
113+
of Git, hence the form without <filepattern> should not be used.
113114

114115
-A::
115116
--all::

builtin/add.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,35 @@ static int add_files(struct dir_struct *dir, int flags)
363363
return exit_status;
364364
}
365365

366+
static void warn_pathless_add(const char *option_name, const char *short_name) {
367+
/*
368+
* To be consistent with "git add -p" and most Git
369+
* commands, we should default to being tree-wide, but
370+
* this is not the original behavior and can't be
371+
* changed until users trained themselves not to type
372+
* "git add -u" or "git add -A". For now, we warn and
373+
* keep the old behavior. Later, this warning can be
374+
* turned into a die(...), and eventually we may
375+
* reallow the command with a new behavior.
376+
*/
377+
warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n"
378+
"subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n"
379+
"To add content for the whole tree, run:\n"
380+
"\n"
381+
" git add %s :/\n"
382+
" (or git add %s :/)\n"
383+
"\n"
384+
"To restrict the command to the current directory, run:\n"
385+
"\n"
386+
" git add %s .\n"
387+
" (or git add %s .)\n"
388+
"\n"
389+
"With the current Git version, the command is restricted to the current directory."),
390+
option_name, short_name,
391+
option_name, short_name,
392+
option_name, short_name);
393+
}
394+
366395
int cmd_add(int argc, const char **argv, const char *prefix)
367396
{
368397
int exit_status = 0;
@@ -373,6 +402,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
373402
int add_new_files;
374403
int require_pathspec;
375404
char *seen = NULL;
405+
const char *option_with_implicit_dot = NULL;
406+
const char *short_option_with_implicit_dot = NULL;
376407

377408
git_config(add_config, NULL);
378409

@@ -392,8 +423,19 @@ int cmd_add(int argc, const char **argv, const char *prefix)
392423
die(_("-A and -u are mutually incompatible"));
393424
if (!show_only && ignore_missing)
394425
die(_("Option --ignore-missing can only be used together with --dry-run"));
395-
if ((addremove || take_worktree_changes) && !argc) {
426+
if (addremove) {
427+
option_with_implicit_dot = "--all";
428+
short_option_with_implicit_dot = "-A";
429+
}
430+
if (take_worktree_changes) {
431+
option_with_implicit_dot = "--update";
432+
short_option_with_implicit_dot = "-u";
433+
}
434+
if (option_with_implicit_dot && !argc) {
396435
static const char *here[2] = { ".", NULL };
436+
if (prefix)
437+
warn_pathless_add(option_with_implicit_dot,
438+
short_option_with_implicit_dot);
397439
argc = 1;
398440
argv = here;
399441
}

0 commit comments

Comments
 (0)