git add: -u/-A now affects the entire working tree
As promised in 0fa2eb530fb7 (add: warn when -u or -A is used without pathspec, 2013-01-28), in Git 2.0, "git add -u/-A" that is run without pathspec in a subdirectory updates all updated paths in the entire working tree, not just the current directory and its subdirectories. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Mar 19, 2013 at 15:53 UTC
808d3d717e86be597aa94d4a26f82a0ba5a53c22
4 files changed
+19
-121
Documentation/git-add.txt
+8
-8
@@ -104,10 +104,10 @@ apply to the index. See EDITING PATCHES below.
104
<pathspec>. This removes as well as modifies index entries to
105
match the working tree, but adds no new files.
106
+
107
-If no <pathspec> is given, the current version of Git defaults to
108
-"."; in other words, update all tracked files in the current directory
109
-and its subdirectories. This default will change in a future version
110
-of Git, hence the form without <pathspec> should not be used.
107
+If no <pathspec> is given when `-u` option is used, all
108
+tracked files in the entire working tree are updated (old versions
109
+of Git used to limit the update to the current directory and its
110
+subdirectories).
111
112
-A::
113
--all::
@@ -117,10 +117,10 @@ of Git, hence the form without <pathspec> should not be used.
117
entry. This adds, modifies, and removes index entries to
118
match the working tree.
119
+
120
-If no <pathspec> is given, the current version of Git defaults to
121
-"."; in other words, update all files in the current directory
122
-and its subdirectories. This default will change in a future version
123
-of Git, hence the form without <pathspec> should not be used.
120
+If no <pathspec> is given when `-A` option is used, all
121
+files in the entire working tree are updated (old versions
122
+of Git used to limit the update to the current directory and its
123
+subdirectories).
124
125
--no-all::
126
--ignore-removal::
builtin/add.c
+9
-105
@@ -26,55 +26,10 @@ static int take_worktree_changes;
26
struct update_callback_data {
27
int flags;
28
int add_errors;
29
- const char *implicit_dot;
30
- size_t implicit_dot_len;
31
-
29
/* only needed for 2.0 transition preparation */
30
int warn_add_would_remove;
31
};
32
36
-static const char *option_with_implicit_dot;
37
-static const char *short_option_with_implicit_dot;
38
-
39
-static void warn_pathless_add(void)
40
-{
41
- static int shown;
42
- assert(option_with_implicit_dot && short_option_with_implicit_dot);
43
-
44
- if (shown)
45
- return;
46
- shown = 1;
47
-
48
- /*
49
- * To be consistent with "git add -p" and most Git
50
- * commands, we should default to being tree-wide, but
51
- * this is not the original behavior and can't be
52
- * changed until users trained themselves not to type
53
- * "git add -u" or "git add -A". For now, we warn and
54
- * keep the old behavior. Later, the behavior can be changed
55
- * to tree-wide, keeping the warning for a while, and
56
- * eventually we can drop the warning.
57
- */
58
- warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n"
59
- "subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n"
60
- "To add content for the whole tree, run:\n"
61
- "\n"
62
- " git add %s :/\n"
63
- " (or git add %s :/)\n"
64
- "\n"
65
- "To restrict the command to the current directory, run:\n"
66
- "\n"
67
- " git add %s .\n"
68
- " (or git add %s .)\n"
69
- "\n"
70
- "With the current Git version, the command is restricted to "
71
- "the current directory.\n"
72
- ""),
73
- option_with_implicit_dot, short_option_with_implicit_dot,
74
- option_with_implicit_dot, short_option_with_implicit_dot,
75
- option_with_implicit_dot, short_option_with_implicit_dot);
76
-}
77
-
33
static int fix_unmerged_status(struct diff_filepair *p,
34
struct update_callback_data *data)
35
{
@@ -119,26 +74,10 @@ static void update_callback(struct diff_queue_struct *q,
74
{
75
int i;
76
struct update_callback_data *data = cbdata;
122
- const char *implicit_dot = data->implicit_dot;
123
- size_t implicit_dot_len = data->implicit_dot_len;
77
78
for (i = 0; i < q->nr; i++) {
79
struct diff_filepair *p = q->queue[i];
80
const char *path = p->one->path;
128
- /*
129
- * Check if "git add -A" or "git add -u" was run from a
130
- * subdirectory with a modified file outside that directory,
131
- * and warn if so.
132
- *
133
- * "git add -u" will behave like "git add -u :/" instead of
134
- * "git add -u ." in the future. This warning prepares for
135
- * that change.
136
- */
137
- if (implicit_dot &&
138
- strncmp_icase(path, implicit_dot, implicit_dot_len)) {
139
- warn_pathless_add();
140
- continue;
141
- }
81
switch (fix_unmerged_status(p, data)) {
82
default:
83
die(_("unexpected diff status %c"), p->status);
@@ -191,9 +130,7 @@ int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
130
return !!data.add_errors;
131
}
132
194
-#define WARN_IMPLICIT_DOT (1u << 0)
195
-static char *prune_directory(struct dir_struct *dir, const char **pathspec,
196
- int prefix, unsigned flag)
133
+static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
134
{
135
char *seen;
136
int i, specs;
@@ -210,16 +147,6 @@ static char *prune_directory(struct dir_struct *dir, const char **pathspec,
147
if (match_pathspec(pathspec, entry->name, entry->len,
148
prefix, seen))
149
*dst++ = entry;
213
- else if (flag & WARN_IMPLICIT_DOT)
214
- /*
215
- * "git add -A" was run from a subdirectory with a
216
- * new file outside that directory.
217
- *
218
- * "git add -A" will behave like "git add -A :/"
219
- * instead of "git add -A ." in the future.
220
- * Warn about the coming behavior change.
221
- */
222
- warn_pathless_add();
150
}
151
dir->nr = dst - dir->entries;
152
add_pathspec_matches_against_index(pathspec, seen, specs);
@@ -451,7 +378,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
378
int add_new_files;
379
int require_pathspec;
380
char *seen = NULL;
454
- int implicit_dot = 0;
381
struct update_callback_data update_data;
382
383
git_config(add_config, NULL);
@@ -493,19 +419,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
419
420
if (!show_only && ignore_missing)
421
die(_("Option --ignore-missing can only be used together with --dry-run"));
496
- if (addremove) {
497
- option_with_implicit_dot = "--all";
498
- short_option_with_implicit_dot = "-A";
499
- }
500
- if (take_worktree_changes) {
501
- option_with_implicit_dot = "--update";
502
- short_option_with_implicit_dot = "-u";
503
- }
504
- if (option_with_implicit_dot && !argc) {
505
- static const char *here[2] = { ".", NULL };
422
+
423
+ if ((addremove || take_worktree_changes) && !argc) {
424
+ static const char *whole[2] = { ":/", NULL };
425
argc = 1;
507
- argv = here;
508
- implicit_dot = 1;
426
+ argv = whole;
427
}
428
429
add_new_files = !take_worktree_changes && !refresh_only;
@@ -518,8 +436,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
436
(intent_to_add ? ADD_CACHE_INTENT : 0) |
437
(ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
438
(!(addremove || take_worktree_changes)
521
- ? ADD_CACHE_IGNORE_REMOVAL : 0)) |
522
- (implicit_dot ? ADD_CACHE_IMPLICIT_DOT : 0);
439
+ ? ADD_CACHE_IGNORE_REMOVAL : 0));
440
441
if (require_pathspec && argc == 0) {
442
fprintf(stderr, _("Nothing specified, nothing added.\n"));
@@ -543,18 +460,15 @@ int cmd_add(int argc, const char **argv, const char *prefix)
460
}
461
462
/* This picks up the paths that are not tracked */
546
- baselen = fill_directory(&dir, implicit_dot ? NULL : pathspec);
463
+ baselen = fill_directory(&dir, pathspec);
464
if (pathspec)
548
- seen = prune_directory(&dir, pathspec, baselen,
549
- implicit_dot ? WARN_IMPLICIT_DOT : 0);
465
+ seen = prune_directory(&dir, pathspec, baselen);
466
}
467
468
if (refresh_only) {
469
refresh(verbose, pathspec);
470
goto finish;
471
}
556
- if (implicit_dot && prefix)
557
- refresh_cache(REFRESH_QUIET);
472
473
if (pathspec) {
474
int i;
@@ -578,17 +492,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
492
493
plug_bulk_checkin();
494
581
- if ((flags & ADD_CACHE_IMPLICIT_DOT) && prefix) {
582
- /*
583
- * Check for modified files throughout the worktree so
584
- * update_callback has a chance to warn about changes
585
- * outside the cwd.
586
- */
587
- update_data.implicit_dot = prefix;
588
- update_data.implicit_dot_len = strlen(prefix);
589
- pathspec = NULL;
590
- }
591
- update_data.flags = flags & ~ADD_CACHE_IMPLICIT_DOT;
495
+ update_data.flags = flags;
496
update_files_in_cache(prefix, pathspec, &update_data);
497
498
exit_status |= !!update_data.add_errors;
cache.h
-1
@@ -466,7 +466,6 @@ extern int remove_file_from_index(struct index_state *, const char *path);
466
#define ADD_CACHE_IGNORE_ERRORS 4
467
#define ADD_CACHE_IGNORE_REMOVAL 8
468
#define ADD_CACHE_INTENT 16
469
-#define ADD_CACHE_IMPLICIT_DOT 32 /* internal to "git add -u/-A" */
469
extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
470
extern int add_file_to_index(struct index_state *, const char *path, int flags);
471
extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
t/t2200-add-update.sh
+2
-7
@@ -80,18 +80,13 @@ test_expect_success 'change gets noticed' '
80
81
'
82
83
-# Note that this is scheduled to change in Git 2.0, when
84
-# "git add -u" will become full-tree by default.
85
-test_expect_success 'non-limited update in subdir leaves root alone' '
83
+test_expect_success 'non-qualified update in subdir updates from the root' '
84
(
85
cd dir1 &&
86
echo even more >>sub2 &&
87
git add -u
88
) &&
91
- cat >expect <<-\EOF &&
92
- check
93
- top
94
- EOF
89
+ : >expect &&
90
git diff-files --name-only >actual &&
91
test_cmp expect actual
92
'