Skip to content

Commit 108da0d

Browse files
jlehmanngitster
authored andcommitted
git add: Add the "--ignore-missing" option for the dry run
Sometimes it is useful to know if a file or directory will be ignored before it is added to the work tree. An example is "git submodule add", where it would be really nice to be able to fail with an appropriate error message before the submodule is cloned and checked out. Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 637ab29 commit 108da0d

File tree

5 files changed

+47
-6
lines changed

5 files changed

+47
-6
lines changed

Documentation/git-add.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ OPTIONS
5757

5858
-n::
5959
--dry-run::
60-
Don't actually add the file(s), just show if they exist.
60+
Don't actually add the file(s), just show if they exist and/or will
61+
be ignored.
6162

6263
-v::
6364
--verbose::
@@ -131,6 +132,12 @@ subdirectories.
131132
them, do not abort the operation, but continue adding the
132133
others. The command shall still exit with non-zero status.
133134

135+
--ignore-missing::
136+
This option can only be used together with --dry-run. By using
137+
this option the user can check if any of the given files would
138+
be ignored, no matter if they are already present in the work
139+
tree or not.
140+
134141
\--::
135142
This option can be used to separate command-line options from
136143
the list of files, (useful when filenames might be mistaken

builtin/add.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ static const char ignore_error[] =
310310
"The following paths are ignored by one of your .gitignore files:\n";
311311

312312
static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
313-
static int ignore_add_errors, addremove, intent_to_add;
313+
static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0;
314314

315315
static struct option builtin_add_options[] = {
316316
OPT__DRY_RUN(&show_only),
@@ -325,6 +325,7 @@ static struct option builtin_add_options[] = {
325325
OPT_BOOLEAN('A', "all", &addremove, "add all, noticing removal of tracked files"),
326326
OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
327327
OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, "just skip files which cannot be added because of errors"),
328+
OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, "check if - even missing - files are ignored in dry run"),
328329
OPT_END(),
329330
};
330331

@@ -385,6 +386,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
385386

386387
if (addremove && take_worktree_changes)
387388
die("-A and -u are mutually incompatible");
389+
if (!show_only && ignore_missing)
390+
die("Option --ignore-missing can only be used together with --dry-run");
388391
if ((addremove || take_worktree_changes) && !argc) {
389392
static const char *here[2] = { ".", NULL };
390393
argc = 1;
@@ -441,9 +444,14 @@ int cmd_add(int argc, const char **argv, const char *prefix)
441444
seen = find_used_pathspec(pathspec);
442445
for (i = 0; pathspec[i]; i++) {
443446
if (!seen[i] && pathspec[i][0]
444-
&& !file_exists(pathspec[i]))
445-
die("pathspec '%s' did not match any files",
446-
pathspec[i]);
447+
&& !file_exists(pathspec[i])) {
448+
if (ignore_missing) {
449+
if (excluded(&dir, pathspec[i], DT_UNKNOWN))
450+
dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
451+
} else
452+
die("pathspec '%s' did not match any files",
453+
pathspec[i]);
454+
}
447455
}
448456
free(seen);
449457
}

dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna
453453
return dir->entries[dir->nr++] = dir_entry_new(pathname, len);
454454
}
455455

456-
static struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len)
456+
struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len)
457457
{
458458
if (!cache_name_is_other(pathname, len))
459459
return NULL;

dir.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ extern int read_directory(struct dir_struct *, const char *path, int len, const
7272
extern int excluded_from_list(const char *pathname, int pathlen, const char *basename,
7373
int *dtype, struct exclude_list *el);
7474
extern int excluded(struct dir_struct *, const char *, int *);
75+
struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len);
7576
extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
7677
char **buf_p, struct exclude_list *which, int check_index);
7778
extern void add_excludes_from_file(struct dir_struct *, const char *fname);

t/t3700-add.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,29 @@ test_expect_success '"add non-existent" should fail' '
260260
! (git ls-files | grep "non-existent")
261261
'
262262

263+
test_expect_success 'git add --dry-run of existing changed file' "
264+
echo new >>track-this &&
265+
git add --dry-run track-this >actual 2>&1 &&
266+
echo \"add 'track-this'\" | test_cmp - actual
267+
"
268+
269+
test_expect_success 'git add --dry-run of non-existing file' "
270+
echo ignored-file >>.gitignore &&
271+
! (git add --dry-run track-this ignored-file >actual 2>&1) &&
272+
echo \"fatal: pathspec 'ignored-file' did not match any files\" | test_cmp - actual
273+
"
274+
275+
cat >expect <<EOF
276+
The following paths are ignored by one of your .gitignore files:
277+
ignored-file
278+
Use -f if you really want to add them.
279+
fatal: no files added
280+
add 'track-this'
281+
EOF
282+
283+
test_expect_success 'git add --dry-run --ignore-missing of non-existing file' '
284+
!(git add --dry-run --ignore-missing track-this ignored-file >actual 2>&1) &&
285+
test_cmp expect actual
286+
'
287+
263288
test_done

0 commit comments

Comments
 (0)