{"thread":{"id":"35780","subject":"splitting a commit that adds new files","startedAt":"2014-02-01T10:48:34Z","lastAt":"2014-02-06T01:58:18Z","messageCount":17,"participants":["Duy Nguyen","Junio C Hamano","Jeff King","Nguyễn Thái Ngọc Duy","Jonathan Nieder"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"234019","messageId":"CACsJy8BXGZ+1Oqrpcky5JPCtZRwvxmxhXGfuEqY9Ct4Pt8FmJg@mail.gmail.com","threadId":"35780","inReplyTo":null,"subject":"splitting a commit that adds new files","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2014-02-01T10:48:34Z","receivedAt":"2014-02-01T10:48:34Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"I usually start splitting a commit with \"reset @^\" then \"add -p\" back.\nThe problem is \"reset @^\" does not keep track of new files added in\nHEAD, so I often end up forgetting to add new files back (with \"add\n-p\"). I'm thinking of making \"reset\" to do \"add -N\" automatically for\nme so I won't miss changes in \"add -p\". But maybe people already know\nhow to deal with this case without adding more code?\n-- \nDuy\n"},{"id":"234057","messageId":"xmqqzjm9fkk4.fsf@gitster.dls.corp.google.com","threadId":"35780","inReplyTo":"CACsJy8BXGZ+1Oqrpcky5JPCtZRwvxmxhXGfuEqY9Ct4Pt8FmJg@mail.gmail.com","subject":"Re: splitting a commit that adds new files","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-02-02T18:15:07Z","receivedAt":"2014-02-02T18:15:07Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> I usually start splitting a commit with \"reset @^\" then \"add -p\" back.\n> The problem is \"reset @^\" does not keep track of new files added in\n> HEAD, so I often end up forgetting to add new files back (with \"add\n> -p\"). I'm thinking of making \"reset\" to do \"add -N\" automatically for\n> me so I won't miss changes in \"add -p\". But maybe people already know\n> how to deal with this case without adding more code?\n\nIs \"reset -p\" what you are looking for?  I do not use that myself,\nthough.\n"},{"id":"234065","messageId":"20140202231110.GC16196@sigill.intra.peff.net","threadId":"35780","inReplyTo":"xmqqzjm9fkk4.fsf@gitster.dls.corp.google.com","subject":"Re: splitting a commit that adds new files","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-02-02T23:11:10Z","receivedAt":"2014-02-02T23:11:10Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Feb 02, 2014 at 10:15:07AM -0800, Junio C Hamano wrote:\n\n> Duy Nguyen <pclouds@gmail.com> writes:\n> \n> > I usually start splitting a commit with \"reset @^\" then \"add -p\" back.\n> > The problem is \"reset @^\" does not keep track of new files added in\n> > HEAD, so I often end up forgetting to add new files back (with \"add\n> > -p\"). I'm thinking of making \"reset\" to do \"add -N\" automatically for\n> > me so I won't miss changes in \"add -p\". But maybe people already know\n> > how to deal with this case without adding more code?\n> \n> Is \"reset -p\" what you are looking for?  I do not use that myself,\n> though.\n\nI don't think so. He is at a commit that needs split, so the first thing\nto do is to shift the HEAD back. \"reset -p\" is only about changing the\nindex[1]. I suppose you could start with a soft reset, and then \"reset\n-p\" away the changes. But then you are going backwards (\"this does not\nbelong in the commit, remove it\" rather than \"this does belong in the\ncommit, add it\").\n\nI don't typically have a problem with this because I keep my directory\nfree of untracked files (they are either marked by .gitignore, or\nsomething that I am planning to commit). So just running \"git status\"\ngives me a neat list of what needs to be added (and typically \"git add\n-N .\" is a good starting point upon which to build a \"git add -p\"\nsession).\n\n-Peff\n\n[1] I _do_ use \"reset -p\" when splitting commits, but I do not think it\n    is useful here. I use it for \"oops, I staged this change, but it\n    actually belongs in the next commit. Undo my staging, but leave the\n    changes in the working tree for the next one\".\n"},{"id":"234121","messageId":"xmqqioswf4mh.fsf@gitster.dls.corp.google.com","threadId":"35780","inReplyTo":"20140202231110.GC16196@sigill.intra.peff.net","subject":"Re: splitting a commit that adds new files","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-02-03T18:11:34Z","receivedAt":"2014-02-03T18:11:34Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> [1] I _do_ use \"reset -p\" when splitting commits, but I do not think it\n>     is useful here. I use it for \"oops, I staged this change, but it\n>     actually belongs in the next commit. Undo my staging, but leave the\n>     changes in the working tree for the next one\".\n\nSure.  I thought that was exactly what Duy was attempting to do when\nhe splitted a commit into two (or more).\n"},{"id":"234181","messageId":"CACsJy8AWHJ=FE3zQN_UUc-AnAz14OsRk8Xw36_Y8n+VujTP35A@mail.gmail.com","threadId":"35780","inReplyTo":"xmqqioswf4mh.fsf@gitster.dls.corp.google.com","subject":"Re: splitting a commit that adds new files","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2014-02-04T00:54:45Z","receivedAt":"2014-02-04T00:54:45Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Feb 4, 2014 at 1:11 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Jeff King <peff@peff.net> writes:\n>\n>> [1] I _do_ use \"reset -p\" when splitting commits, but I do not think it\n>>     is useful here. I use it for \"oops, I staged this change, but it\n>>     actually belongs in the next commit. Undo my staging, but leave the\n>>     changes in the working tree for the next one\".\n>\n> Sure.  I thought that was exactly what Duy was attempting to do when\n> he splitted a commit into two (or more).\n\nFor splitting into two commits, \"reset -p\" or \"reset @^; add -p\" would\nbe more or less the same, although I still prefer to think \"this is\nwhat I need\" than \"this is what I do _not_ need\". \"add -p\" is more\nconvenient when the commit is big and you need to split into more than\ntwo because the number of revert chunks may be higher than the number\nof added chunks. I recall editing a patch with \"checkout -p\" sometimes\ndoes not work, not sure it happens with \"reset -p\" too.\n-- \nDuy\n"},{"id":"234182","messageId":"1391480409-25727-1-git-send-email-pclouds@gmail.com","threadId":"35780","inReplyTo":"CACsJy8BXGZ+1Oqrpcky5JPCtZRwvxmxhXGfuEqY9Ct4Pt8FmJg@mail.gmail.com","subject":"[PATCH 1/2] t7101, t7014: rename test files to indicate what that file is for","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2014-02-04T02:20:08Z","receivedAt":"2014-02-04T02:20:08Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Looks like a good thing to do.. Three files with the same \"-reset.sh\"\n suffix could be confusing.\n\n t/t7101-reset-empty-subdirs.sh (new +x) | 63 +++++++++++++++++++++++++++++++++\n t/t7101-reset.sh (gone)                 | 63 ---------------------------------\n t/t7104-reset-hard.sh (new +x)          | 46 ++++++++++++++++++++++++\n t/t7104-reset.sh (gone)                 | 46 ------------------------\n 4 files changed, 109 insertions(+), 109 deletions(-)\n create mode 100755 t/t7101-reset-empty-subdirs.sh\n delete mode 100755 t/t7101-reset.sh\n create mode 100755 t/t7104-reset-hard.sh\n delete mode 100755 t/t7104-reset.sh\n\ndiff --git a/t/t7101-reset-empty-subdirs.sh b/t/t7101-reset-empty-subdirs.sh\nnew file mode 100755\nindex 0000000..96e163f\n--- /dev/null\n+++ b/t/t7101-reset-empty-subdirs.sh\n@@ -0,0 +1,63 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2006 Shawn Pearce\n+#\n+\n+test_description='git reset should cull empty subdirs'\n+. ./test-lib.sh\n+\n+test_expect_success \\\n+    'creating initial files' \\\n+    'mkdir path0 &&\n+     cp \"$TEST_DIRECTORY\"/../COPYING path0/COPYING &&\n+     git add path0/COPYING &&\n+     git commit -m add -a'\n+\n+test_expect_success \\\n+    'creating second files' \\\n+    'mkdir path1 &&\n+     mkdir path1/path2 &&\n+     cp \"$TEST_DIRECTORY\"/../COPYING path1/path2/COPYING &&\n+     cp \"$TEST_DIRECTORY\"/../COPYING path1/COPYING &&\n+     cp \"$TEST_DIRECTORY\"/../COPYING COPYING &&\n+     cp \"$TEST_DIRECTORY\"/../COPYING path0/COPYING-TOO &&\n+     git add path1/path2/COPYING &&\n+     git add path1/COPYING &&\n+     git add COPYING &&\n+     git add path0/COPYING-TOO &&\n+     git commit -m change -a'\n+\n+test_expect_success \\\n+    'resetting tree HEAD^' \\\n+    'git reset --hard HEAD^'\n+\n+test_expect_success \\\n+    'checking initial files exist after rewind' \\\n+    'test -d path0 &&\n+     test -f path0/COPYING'\n+\n+test_expect_success \\\n+    'checking lack of path1/path2/COPYING' \\\n+    '! test -f path1/path2/COPYING'\n+\n+test_expect_success \\\n+    'checking lack of path1/COPYING' \\\n+    '! test -f path1/COPYING'\n+\n+test_expect_success \\\n+    'checking lack of COPYING' \\\n+    '! test -f COPYING'\n+\n+test_expect_success \\\n+    'checking checking lack of path1/COPYING-TOO' \\\n+    '! test -f path0/COPYING-TOO'\n+\n+test_expect_success \\\n+    'checking lack of path1/path2' \\\n+    '! test -d path1/path2'\n+\n+test_expect_success \\\n+    'checking lack of path1' \\\n+    '! test -d path1'\n+\n+test_done\ndiff --git a/t/t7101-reset.sh b/t/t7101-reset.sh\ndeleted file mode 100755\nindex 96e163f..0000000\n--- a/t/t7101-reset.sh\n+++ /dev/null\n@@ -1,63 +0,0 @@\n-#!/bin/sh\n-#\n-# Copyright (c) 2006 Shawn Pearce\n-#\n-\n-test_description='git reset should cull empty subdirs'\n-. ./test-lib.sh\n-\n-test_expect_success \\\n-    'creating initial files' \\\n-    'mkdir path0 &&\n-     cp \"$TEST_DIRECTORY\"/../COPYING path0/COPYING &&\n-     git add path0/COPYING &&\n-     git commit -m add -a'\n-\n-test_expect_success \\\n-    'creating second files' \\\n-    'mkdir path1 &&\n-     mkdir path1/path2 &&\n-     cp \"$TEST_DIRECTORY\"/../COPYING path1/path2/COPYING &&\n-     cp \"$TEST_DIRECTORY\"/../COPYING path1/COPYING &&\n-     cp \"$TEST_DIRECTORY\"/../COPYING COPYING &&\n-     cp \"$TEST_DIRECTORY\"/../COPYING path0/COPYING-TOO &&\n-     git add path1/path2/COPYING &&\n-     git add path1/COPYING &&\n-     git add COPYING &&\n-     git add path0/COPYING-TOO &&\n-     git commit -m change -a'\n-\n-test_expect_success \\\n-    'resetting tree HEAD^' \\\n-    'git reset --hard HEAD^'\n-\n-test_expect_success \\\n-    'checking initial files exist after rewind' \\\n-    'test -d path0 &&\n-     test -f path0/COPYING'\n-\n-test_expect_success \\\n-    'checking lack of path1/path2/COPYING' \\\n-    '! test -f path1/path2/COPYING'\n-\n-test_expect_success \\\n-    'checking lack of path1/COPYING' \\\n-    '! test -f path1/COPYING'\n-\n-test_expect_success \\\n-    'checking lack of COPYING' \\\n-    '! test -f COPYING'\n-\n-test_expect_success \\\n-    'checking checking lack of path1/COPYING-TOO' \\\n-    '! test -f path0/COPYING-TOO'\n-\n-test_expect_success \\\n-    'checking lack of path1/path2' \\\n-    '! test -d path1/path2'\n-\n-test_expect_success \\\n-    'checking lack of path1' \\\n-    '! test -d path1'\n-\n-test_done\ndiff --git a/t/t7104-reset-hard.sh b/t/t7104-reset-hard.sh\nnew file mode 100755\nindex 0000000..f136ee7\n--- /dev/null\n+++ b/t/t7104-reset-hard.sh\n@@ -0,0 +1,46 @@\n+#!/bin/sh\n+\n+test_description='reset --hard unmerged'\n+\n+. ./test-lib.sh\n+\n+test_expect_success setup '\n+\n+\tmkdir before later &&\n+\t>before/1 &&\n+\t>before/2 &&\n+\t>hello &&\n+\t>later/3 &&\n+\tgit add before hello later &&\n+\tgit commit -m world &&\n+\n+\tH=$(git rev-parse :hello) &&\n+\tgit rm --cached hello &&\n+\techo \"100644 $H 2\thello\" | git update-index --index-info &&\n+\n+\trm -f hello &&\n+\tmkdir -p hello &&\n+\t>hello/world &&\n+\ttest \"$(git ls-files -o)\" = hello/world\n+\n+'\n+\n+test_expect_success 'reset --hard should restore unmerged ones' '\n+\n+\tgit reset --hard &&\n+\tgit ls-files --error-unmatch before/1 before/2 hello later/3 &&\n+\ttest -f hello\n+\n+'\n+\n+test_expect_success 'reset --hard did not corrupt index nor cached-tree' '\n+\n+\tT=$(git write-tree) &&\n+\trm -f .git/index &&\n+\tgit add before hello later &&\n+\tU=$(git write-tree) &&\n+\ttest \"$T\" = \"$U\"\n+\n+'\n+\n+test_done\ndiff --git a/t/t7104-reset.sh b/t/t7104-reset.sh\ndeleted file mode 100755\nindex f136ee7..0000000\n--- a/t/t7104-reset.sh\n+++ /dev/null\n@@ -1,46 +0,0 @@\n-#!/bin/sh\n-\n-test_description='reset --hard unmerged'\n-\n-. ./test-lib.sh\n-\n-test_expect_success setup '\n-\n-\tmkdir before later &&\n-\t>before/1 &&\n-\t>before/2 &&\n-\t>hello &&\n-\t>later/3 &&\n-\tgit add before hello later &&\n-\tgit commit -m world &&\n-\n-\tH=$(git rev-parse :hello) &&\n-\tgit rm --cached hello &&\n-\techo \"100644 $H 2\thello\" | git update-index --index-info &&\n-\n-\trm -f hello &&\n-\tmkdir -p hello &&\n-\t>hello/world &&\n-\ttest \"$(git ls-files -o)\" = hello/world\n-\n-'\n-\n-test_expect_success 'reset --hard should restore unmerged ones' '\n-\n-\tgit reset --hard &&\n-\tgit ls-files --error-unmatch before/1 before/2 hello later/3 &&\n-\ttest -f hello\n-\n-'\n-\n-test_expect_success 'reset --hard did not corrupt index nor cached-tree' '\n-\n-\tT=$(git write-tree) &&\n-\trm -f .git/index &&\n-\tgit add before hello later &&\n-\tU=$(git write-tree) &&\n-\ttest \"$T\" = \"$U\"\n-\n-'\n-\n-test_done\n-- \n1.8.5.2.240.g8478abd\n"},{"id":"234183","messageId":"1391480409-25727-2-git-send-email-pclouds@gmail.com","threadId":"35780","inReplyTo":"1391480409-25727-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 2/2] reset: support \"--mixed --intent-to-add\" mode","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2014-02-04T02:20:09Z","receivedAt":"2014-02-04T02:20:09Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"When --mixed is used, entries could be removed from index if the\ntarget ref does not have them. When \"reset\" is used in preparation for\ncommit spliting (in a dirty worktree), it could be hard to track what\nfiles to be added back. The new option --intent-to-add simplifies it\nby marking all removed files intent-to-add.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/git-reset.txt |  5 ++++-\n builtin/reset.c             | 19 +++++++++++++++++--\n cache.h                     |  1 +\n read-cache.c                |  9 +++++++++\n t/t7102-reset.sh            |  9 +++++++++\n 5 files changed, 40 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt\nindex f445cb3..a077ba0 100644\n--- a/Documentation/git-reset.txt\n+++ b/Documentation/git-reset.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n [verse]\n 'git reset' [-q] [<tree-ish>] [--] <paths>...\n 'git reset' (--patch | -p) [<tree-ish>] [--] [<paths>...]\n-'git reset' [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]\n+'git reset' [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]\n \n DESCRIPTION\n -----------\n@@ -60,6 +60,9 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode.\n \tResets the index but not the working tree (i.e., the changed files\n \tare preserved but not marked for commit) and reports what has not\n \tbeen updated. This is the default action.\n++\n+If `-N` is specified, removed paths are marked as intent-to-add (see\n+linkgit:git-add[1]).\n \n --hard::\n \tResets the index and working tree. Any changes to tracked files in the\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex 6004803..f34eab4 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -116,6 +116,7 @@ static void update_index_from_diff(struct diff_queue_struct *q,\n \t\tstruct diff_options *opt, void *data)\n {\n \tint i;\n+\tint *intent_to_add = data;\n \n \tfor (i = 0; i < q->nr; i++) {\n \t\tstruct diff_filespec *one = q->queue[i]->one;\n@@ -128,13 +129,20 @@ static void update_index_from_diff(struct diff_queue_struct *q,\n \t\t\t\t    one->path);\n \t\t\tadd_cache_entry(ce, ADD_CACHE_OK_TO_ADD |\n \t\t\t\tADD_CACHE_OK_TO_REPLACE);\n+\t\t} else if (*intent_to_add) {\n+\t\t\tint pos = cache_name_pos(one->path, strlen(one->path));\n+\t\t\tif (pos < 0)\n+\t\t\t\tdie(_(\"%s does not exist in index\"),\n+\t\t\t\t    one->path);\n+\t\t\tset_intent_to_add(&the_index, active_cache[pos]);\n \t\t} else\n \t\t\tremove_file_from_cache(one->path);\n \t}\n }\n \n static int read_from_tree(const struct pathspec *pathspec,\n-\t\t\t  unsigned char *tree_sha1)\n+\t\t\t  unsigned char *tree_sha1,\n+\t\t\t  int intent_to_add)\n {\n \tstruct diff_options opt;\n \n@@ -142,6 +150,7 @@ static int read_from_tree(const struct pathspec *pathspec,\n \tcopy_pathspec(&opt.pathspec, pathspec);\n \topt.output_format = DIFF_FORMAT_CALLBACK;\n \topt.format_callback = update_index_from_diff;\n+\topt.format_callback_data = &intent_to_add;\n \n \tif (do_diff_cache(tree_sha1, &opt))\n \t\treturn 1;\n@@ -258,6 +267,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \tconst char *rev;\n \tunsigned char sha1[20];\n \tstruct pathspec pathspec;\n+\tint intent_to_add = 0;\n \tconst struct option options[] = {\n \t\tOPT__QUIET(&quiet, N_(\"be quiet, only report errors\")),\n \t\tOPT_SET_INT(0, \"mixed\", &reset_type,\n@@ -270,6 +280,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\tOPT_SET_INT(0, \"keep\", &reset_type,\n \t\t\t\tN_(\"reset HEAD but keep local changes\"), KEEP),\n \t\tOPT_BOOL('p', \"patch\", &patch_mode, N_(\"select hunks interactively\")),\n+\t\tOPT_BOOL('N', \"intent-to-add\", &intent_to_add,\n+\t\t\t\tN_(\"record only the fact that removed paths will be added later\")),\n \t\tOPT_END()\n \t};\n \n@@ -327,6 +339,9 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\tdie(_(\"%s reset is not allowed in a bare repository\"),\n \t\t    _(reset_type_names[reset_type]));\n \n+\tif (intent_to_add && reset_type != MIXED)\n+\t\tdie(_(\"-N can only be used with --mixed\"));\n+\n \t/* Soft reset does not touch the index file nor the working tree\n \t * at all, but requires them in a good order.  Other resets reset\n \t * the index file to the tree object we are switching to. */\n@@ -338,7 +353,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\tint newfd = hold_locked_index(lock, 1);\n \t\tif (reset_type == MIXED) {\n \t\t\tint flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;\n-\t\t\tif (read_from_tree(&pathspec, sha1))\n+\t\t\tif (read_from_tree(&pathspec, sha1, intent_to_add))\n \t\t\t\treturn 1;\n \t\t\trefresh_index(&the_index, flags, NULL, NULL,\n \t\t\t\t      _(\"Unstaged changes after reset:\"));\ndiff --git a/cache.h b/cache.h\nindex dc040fb..9d5e09e 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -479,6 +479,7 @@ extern void rename_index_entry_at(struct index_state *, int pos, const char *new\n extern int remove_index_entry_at(struct index_state *, int pos);\n extern void remove_marked_cache_entries(struct index_state *istate);\n extern int remove_file_from_index(struct index_state *, const char *path);\n+extern int set_intent_to_add(struct index_state *, struct cache_entry *);\n #define ADD_CACHE_VERBOSE 1\n #define ADD_CACHE_PRETEND 2\n #define ADD_CACHE_IGNORE_ERRORS\t4\ndiff --git a/read-cache.c b/read-cache.c\nindex 33dd676..dc160a3 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -587,6 +587,15 @@ static void record_intent_to_add(struct cache_entry *ce)\n \thashcpy(ce->sha1, sha1);\n }\n \n+int set_intent_to_add(struct index_state *istate, struct cache_entry *ce)\n+{\n+\trecord_intent_to_add(ce);\n+\tce->ce_flags |= CE_INTENT_TO_ADD;\n+\tcache_tree_invalidate_path(istate->cache_tree, ce->name);\n+\tistate->cache_changed = 1;\n+\treturn 0;\n+}\n+\n int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)\n {\n \tint size, namelen, was_same;\ndiff --git a/t/t7102-reset.sh b/t/t7102-reset.sh\nindex 8d4b50d..642920a 100755\n--- a/t/t7102-reset.sh\n+++ b/t/t7102-reset.sh\n@@ -535,4 +535,13 @@ test_expect_success 'reset with paths accepts tree' '\n \tgit diff HEAD --exit-code\n '\n \n+test_expect_success 'reset -N keeps removed files as intent-to-add' '\n+\techo new-file >new-file &&\n+\tgit add new-file &&\n+\tgit reset -N HEAD &&\n+\tgit diff --name-only >actual &&\n+\techo new-file >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n1.8.5.2.240.g8478abd\n"},{"id":"234205","messageId":"20140204160523.GK30398@google.com","threadId":"35780","inReplyTo":"1391480409-25727-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 1/2] t7101, t7014: rename test files to indicate what that file is for","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2014-02-04T16:05:23Z","receivedAt":"2014-02-04T16:05:23Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Nguyễn Thái Ngọc Duy wrote:\n\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n\nMakes sense.\n\n[...]\n>  t/t7101-reset-empty-subdirs.sh (new +x) | 63 +++++++++++++++++++++++++++++++++\n>  t/t7101-reset.sh (gone)                 | 63 ---------------------------------\n>  t/t7104-reset-hard.sh (new +x)          | 46 ++++++++++++++++++++++++\n>  t/t7104-reset.sh (gone)                 | 46 ------------------------\n\nHm, summary incorporated in the diffstat.  Neat. :)\n\nformat-patch -M tells me that this indeed just renamed the files, so\nfwiw\n\nReviewed-by: Jonathan Nieder <jrnieder@gmail.com>\n"},{"id":"234215","messageId":"xmqqvbwu8zjx.fsf@gitster.dls.corp.google.com","threadId":"35780","inReplyTo":"1391480409-25727-2-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 2/2] reset: support \"--mixed --intent-to-add\" mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-02-04T19:09:54Z","receivedAt":"2014-02-04T19:09:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> @@ -128,13 +129,20 @@ static void update_index_from_diff(struct diff_queue_struct *q,\n>  \t\t\t\t    one->path);\n>  \t\t\tadd_cache_entry(ce, ADD_CACHE_OK_TO_ADD |\n>  \t\t\t\tADD_CACHE_OK_TO_REPLACE);\n> +\t\t} else if (*intent_to_add) {\n> +\t\t\tint pos = cache_name_pos(one->path, strlen(one->path));\n> +\t\t\tif (pos < 0)\n> +\t\t\t\tdie(_(\"%s does not exist in index\"),\n> +\t\t\t\t    one->path);\n> +\t\t\tset_intent_to_add(&the_index, active_cache[pos]);\n\nWhile I do not have any problem with adding an optional \"keep lost\npaths as intent-to-add entries\" feature, I am not sure why this has\nto be so different from the usual add-cache-entry codepath.  The\nif/elseif chain you are touching inside this loop does:\n\n - If the tree you are resetting to has something at the path\n   (which is different from the current index, obviously), create\n   a cache entry to represent that state from the tree and stuff\n   it in the index;\n\n - Otherwise, the tree you are resetting to does not have that\n   path.  We used to say \"remove it from the index\", but now we have\n   an option to instead add it as an intent-to-add entry.\n\nSo, why doesn't the new codepath do exactly the same thing as the\nfirst branch of the if/else chain and call add_cache_entry but with\na ce marked with CE_INTENT_TO_ADD?  That would parallel what happens\nin \"git add -N\" better, I would think, no?\n"},{"id":"234252","messageId":"xmqqeh3i7bxm.fsf@gitster.dls.corp.google.com","threadId":"35780","inReplyTo":"xmqqvbwu8zjx.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH 2/2] reset: support \"--mixed --intent-to-add\" mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-02-04T22:25:25Z","receivedAt":"2014-02-04T22:25:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> While I do not have any problem with adding an optional \"keep lost\n> paths as intent-to-add entries\" feature, I am not sure why this has\n> to be so different from the usual add-cache-entry codepath.  The\n> if/elseif chain you are touching inside this loop does:\n>\n>  - If the tree you are resetting to has something at the path\n>    (which is different from the current index, obviously), create\n>    a cache entry to represent that state from the tree and stuff\n>    it in the index;\n>\n>  - Otherwise, the tree you are resetting to does not have that\n>    path.  We used to say \"remove it from the index\", but now we have\n>    an option to instead add it as an intent-to-add entry.\n>\n> So, why doesn't the new codepath do exactly the same thing as the\n> first branch of the if/else chain and call add_cache_entry but with\n> a ce marked with CE_INTENT_TO_ADD?  That would parallel what happens\n> in \"git add -N\" better, I would think, no?\n\nIn other words, something along this line, perhaps?\n\n-- >8 --\nFrom: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nDate: Tue, 4 Feb 2014 09:20:09 +0700\n\nWhen --mixed is used, entries could be removed from index if the\ntarget ref does not have them. When \"reset\" is used in preparation for\ncommit spliting (in a dirty worktree), it could be hard to track what\nfiles to be added back. The new option --intent-to-add simplifies it\nby marking all removed files intent-to-add.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/git-reset.txt |  5 ++++-\n builtin/reset.c             | 38 ++++++++++++++++++++++++++------------\n cache.h                     |  1 +\n read-cache.c                |  4 ++--\n t/t7102-reset.sh            |  9 +++++++++\n 5 files changed, 42 insertions(+), 15 deletions(-)\n\ndiff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt\nindex f445cb3..a077ba0 100644\n--- a/Documentation/git-reset.txt\n+++ b/Documentation/git-reset.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n [verse]\n 'git reset' [-q] [<tree-ish>] [--] <paths>...\n 'git reset' (--patch | -p) [<tree-ish>] [--] [<paths>...]\n-'git reset' [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]\n+'git reset' [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]\n \n DESCRIPTION\n -----------\n@@ -60,6 +60,9 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode.\n \tResets the index but not the working tree (i.e., the changed files\n \tare preserved but not marked for commit) and reports what has not\n \tbeen updated. This is the default action.\n++\n+If `-N` is specified, removed paths are marked as intent-to-add (see\n+linkgit:git-add[1]).\n \n --hard::\n \tResets the index and working tree. Any changes to tracked files in the\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex 6004803..d363bc5 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -116,25 +116,32 @@ static void update_index_from_diff(struct diff_queue_struct *q,\n \t\tstruct diff_options *opt, void *data)\n {\n \tint i;\n+\tint intent_to_add = *(int *)data;\n \n \tfor (i = 0; i < q->nr; i++) {\n \t\tstruct diff_filespec *one = q->queue[i]->one;\n-\t\tif (one->mode && !is_null_sha1(one->sha1)) {\n-\t\t\tstruct cache_entry *ce;\n-\t\t\tce = make_cache_entry(one->mode, one->sha1, one->path,\n-\t\t\t\t0, 0);\n-\t\t\tif (!ce)\n-\t\t\t\tdie(_(\"make_cache_entry failed for path '%s'\"),\n-\t\t\t\t    one->path);\n-\t\t\tadd_cache_entry(ce, ADD_CACHE_OK_TO_ADD |\n-\t\t\t\tADD_CACHE_OK_TO_REPLACE);\n-\t\t} else\n+\t\tint is_missing = !(one->mode && !is_null_sha1(one->sha1));\n+\t\tstruct cache_entry *ce;\n+\n+\t\tif (is_missing && !intent_to_add) {\n \t\t\tremove_file_from_cache(one->path);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tce = make_cache_entry(one->mode, one->sha1, one->path,\n+\t\t\t\t      0, 0);\n+\t\tif (!ce)\n+\t\t\tdie(_(\"make_cache_entry failed for path '%s'\"),\n+\t\t\t    one->path);\n+\t\tif (is_missing)\n+\t\t\tmark_intent_to_add(ce);\n+\t\tadd_cache_entry(ce, ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);\n \t}\n }\n \n static int read_from_tree(const struct pathspec *pathspec,\n-\t\t\t  unsigned char *tree_sha1)\n+\t\t\t  unsigned char *tree_sha1,\n+\t\t\t  int intent_to_add)\n {\n \tstruct diff_options opt;\n \n@@ -142,6 +149,7 @@ static int read_from_tree(const struct pathspec *pathspec,\n \tcopy_pathspec(&opt.pathspec, pathspec);\n \topt.output_format = DIFF_FORMAT_CALLBACK;\n \topt.format_callback = update_index_from_diff;\n+\topt.format_callback_data = &intent_to_add;\n \n \tif (do_diff_cache(tree_sha1, &opt))\n \t\treturn 1;\n@@ -258,6 +266,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \tconst char *rev;\n \tunsigned char sha1[20];\n \tstruct pathspec pathspec;\n+\tint intent_to_add = 0;\n \tconst struct option options[] = {\n \t\tOPT__QUIET(&quiet, N_(\"be quiet, only report errors\")),\n \t\tOPT_SET_INT(0, \"mixed\", &reset_type,\n@@ -270,6 +279,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\tOPT_SET_INT(0, \"keep\", &reset_type,\n \t\t\t\tN_(\"reset HEAD but keep local changes\"), KEEP),\n \t\tOPT_BOOL('p', \"patch\", &patch_mode, N_(\"select hunks interactively\")),\n+\t\tOPT_BOOL('N', \"intent-to-add\", &intent_to_add,\n+\t\t\t\tN_(\"record only the fact that removed paths will be added later\")),\n \t\tOPT_END()\n \t};\n \n@@ -327,6 +338,9 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\tdie(_(\"%s reset is not allowed in a bare repository\"),\n \t\t    _(reset_type_names[reset_type]));\n \n+\tif (intent_to_add && reset_type != MIXED)\n+\t\tdie(_(\"-N can only be used with --mixed\"));\n+\n \t/* Soft reset does not touch the index file nor the working tree\n \t * at all, but requires them in a good order.  Other resets reset\n \t * the index file to the tree object we are switching to. */\n@@ -338,7 +352,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\tint newfd = hold_locked_index(lock, 1);\n \t\tif (reset_type == MIXED) {\n \t\t\tint flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;\n-\t\t\tif (read_from_tree(&pathspec, sha1))\n+\t\t\tif (read_from_tree(&pathspec, sha1, intent_to_add))\n \t\t\t\treturn 1;\n \t\t\trefresh_index(&the_index, flags, NULL, NULL,\n \t\t\t\t      _(\"Unstaged changes after reset:\"));\ndiff --git a/cache.h b/cache.h\nindex dc040fb..20aa73f 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -489,6 +489,7 @@ extern int add_to_index(struct index_state *, const char *path, struct stat *, i\n extern int add_file_to_index(struct index_state *, const char *path, int flags);\n extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);\n extern int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);\n+extern void mark_intent_to_add(struct cache_entry *ce);\n extern int index_name_is_other(const struct index_state *, const char *, int);\n extern void *read_blob_data_from_index(struct index_state *, const char *, unsigned long *);\n \ndiff --git a/read-cache.c b/read-cache.c\nindex 33dd676..325d193 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -579,7 +579,7 @@ static struct cache_entry *create_alias_ce(struct cache_entry *ce, struct cache_\n \treturn new;\n }\n \n-static void record_intent_to_add(struct cache_entry *ce)\n+void mark_intent_to_add(struct cache_entry *ce)\n {\n \tunsigned char sha1[20];\n \tif (write_sha1_file(\"\", 0, blob_type, sha1))\n@@ -665,7 +665,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \t\tif (index_path(ce->sha1, path, st, HASH_WRITE_OBJECT))\n \t\t\treturn error(\"unable to index file %s\", path);\n \t} else\n-\t\trecord_intent_to_add(ce);\n+\t\tmark_intent_to_add(ce);\n \n \tif (ignore_case && alias && different_name(ce, alias))\n \t\tce = create_alias_ce(ce, alias);\ndiff --git a/t/t7102-reset.sh b/t/t7102-reset.sh\nindex 8d4b50d..642920a 100755\n--- a/t/t7102-reset.sh\n+++ b/t/t7102-reset.sh\n@@ -535,4 +535,13 @@ test_expect_success 'reset with paths accepts tree' '\n \tgit diff HEAD --exit-code\n '\n \n+test_expect_success 'reset -N keeps removed files as intent-to-add' '\n+\techo new-file >new-file &&\n+\tgit add new-file &&\n+\tgit reset -N HEAD &&\n+\tgit diff --name-only >actual &&\n+\techo new-file >expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n1.9-rc2-217-g24a8b2e\n"},{"id":"234263","messageId":"20140205002725.GA3858@lanh","threadId":"35780","inReplyTo":"xmqqeh3i7bxm.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH 2/2] reset: support \"--mixed --intent-to-add\" mode","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2014-02-05T00:27:26Z","receivedAt":"2014-02-05T00:27:26Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Feb 04, 2014 at 02:25:25PM -0800, Junio C Hamano wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n> \n> > While I do not have any problem with adding an optional \"keep lost\n> > paths as intent-to-add entries\" feature, I am not sure why this has\n> > to be so different from the usual add-cache-entry codepath.  The\n> > if/elseif chain you are touching inside this loop does:\n> >\n> >  - If the tree you are resetting to has something at the path\n> >    (which is different from the current index, obviously), create\n> >    a cache entry to represent that state from the tree and stuff\n> >    it in the index;\n> >\n> >  - Otherwise, the tree you are resetting to does not have that\n> >    path.  We used to say \"remove it from the index\", but now we have\n> >    an option to instead add it as an intent-to-add entry.\n> >\n> > So, why doesn't the new codepath do exactly the same thing as the\n> > first branch of the if/else chain and call add_cache_entry but with\n> > a ce marked with CE_INTENT_TO_ADD?  That would parallel what happens\n> > in \"git add -N\" better, I would think, no?\n> \n> In other words, something along this line, perhaps?\n\n<snip>\n\nYes. But you need something like this on top to actually set\nCE_INTENT_TO_ADD\n\n-- 8< --\ndiff --git a/read-cache.c b/read-cache.c\nindex 325d193..87f1367 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -585,6 +585,7 @@ void mark_intent_to_add(struct cache_entry *ce)\n \tif (write_sha1_file(\"\", 0, blob_type, sha1))\n \t\tdie(\"cannot create an empty blob in the object database\");\n \thashcpy(ce->sha1, sha1);\n+\tce->ce_flags |= CE_INTENT_TO_ADD;\n }\n \n int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)\n-- 8< --\n"},{"id":"234286","messageId":"xmqqob2l5vl2.fsf@gitster.dls.corp.google.com","threadId":"35780","inReplyTo":"20140205002725.GA3858@lanh","subject":"Re: [PATCH 2/2] reset: support \"--mixed --intent-to-add\" mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-02-05T17:16:09Z","receivedAt":"2014-02-05T17:16:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> On Tue, Feb 04, 2014 at 02:25:25PM -0800, Junio C Hamano wrote:\n>> Junio C Hamano <gitster@pobox.com> writes:\n>> \n>> > While I do not have any problem with adding an optional \"keep lost\n>> > paths as intent-to-add entries\" feature, I am not sure why this has\n>> > to be so different from the usual add-cache-entry codepath.  The\n>> > if/elseif chain you are touching inside this loop does:\n>> >\n>> >  - If the tree you are resetting to has something at the path\n>> >    (which is different from the current index, obviously), create\n>> >    a cache entry to represent that state from the tree and stuff\n>> >    it in the index;\n>> >\n>> >  - Otherwise, the tree you are resetting to does not have that\n>> >    path.  We used to say \"remove it from the index\", but now we have\n>> >    an option to instead add it as an intent-to-add entry.\n>> >\n>> > So, why doesn't the new codepath do exactly the same thing as the\n>> > first branch of the if/else chain and call add_cache_entry but with\n>> > a ce marked with CE_INTENT_TO_ADD?  That would parallel what happens\n>> > in \"git add -N\" better, I would think, no?\n>> \n>> In other words, something along this line, perhaps?\n>\n> <snip>\n>\n> Yes. But you need something like this on top to actually set\n> CE_INTENT_TO_ADD\n\nYes, indeed.  I wonder why your new test did not notice it, though\n;-)\n\n\n>\n> -- 8< --\n> diff --git a/read-cache.c b/read-cache.c\n> index 325d193..87f1367 100644\n> --- a/read-cache.c\n> +++ b/read-cache.c\n> @@ -585,6 +585,7 @@ void mark_intent_to_add(struct cache_entry *ce)\n>  \tif (write_sha1_file(\"\", 0, blob_type, sha1))\n>  \t\tdie(\"cannot create an empty blob in the object database\");\n>  \thashcpy(ce->sha1, sha1);\n> +\tce->ce_flags |= CE_INTENT_TO_ADD;\n>  }\n>  \n>  int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)\n> -- 8< --\n"},{"id":"234308","messageId":"xmqqbnyl5sde.fsf@gitster.dls.corp.google.com","threadId":"35780","inReplyTo":"xmqqob2l5vl2.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH 2/2] reset: support \"--mixed --intent-to-add\" mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-02-05T18:25:33Z","receivedAt":"2014-02-05T18:25:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Duy Nguyen <pclouds@gmail.com> writes:\n>\n>> On Tue, Feb 04, 2014 at 02:25:25PM -0800, Junio C Hamano wrote:\n>>> Junio C Hamano <gitster@pobox.com> writes:\n>>> \n>>> > While I do not have any problem with adding an optional \"keep lost\n>>> > paths as intent-to-add entries\" feature, I am not sure why this has\n>>> > to be so different from the usual add-cache-entry codepath.  The\n>>> > if/elseif chain you are touching inside this loop does:\n>>> >\n>>> >  - If the tree you are resetting to has something at the path\n>>> >    (which is different from the current index, obviously), create\n>>> >    a cache entry to represent that state from the tree and stuff\n>>> >    it in the index;\n>>> >\n>>> >  - Otherwise, the tree you are resetting to does not have that\n>>> >    path.  We used to say \"remove it from the index\", but now we have\n>>> >    an option to instead add it as an intent-to-add entry.\n>>> >\n>>> > So, why doesn't the new codepath do exactly the same thing as the\n>>> > first branch of the if/else chain and call add_cache_entry but with\n>>> > a ce marked with CE_INTENT_TO_ADD?  That would parallel what happens\n>>> > in \"git add -N\" better, I would think, no?\n>>> \n>>> In other words, something along this line, perhaps?\n>>\n>> <snip>\n>>\n>> Yes. But you need something like this on top to actually set\n>> CE_INTENT_TO_ADD\n>\n> Yes, indeed.  I wonder why your new test did not notice it, though\n> ;-)\n\n... and the answer turns out to be that it was not testing the right\nthing.  On top of that faulty version, this will fix it.\n\nYour suggestion to move CE_INTENT_TO_ADD to mark-intent-to-add makes\nsense but a caller needs to be adjusted to drop the duplicated flag\nmanipulation.\n\n read-cache.c     | 3 +--\n t/t7102-reset.sh | 6 ++++++\n 2 files changed, 7 insertions(+), 2 deletions(-)\n\ndiff --git a/read-cache.c b/read-cache.c\nindex 325d193..5b8102a 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -584,6 +584,7 @@ void mark_intent_to_add(struct cache_entry *ce)\n \tunsigned char sha1[20];\n \tif (write_sha1_file(\"\", 0, blob_type, sha1))\n \t\tdie(\"cannot create an empty blob in the object database\");\n+\tce->ce_flags |= CE_INTENT_TO_ADD;\n \thashcpy(ce->sha1, sha1);\n }\n \n@@ -613,8 +614,6 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \tce->ce_namelen = namelen;\n \tif (!intent_only)\n \t\tfill_stat_cache_info(ce, st);\n-\telse\n-\t\tce->ce_flags |= CE_INTENT_TO_ADD;\n \n \tif (trust_executable_bit && has_symlinks)\n \t\tce->ce_mode = create_ce_mode(st_mode);\ndiff --git a/t/t7102-reset.sh b/t/t7102-reset.sh\nindex 642920a..bc0846f 100755\n--- a/t/t7102-reset.sh\n+++ b/t/t7102-reset.sh\n@@ -539,6 +539,12 @@ test_expect_success 'reset -N keeps removed files as intent-to-add' '\n \techo new-file >new-file &&\n \tgit add new-file &&\n \tgit reset -N HEAD &&\n+\n+\ttree=$(git write-tree) &&\n+\tgit ls-tree $tree new-file >actual &&\n+\t>expect &&\n+\ttest_cmp expect actual &&\n+\n \tgit diff --name-only >actual &&\n \techo new-file >expect &&\n \ttest_cmp expect actual\n"},{"id":"234351","messageId":"CACsJy8Aj-5MzRjDxfWkOVtqxjo+w7v6uEjGfGAj_9s59t5eiYA@mail.gmail.com","threadId":"35780","inReplyTo":"xmqqbnyl5sde.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH 2/2] reset: support \"--mixed --intent-to-add\" mode","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2014-02-05T23:48:45Z","receivedAt":"2014-02-05T23:48:45Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Feb 6, 2014 at 1:25 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Yes, indeed.  I wonder why your new test did not notice it, though\n>> ;-)\n>\n> ... and the answer turns out to be that it was not testing the right\n> thing.  On top of that faulty version, this will fix it.\n\nYes, write-tree should test that well.\n\n> Your suggestion to move CE_INTENT_TO_ADD to mark-intent-to-add makes\n> sense but a caller needs to be adjusted to drop the duplicated flag\n> manipulation.\n\nNo no. I found that duplicate, but I did not suggest removing it\nbecause it is needed there..\n\n> @@ -613,8 +614,6 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n>         ce->ce_namelen = namelen;\n>         if (!intent_only)\n>                 fill_stat_cache_info(ce, st);\n> -       else\n> -               ce->ce_flags |= CE_INTENT_TO_ADD;\n>\n>         if (trust_executable_bit && has_symlinks)\n>                 ce->ce_mode = create_ce_mode(st_mode);\n\nA few lines down, there's ie_match_stat() call that will check\nCE_INTENT_TO_ADD and returns \"changed\" immediately without looking at\nstat data. If stat info is used, it may (not so sure) return \"not\nchanged\", the exit path is taken and mark_intent_to_add() is ignored.\n-- \nDuy\n"},{"id":"234352","messageId":"CAPc5daXvBPTVCUv=qO++kiOMQck1daTc_rmhpWrDk-KbTuvZOQ@mail.gmail.com","threadId":"35780","inReplyTo":"CACsJy8Aj-5MzRjDxfWkOVtqxjo+w7v6uEjGfGAj_9s59t5eiYA@mail.gmail.com","subject":"Re: [PATCH 2/2] reset: support \"--mixed --intent-to-add\" mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-02-06T00:08:15Z","receivedAt":"2014-02-06T00:08:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"On Wed, Feb 5, 2014 at 3:48 PM, Duy Nguyen <pclouds@gmail.com> wrote:\n> No no. I found that duplicate, but I did not suggest removing it\n> because it is needed there..\n\nHmph, if that is the case, we probably should make it the\nresponsibility of the calling side to actually mark ce->flags with the\nbit (which would also mean the function must be renamed to make it\nclear that it does not mark).\n"},{"id":"234354","messageId":"xmqq1tzh135x.fsf@gitster.dls.corp.google.com","threadId":"35780","inReplyTo":"CAPc5daXvBPTVCUv=qO++kiOMQck1daTc_rmhpWrDk-KbTuvZOQ@mail.gmail.com","subject":"Re: [PATCH 2/2] reset: support \"--mixed --intent-to-add\" mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-02-06T00:43:38Z","receivedAt":"2014-02-06T00:43:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> On Wed, Feb 5, 2014 at 3:48 PM, Duy Nguyen <pclouds@gmail.com> wrote:\n>> No no. I found that duplicate, but I did not suggest removing it\n>> because it is needed there..\n>\n> Hmph, if that is the case, we probably should make it the\n> responsibility of the calling side to actually mark ce->flags with the\n> bit (which would also mean the function must be renamed to make it\n> clear that it does not mark).\n\nAfter looking at the codepath that uses the record_intent_to_add()\nbefore this patch, I am coming to the conclusion that it is the\nright thing to do after all.  The code appears in this section:\n\n\tif (!intent_only) {\n\t\tif (index_path(ce->sha1, path, st, HASH_WRITE_OBJECT))\n\t\t\treturn error(\"unable to index file %s\", path);\n\t} else\n\t\trecord_intent_to_add(ce);\n\nwhich tells (at least) me: \"We are not adding the contents of this\npath, so we do not run index_path(); instead we call this helper\nfunction to set the object name in ce to represent an intent-to-add\nentry\".\n\nSo I'll rename it to set_object_name_for_intent_to_add_entry() or\nsomething, restore that flag manipulation back to the caller, and\nadd another to the new caller, and requeue.\n"},{"id":"234355","messageId":"CACsJy8C93H4YW_ZbJaEDgTyr30OXtEP+uiXB_TA9jjWzD6rGqw@mail.gmail.com","threadId":"35780","inReplyTo":"20140204160523.GK30398@google.com","subject":"Re: [PATCH 1/2] t7101, t7014: rename test files to indicate what that file is for","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2014-02-06T01:58:18Z","receivedAt":"2014-02-06T01:58:18Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Feb 4, 2014 at 11:05 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:\n>>  t/t7101-reset-empty-subdirs.sh (new +x) | 63 +++++++++++++++++++++++++++++++++\n>>  t/t7101-reset.sh (gone)                 | 63 ---------------------------------\n>>  t/t7104-reset-hard.sh (new +x)          | 46 ++++++++++++++++++++++++\n>>  t/t7104-reset.sh (gone)                 | 46 ------------------------\n>\n> Hm, summary incorporated in the diffstat.  Neat. :)\n\nYeah, it's from this patch [1]. Maybe I should give it another push,\nthen remove --summary from format-patch diffstat.\n\n[1] http://article.gmane.org/gmane.comp.version-control.git/213752\n-- \nDuy\n"}]}