{"thread":{"id":"38814","subject":"[PATCH 1/3 v2] add: introduce new --exclude option","startedAt":"2015-03-15T19:06:23Z","lastAt":"2015-03-16T00:56:38Z","messageCount":7,"participants":["Alexander Kuleshov","Philip Oakley","Eric Sunshine"],"isPatch":true,"patchVersion":2,"patchTotal":3},"messages":[{"id":"257738","messageId":"1426446383-5264-1-git-send-email-kuleshovmail@gmail.com","threadId":"38814","inReplyTo":null,"subject":"[PATCH 1/3 v2] add: introduce new --exclude option","fromName":"Alexander Kuleshov","fromEmail":"kuleshovmail@gmail.com","sentAt":"2015-03-15T19:06:23Z","receivedAt":"2015-03-15T19:06:23Z","isPatch":true,"sender":{"key":"kuleshovmail@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2699235?v=4"},"body":"We already have core.excludesfile configuration variable which indicates\na path to file which contains patterns to exclude. This patch provides\nability to pass --exclude option to the git add command to exclude paths\nfrom command line in addition to which specified in the ignore files.\n\nThis option can be useful in a case when we have a directory with some *.ext\nfiles which have changes and we want to commit all files besides one for now.\nIt can be too annoying to touch .gitignore for this.\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nHelped-by: Torsten Bögershausen <tboegi@web.de>\nHelped-by: Philip Oakley <philipoakley@iee.org>\nSigned-off-by: Alexander Kuleshov <kuleshovmail@gmail.com>\n---\n builtin/add.c | 12 ++++++++++++\n 1 file changed, 12 insertions(+)\n\ndiff --git a/builtin/add.c b/builtin/add.c\nindex 3390933..e165fbc 100644\n--- a/builtin/add.c\n+++ b/builtin/add.c\n@@ -244,6 +244,8 @@ static int ignore_removal_cb(const struct option *opt, const char *arg, int unse\n \treturn 0;\n }\n \n+static struct string_list exclude_list = STRING_LIST_INIT_NODUP;\n+\n static struct option builtin_add_options[] = {\n \tOPT__DRY_RUN(&show_only, N_(\"dry run\")),\n \tOPT__VERBOSE(&verbose, N_(\"be verbose\")),\n@@ -255,6 +257,8 @@ static struct option builtin_add_options[] = {\n \tOPT_BOOL('u', \"update\", &take_worktree_changes, N_(\"update tracked files\")),\n \tOPT_BOOL('N', \"intent-to-add\", &intent_to_add, N_(\"record only the fact that the path will be added later\")),\n \tOPT_BOOL('A', \"all\", &addremove_explicit, N_(\"add changes from all tracked and untracked files\")),\n+\tOPT_STRING_LIST(0, \"exclude\", &exclude_list, N_(\"pattern\"),\n+\t\t\tN_(\"do not add files matching pattern to index\")),\n \t{ OPTION_CALLBACK, 0, \"ignore-removal\", &addremove_explicit,\n \t  NULL /* takes no arguments */,\n \t  N_(\"ignore paths removed in the working tree (same as --no-all)\"),\n@@ -305,6 +309,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \tint add_new_files;\n \tint require_pathspec;\n \tchar *seen = NULL;\n+\tstruct exclude_list *el;\n \n \tgit_config(add_config, NULL);\n \n@@ -379,8 +384,14 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t\t/* Set up the default git porcelain excludes */\n \t\tmemset(&dir, 0, sizeof(dir));\n \t\tif (!ignored_too) {\n+\t\t\tint i;\n \t\t\tdir.flags |= DIR_COLLECT_IGNORED;\n \t\t\tsetup_standard_excludes(&dir);\n+\n+\t\t\tel = add_exclude_list(&dir, EXC_CMDL, \"--exclude option\");\n+\t\t\tfor (i = 0; i < exclude_list.nr; i++)\n+\t\t\t\tadd_exclude(exclude_list.items[i].string, \"\", 0, el, -(i+1));\n+\n \t\t}\n \n \t\tmemset(&empty_pathspec, 0, sizeof(empty_pathspec));\n@@ -446,5 +457,6 @@ finish:\n \t\t\tdie(_(\"Unable to write new index file\"));\n \t}\n \n+\tstring_list_clear(&exclude_list, 0);\n \treturn exit_status;\n }\n-- \n2.3.3.472.g20ceeac.dirty\n"},{"id":"257739","messageId":"1426446416-5753-1-git-send-email-kuleshovmail@gmail.com","threadId":"38814","inReplyTo":"1426446383-5264-1-git-send-email-kuleshovmail@gmail.com","subject":"[PATCH 2/3 v2] Documentation/git-add.txt: describe --exclude option","fromName":"Alexander Kuleshov","fromEmail":"kuleshovmail@gmail.com","sentAt":"2015-03-15T19:06:56Z","receivedAt":"2015-03-15T19:06:56Z","isPatch":true,"sender":{"key":"kuleshovmail@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2699235?v=4"},"body":"Helped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Alexander Kuleshov <kuleshovmail@gmail.com>\n---\n Documentation/git-add.txt | 6 +++++-\n 1 file changed, 5 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-add.txt b/Documentation/git-add.txt\nindex f2eb907..fee97ed 100644\n--- a/Documentation/git-add.txt\n+++ b/Documentation/git-add.txt\n@@ -9,7 +9,7 @@ SYNOPSIS\n --------\n [verse]\n 'git add' [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p]\n-\t  [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]]\n+\t  [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--exclude=<pattern>]\n \t  [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing]\n \t  [--] [<pathspec>...]\n \n@@ -164,6 +164,10 @@ for \"git add --no-all <pathspec>...\", i.e. ignored removed files.\n \tbe ignored, no matter if they are already present in the work\n \ttree or not.\n \n+--exclude=<pattern>::\n+\tAlso ignore files matching <pattern>, a .gitignore-like\n+\tpattern. Option can be used multiply times.\n+\n \\--::\n \tThis option can be used to separate command-line options from\n \tthe list of files, (useful when filenames might be mistaken\n-- \n2.3.3.472.g20ceeac.dirty\n"},{"id":"257740","messageId":"1426446428-6279-1-git-send-email-kuleshovmail@gmail.com","threadId":"38814","inReplyTo":"1426446383-5264-1-git-send-email-kuleshovmail@gmail.com","subject":"[PATCH 3/3 v2] t3700-add: added test for --exclude option","fromName":"Alexander Kuleshov","fromEmail":"kuleshovmail@gmail.com","sentAt":"2015-03-15T19:07:08Z","receivedAt":"2015-03-15T19:07:08Z","isPatch":true,"sender":{"key":"kuleshovmail@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2699235?v=4"},"body":"Signed-off-by: Alexander Kuleshov <kuleshovmail@gmail.com>\n---\n t/t3700-add.sh | 18 ++++++++++++++++++\n 1 file changed, 18 insertions(+)\n\ndiff --git a/t/t3700-add.sh b/t/t3700-add.sh\nindex f7ff1f5..6f71c67 100755\n--- a/t/t3700-add.sh\n+++ b/t/t3700-add.sh\n@@ -332,4 +332,22 @@ test_expect_success 'git add --dry-run --ignore-missing of non-existing file out\n \ttest_i18ncmp expect.err actual.err\n '\n \n+test_expect_success 'Test that \"git add --exclude\" works' '\n+\t>foo &&\n+\t>bar &&\n+\tgit add --exclude=bar . &&\n+\t! (git ls-files | grep bar)\n+\t(git ls-files | grep foo)\n+'\n+\n+test_expect_success 'Test multiply --exclude' '\n+\t>foo &&\n+\t>bar &&\n+\t>\"b a z\" &&\n+\tgit add --exclude=\"bar\" --exclude=\"b a z\" . &&\n+\t(git ls-files | grep foo)\n+\t! (git ls-files | grep \"b a z\")\n+\t! (git ls-files | grep \"baz\")\n+'\n+\n test_done\n-- \n2.3.3.472.g20ceeac.dirty\n"},{"id":"257748","messageId":"EB998FABBD404DB788EF43345031964B@PhilipOakley","threadId":"38814","inReplyTo":"1426446383-5264-1-git-send-email-kuleshovmail@gmail.com","subject":"Re: [PATCH 1/3 v2] add: introduce new --exclude option","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.org","sentAt":null,"receivedAt":"2015-03-15T20:45:48Z","isPatch":true,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"From: \"Alexander Kuleshov\" <kuleshovmail@gmail.com>\n>\n> Helped-by: Eric Sunshine <sunshine@sunshineco.com>\n> Helped-by: Torsten Bögershausen <tboegi@web.de>\n> Helped-by: Philip Oakley <philipoakley@iee.org>\n\nWhile the kudo points are nice to have, I wouldn't say my minor \ncontribution was worthy of the extra Helped-by.\n\nI'd be happy for it to be dropped if you have any rewrites.\n\n> Signed-off-by: Alexander Kuleshov <kuleshovmail@gmail.com>\n> ---\n--\nPhilip \n"},{"id":"257762","messageId":"CAPig+cShxOpS9W9Fp7BXM66SCRdZaJ4hpWbW9ruqCQeK8eSEBw@mail.gmail.com","threadId":"38814","inReplyTo":"1426446428-6279-1-git-send-email-kuleshovmail@gmail.com","subject":"Re: [PATCH 3/3 v2] t3700-add: added test for --exclude option","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-03-16T00:35:24Z","receivedAt":"2015-03-16T00:35:24Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Mar 15, 2015 at 3:07 PM, Alexander Kuleshov\n<kuleshovmail@gmail.com> wrote:\n> t3700-add: added test for --exclude option\n\ns/added/add/\n\n> Signed-off-by: Alexander Kuleshov <kuleshovmail@gmail.com>\n> ---\n> diff --git a/t/t3700-add.sh b/t/t3700-add.sh\n> index f7ff1f5..6f71c67 100755\n> --- a/t/t3700-add.sh\n> +++ b/t/t3700-add.sh\n> @@ -332,4 +332,22 @@ test_expect_success 'git add --dry-run --ignore-missing of non-existing file out\n>         test_i18ncmp expect.err actual.err\n>  '\n>\n> +test_expect_success 'Test that \"git add --exclude\" works' '\n\nRather than inventing a new title style, try to match the style of the\nexisting tests titles in this file.\n\n> +       >foo &&\n> +       >bar &&\n> +       git add --exclude=bar . &&\n> +       ! (git ls-files | grep bar)\n\nBroken &&-chain.\n\n> +       (git ls-files | grep foo)\n\nUnnecessary additional git-ls-files invocation. You could just save\nthe output to a file and then process that file.\n\n> +'\n> +\n> +test_expect_success 'Test multiply --exclude' '\n\ns/multiply/multiple/\n\nDitto: Match existing title style.\n\n> +       >foo &&\n> +       >bar &&\n> +       >\"b a z\" &&\n> +       git add --exclude=\"bar\" --exclude=\"b a z\" . &&\n> +       (git ls-files | grep foo)\n> +       ! (git ls-files | grep \"b a z\")\n> +       ! (git ls-files | grep \"baz\")\n\nBroken &&-chain throughout.\n\nDitto: Unnecessary git-ls-files invocations.\n\n> +'\n> +\n>  test_done\n> --\n> 2.3.3.472.g20ceeac.dirty\n"},{"id":"257763","messageId":"CAPig+cT0SS2hJ+9vNk6B0NfsFKSDa4FK-B0hYBYpGSBk1FfFKA@mail.gmail.com","threadId":"38814","inReplyTo":"1426446416-5753-1-git-send-email-kuleshovmail@gmail.com","subject":"Re: [PATCH 2/3 v2] Documentation/git-add.txt: describe --exclude option","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-03-16T00:36:53Z","receivedAt":"2015-03-16T00:36:53Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Mar 15, 2015 at 3:06 PM, Alexander Kuleshov\n<kuleshovmail@gmail.com> wrote:\n> Helped-by: Eric Sunshine <sunshine@sunshineco.com>\n> Signed-off-by: Alexander Kuleshov <kuleshovmail@gmail.com>\n> ---\n> diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt\n> index f2eb907..fee97ed 100644\n> --- a/Documentation/git-add.txt\n> +++ b/Documentation/git-add.txt\n> @@ -9,7 +9,7 @@ SYNOPSIS\n>  --------\n>  [verse]\n>  'git add' [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p]\n> -         [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]]\n> +         [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]] [--exclude=<pattern>]\n>           [--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing]\n>           [--] [<pathspec>...]\n>\n> @@ -164,6 +164,10 @@ for \"git add --no-all <pathspec>...\", i.e. ignored removed files.\n>         be ignored, no matter if they are already present in the work\n>         tree or not.\n>\n> +--exclude=<pattern>::\n> +       Also ignore files matching <pattern>, a .gitignore-like\n> +       pattern. Option can be used multiply times.\n\ns/multiply/multiple/\n\n> +\n>  \\--::\n>         This option can be used to separate command-line options from\n>         the list of files, (useful when filenames might be mistaken\n> --\n> 2.3.3.472.g20ceeac.dirty\n"},{"id":"257765","messageId":"CAPig+cS5GKHCeT3zY_oV-kKBT-Os4xn-8J3iew7741UCLYLYyA@mail.gmail.com","threadId":"38814","inReplyTo":"1426446383-5264-1-git-send-email-kuleshovmail@gmail.com","subject":"Re: [PATCH 1/3 v2] add: introduce new --exclude option","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2015-03-16T00:56:38Z","receivedAt":"2015-03-16T00:56:38Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Mar 15, 2015 at 3:06 PM, Alexander Kuleshov\n<kuleshovmail@gmail.com> wrote:\n> We already have core.excludesfile configuration variable which indicates\n> a path to file which contains patterns to exclude. This patch provides\n> ability to pass --exclude option to the git add command to exclude paths\n> from command line in addition to which specified in the ignore files.\n>\n> This option can be useful in a case when we have a directory with some *.ext\n> files which have changes and we want to commit all files besides one for now.\n> It can be too annoying to touch .gitignore for this.\n\nWon't this lead to unintuitive behavior? The 'excludes' mechanism does\nnot unconditionally ignore; instead, it ignores _untracked_ files.\nConsider file \"foo\" which is already tracked. Make a temporary change\nto \"foo\" which you don't intend to commit. Since \"foo\" is tracked, the\ncommand 'git add . --exclude=foo' will still add \"foo\" to the index,\ndespite the use of --exclude. Most people would probably find such\nbehavior surprising and undesirable.\n\nThe negative pathspec mentioned by Junio[1], on the other hand, does\nnot suffer this shortcoming.\n\nMore below.\n\n[1]: http://thread.gmane.org/gmane.comp.version-control.git/265493/focus=265518\n\n> Helped-by: Eric Sunshine <sunshine@sunshineco.com>\n> Helped-by: Torsten Bögershausen <tboegi@web.de>\n> Helped-by: Philip Oakley <philipoakley@iee.org>\n> Signed-off-by: Alexander Kuleshov <kuleshovmail@gmail.com>\n> ---\n> diff --git a/builtin/add.c b/builtin/add.c\n> index 3390933..e165fbc 100644\n> --- a/builtin/add.c\n> +++ b/builtin/add.c\n> @@ -244,6 +244,8 @@ static int ignore_removal_cb(const struct option *opt, const char *arg, int unse\n>         return 0;\n>  }\n>\n> +static struct string_list exclude_list = STRING_LIST_INIT_NODUP;\n> +\n>  static struct option builtin_add_options[] = {\n>         OPT__DRY_RUN(&show_only, N_(\"dry run\")),\n>         OPT__VERBOSE(&verbose, N_(\"be verbose\")),\n> @@ -255,6 +257,8 @@ static struct option builtin_add_options[] = {\n>         OPT_BOOL('u', \"update\", &take_worktree_changes, N_(\"update tracked files\")),\n>         OPT_BOOL('N', \"intent-to-add\", &intent_to_add, N_(\"record only the fact that the path will be added later\")),\n>         OPT_BOOL('A', \"all\", &addremove_explicit, N_(\"add changes from all tracked and untracked files\")),\n> +       OPT_STRING_LIST(0, \"exclude\", &exclude_list, N_(\"pattern\"),\n> +                       N_(\"do not add files matching pattern to index\")),\n>         { OPTION_CALLBACK, 0, \"ignore-removal\", &addremove_explicit,\n>           NULL /* takes no arguments */,\n>           N_(\"ignore paths removed in the working tree (same as --no-all)\"),\n> @@ -305,6 +309,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n>         int add_new_files;\n>         int require_pathspec;\n>         char *seen = NULL;\n> +       struct exclude_list *el;\n\nThis variable is only used within the 'if (!ignored_too)' block below,\nso its declaration should be moved there.\n\n>         git_config(add_config, NULL);\n>\n> @@ -379,8 +384,14 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n>                 /* Set up the default git porcelain excludes */\n>                 memset(&dir, 0, sizeof(dir));\n>                 if (!ignored_too) {\n> +                       int i;\n>                         dir.flags |= DIR_COLLECT_IGNORED;\n>                         setup_standard_excludes(&dir);\n> +\n> +                       el = add_exclude_list(&dir, EXC_CMDL, \"--exclude option\");\n> +                       for (i = 0; i < exclude_list.nr; i++)\n> +                               add_exclude(exclude_list.items[i].string, \"\", 0, el, -(i+1));\n> +\n>                 }\n>\n>                 memset(&empty_pathspec, 0, sizeof(empty_pathspec));\n> @@ -446,5 +457,6 @@ finish:\n>                         die(_(\"Unable to write new index file\"));\n>         }\n>\n> +       string_list_clear(&exclude_list, 0);\n>         return exit_status;\n>  }\n> --\n> 2.3.3.472.g20ceeac.dirty\n"}]}