Skip to content

Commit 561954b

Browse files
committed
Merge branch 'jc/add-2.0-delete-default' (early part)
Preparatory steps to make "git add <pathspec>" take notice of removed paths that match <pathspec> by default in Git 2.0. * 'jc/add-2.0-delete-default' (early part): git add: rephrase the "removal will cease to be ignored" warning git add: rework the logic to warn "git add <pathspec>..." default change git add: start preparing for "git add <pathspec>..." to default to "-A" builtin/add.c: simplify boolean variables
2 parents de0d774 + ccc663b commit 561954b

File tree

3 files changed

+103
-32
lines changed

3 files changed

+103
-32
lines changed

Documentation/git-add.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ SYNOPSIS
99
--------
1010
[verse]
1111
'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
12-
[--edit | -e] [--all | [--update | -u]] [--intent-to-add | -N]
12+
[--edit | -e] [--[no-]all | [--update | -u]] [--intent-to-add | -N]
1313
[--refresh] [--ignore-errors] [--ignore-missing] [--]
1414
[<pathspec>...]
1515

@@ -121,6 +121,18 @@ If no <pathspec> is given, the current version of Git defaults to
121121
and its subdirectories. This default will change in a future version
122122
of Git, hence the form without <pathspec> should not be used.
123123

124+
--no-all::
125+
Update the index by adding new files that are unknown to the
126+
index and files modified in the working tree, but ignore
127+
files that have been removed from the working tree. This
128+
option is a no-op when no <pathspec> is used.
129+
+
130+
This option is primarily to help the current users of Git, whose
131+
"git add <pathspec>..." ignores removed files. In future versions
132+
of Git, "git add <pathspec>..." will be a synonym to "git add -A
133+
<pathspec>..." and "git add --no-all <pathspec>..." will behave like
134+
today's "git add <pathspec>...", ignoring removed files.
135+
124136
-N::
125137
--intent-to-add::
126138
Record only the fact that the path will be added later. An entry

builtin/add.c

Lines changed: 87 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ struct update_callback_data {
2828
int add_errors;
2929
const char *implicit_dot;
3030
size_t implicit_dot_len;
31+
32+
/* only needed for 2.0 transition preparation */
33+
int warn_add_would_remove;
3134
};
3235

3336
static const char *option_with_implicit_dot;
@@ -93,6 +96,24 @@ static int fix_unmerged_status(struct diff_filepair *p,
9396
return DIFF_STATUS_MODIFIED;
9497
}
9598

99+
static const char *add_would_remove_warning = N_(
100+
"You ran 'git add' with neither '-A (--all)' or '--no-all', whose\n"
101+
"behaviour will change in Git 2.0 with respect to paths you removed from\n"
102+
"your working tree. Paths like '%s' that are\n"
103+
"removed are ignored with this version of Git.\n"
104+
"\n"
105+
"* 'git add --no-all <pathspec>', which is the current default, ignores\n"
106+
" paths you removed from your working tree.\n"
107+
"\n"
108+
"* 'git add --all <pathspec>' will let you also record the removals.\n"
109+
"\n"
110+
"Run 'git status' to check the paths you removed from your working tree.\n");
111+
112+
static void warn_add_would_remove(const char *path)
113+
{
114+
warning(_(add_would_remove_warning), path);
115+
}
116+
96117
static void update_callback(struct diff_queue_struct *q,
97118
struct diff_options *opt, void *cbdata)
98119
{
@@ -130,6 +151,10 @@ static void update_callback(struct diff_queue_struct *q,
130151
}
131152
break;
132153
case DIFF_STATUS_DELETED:
154+
if (data->warn_add_would_remove) {
155+
warn_add_would_remove(path);
156+
data->warn_add_would_remove = 0;
157+
}
133158
if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
134159
break;
135160
if (!(data->flags & ADD_CACHE_PRETEND))
@@ -141,32 +166,28 @@ static void update_callback(struct diff_queue_struct *q,
141166
}
142167
}
143168

144-
int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
169+
static void update_files_in_cache(const char *prefix, const char **pathspec,
170+
struct update_callback_data *data)
145171
{
146-
struct update_callback_data data;
147172
struct rev_info rev;
148173

149-
memset(&data, 0, sizeof(data));
150-
data.flags = flags & ~ADD_CACHE_IMPLICIT_DOT;
151-
if ((flags & ADD_CACHE_IMPLICIT_DOT) && prefix) {
152-
/*
153-
* Check for modified files throughout the worktree so
154-
* update_callback has a chance to warn about changes
155-
* outside the cwd.
156-
*/
157-
data.implicit_dot = prefix;
158-
data.implicit_dot_len = strlen(prefix);
159-
pathspec = NULL;
160-
}
161-
162174
init_revisions(&rev, prefix);
163175
setup_revisions(0, NULL, &rev, NULL);
164176
init_pathspec(&rev.prune_data, pathspec);
165177
rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
166178
rev.diffopt.format_callback = update_callback;
167-
rev.diffopt.format_callback_data = &data;
179+
rev.diffopt.format_callback_data = data;
168180
rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
169181
run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
182+
}
183+
184+
int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
185+
{
186+
struct update_callback_data data;
187+
188+
memset(&data, 0, sizeof(data));
189+
data.flags = flags;
190+
update_files_in_cache(prefix, pathspec, &data);
170191
return !!data.add_errors;
171192
}
172193

@@ -354,23 +375,27 @@ static struct lock_file lock_file;
354375
static const char ignore_error[] =
355376
N_("The following paths are ignored by one of your .gitignore files:\n");
356377

357-
static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
358-
static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0;
378+
static int verbose, show_only, ignored_too, refresh_only;
379+
static int ignore_add_errors, intent_to_add, ignore_missing;
380+
381+
#define ADDREMOVE_DEFAULT 0 /* Change to 1 in Git 2.0 */
382+
static int addremove = ADDREMOVE_DEFAULT;
383+
static int addremove_explicit = -1; /* unspecified */
359384

360385
static struct option builtin_add_options[] = {
361386
OPT__DRY_RUN(&show_only, N_("dry run")),
362387
OPT__VERBOSE(&verbose, N_("be verbose")),
363388
OPT_GROUP(""),
364-
OPT_BOOLEAN('i', "interactive", &add_interactive, N_("interactive picking")),
365-
OPT_BOOLEAN('p', "patch", &patch_interactive, N_("select hunks interactively")),
366-
OPT_BOOLEAN('e', "edit", &edit_interactive, N_("edit current diff and apply")),
389+
OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
390+
OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
391+
OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
367392
OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
368-
OPT_BOOLEAN('u', "update", &take_worktree_changes, N_("update tracked files")),
369-
OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
370-
OPT_BOOLEAN('A', "all", &addremove, N_("add changes from all tracked and untracked files")),
371-
OPT_BOOLEAN( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
372-
OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
373-
OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
393+
OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
394+
OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
395+
OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
396+
OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
397+
OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
398+
OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
374399
OPT_END(),
375400
};
376401

@@ -416,6 +441,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
416441
int require_pathspec;
417442
char *seen = NULL;
418443
int implicit_dot = 0;
444+
struct update_callback_data update_data;
419445

420446
git_config(add_config, NULL);
421447

@@ -431,8 +457,29 @@ int cmd_add(int argc, const char **argv, const char *prefix)
431457
argc--;
432458
argv++;
433459

460+
if (0 <= addremove_explicit)
461+
addremove = addremove_explicit;
462+
else if (take_worktree_changes && ADDREMOVE_DEFAULT)
463+
addremove = 0; /* "-u" was given but not "-A" */
464+
434465
if (addremove && take_worktree_changes)
435466
die(_("-A and -u are mutually incompatible"));
467+
468+
/*
469+
* Warn when "git add pathspec..." was given without "-u" or "-A"
470+
* and pathspec... covers a removed path.
471+
*/
472+
memset(&update_data, 0, sizeof(update_data));
473+
if (!take_worktree_changes && addremove_explicit < 0)
474+
update_data.warn_add_would_remove = 1;
475+
476+
if (!take_worktree_changes && addremove_explicit < 0 && argc)
477+
/*
478+
* Turn "git add pathspec..." to "git add -A pathspec..."
479+
* in Git 2.0 but not yet
480+
*/
481+
; /* addremove = 1; */
482+
436483
if (!show_only && ignore_missing)
437484
die(_("Option --ignore-missing can only be used together with --dry-run"));
438485
if (addremove) {
@@ -521,8 +568,20 @@ int cmd_add(int argc, const char **argv, const char *prefix)
521568

522569
plug_bulk_checkin();
523570

524-
exit_status |= add_files_to_cache(prefix, pathspec, flags);
571+
if ((flags & ADD_CACHE_IMPLICIT_DOT) && prefix) {
572+
/*
573+
* Check for modified files throughout the worktree so
574+
* update_callback has a chance to warn about changes
575+
* outside the cwd.
576+
*/
577+
update_data.implicit_dot = prefix;
578+
update_data.implicit_dot_len = strlen(prefix);
579+
pathspec = NULL;
580+
}
581+
update_data.flags = flags & ~ADD_CACHE_IMPLICIT_DOT;
582+
update_files_in_cache(prefix, pathspec, &update_data);
525583

584+
exit_status |= !!update_data.add_errors;
526585
if (add_new_files)
527586
exit_status |= add_files(&dir, flags);
528587

t/t2200-add-update.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,9 @@ test_expect_success 'add -u resolves unmerged paths' '
166166
echo 2 >path3 &&
167167
echo 2 >path5 &&
168168
169-
# Explicit resolving by adding removed paths should fail
170-
test_must_fail git add path4 &&
171-
test_must_fail git add path6 &&
169+
# Fail to explicitly resolve removed paths with "git add"
170+
test_must_fail git add --no-all path4 &&
171+
test_must_fail git add --no-all path6 &&
172172
173173
# "add -u" should notice removals no matter what stages
174174
# the index entries are in.

0 commit comments

Comments
 (0)