diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index b0944e57d5..5c501a299e 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -9,7 +9,7 @@ SYNOPSIS -------- [verse] 'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p] - [--edit | -e] [--all | [--update | -u]] [--intent-to-add | -N] + [--edit | -e] [--[no-]all | [--update | -u]] [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing] [--] [...] @@ -121,6 +121,18 @@ If no is given, the current version of Git defaults to and its subdirectories. This default will change in a future version of Git, hence the form without should not be used. +--no-all:: + Update the index by adding new files that are unknown to the + index and files modified in the working tree, but ignore + files that have been removed from the working tree. This + option is a no-op when no is used. ++ +This option is primarily to help the current users of Git, whose +"git add ..." ignores removed files. In future versions +of Git, "git add ..." will be a synonym to "git add -A +..." and "git add --no-all ..." will behave like +today's "git add ...", ignoring removed files. + -N:: --intent-to-add:: Record only the fact that the path will be added later. An entry diff --git a/builtin/add.c b/builtin/add.c index 220321b7a3..f8f6c9ed34 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -271,7 +271,11 @@ static const char ignore_error[] = N_("The following paths are ignored by one of your .gitignore files:\n"); static int verbose, show_only, ignored_too, refresh_only; -static int ignore_add_errors, addremove, intent_to_add, ignore_missing; +static int ignore_add_errors, intent_to_add, ignore_missing; + +#define ADDREMOVE_DEFAULT 0 /* Change to 1 in Git 2.0 */ +static int addremove = ADDREMOVE_DEFAULT; +static int addremove_explicit = -1; /* unspecified */ static struct option builtin_add_options[] = { OPT__DRY_RUN(&show_only, N_("dry run")), @@ -283,7 +287,7 @@ static struct option builtin_add_options[] = { OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")), OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")), OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")), - OPT_BOOL('A', "all", &addremove, N_("add changes from all tracked and untracked files")), + OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")), OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")), OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")), OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")), @@ -350,6 +354,18 @@ static void warn_pathless_add(const char *option_name, const char *short_name) { option_name, short_name); } +static int directory_given(int argc, const char **argv) +{ + struct stat st; + + while (argc--) { + if (!lstat(*argv, &st) && S_ISDIR(st.st_mode)) + return 1; + argv++; + } + return 0; +} + int cmd_add(int argc, const char **argv, const char *prefix) { int exit_status = 0; @@ -377,8 +393,33 @@ int cmd_add(int argc, const char **argv, const char *prefix) argc--; argv++; + if (0 <= addremove_explicit) + addremove = addremove_explicit; + else if (take_worktree_changes && ADDREMOVE_DEFAULT) + addremove = 0; /* "-u" was given but not "-A" */ + if (addremove && take_worktree_changes) die(_("-A and -u are mutually incompatible")); + + /* + * Warn when "git add pathspec..." was given without "-u" or "-A" + * and pathspec... contains a directory name. + */ + if (!take_worktree_changes && addremove_explicit < 0 && + directory_given(argc, argv)) + warning(_("In Git 2.0, 'git add ...' will also update the\n" + "index for paths removed from the working tree that match\n" + "the given pathspec. If you want to 'add' only changed\n" + "or newly created paths, say 'git add --no-all ...'" + " instead.")); + + if (!take_worktree_changes && addremove_explicit < 0 && argc) + /* + * Turn "git add pathspec..." to "git add -A pathspec..." + * in Git 2.0 but not yet + */ + ; /* addremove = 1; */ + if (!show_only && ignore_missing) die(_("Option --ignore-missing can only be used together with --dry-run")); if (addremove) { diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh index 4cdebda6a5..32f932a4ce 100755 --- a/t/t2200-add-update.sh +++ b/t/t2200-add-update.sh @@ -150,9 +150,9 @@ test_expect_success 'add -u resolves unmerged paths' ' echo 2 >path3 && echo 2 >path5 && - # Explicit resolving by adding removed paths should fail - test_must_fail git add path4 && - test_must_fail git add path6 && + # Fail to explicitly resolve removed paths with "git add" + test_must_fail git add --no-all path4 && + test_must_fail git add --no-all path6 && # "add -u" should notice removals no matter what stages # the index entries are in.