{"thread":{"id":"10614","subject":"git reset -- path weirdness","startedAt":"2007-11-03T11:17:43Z","lastAt":"2007-11-03T13:12:17Z","messageCount":3,"participants":["Björn Steinbrink","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"58098","messageId":"20071103111743.GA29358@atjola.homenet","threadId":"10614","inReplyTo":null,"subject":"git reset -- path weirdness","fromName":"Björn Steinbrink","fromEmail":"b.steinbrink@gmx.de","sentAt":"2007-11-03T11:17:43Z","receivedAt":"2007-11-03T11:17:43Z","isPatch":false,"sender":{"key":"b.steinbrink@gmx.de","avatar":"https://avatars.githubusercontent.com/u/230962?v=4"},"body":"Hi,\n\nI noticed some weirdness with git reset when a path is given. Basically\nit seems to cycle the file through 3 states: unstaged, unmerged,\ndeleted(!) which is IMHO weird at best. A bisection showed that the\nbehaviour was introduced with the shell -> conversion of git-reset.\n\nExtra annoyance is caused by the fact that \"git status\" tells you to add\nthe file when it is in the unmerged state, but that doesn't do anything.\n\nLog of \"git reset\" switching through the states:\n\ndoener@atjola:git (master) $ git status\n# On branch master\nnothing to commit (working directory clean)\n\ndoener@atjola:git (master) $ git reset -- builtin-reset.c\nbuiltin-reset.c: needs merge\n\ndoener@atjola:git (master) $ git status\n# On branch master\n# Changed but not updated:\n#   (use \"git add <file>...\" to update what will be committed)\n#\n#       unmerged:   builtin-reset.c\n#\nno changes added to commit (use \"git add\" and/or \"git commit -a\")\n\ndoener@atjola:git (master) $ git reset -- builtin-reset.c\n\ndoener@atjola:git (master) $ git status\n# On branch master\n# Changes to be committed:\n#   (use \"git reset HEAD <file>...\" to unstage)\n#\n#       deleted:    builtin-reset.c\n#\n# Untracked files:\n#   (use \"git add <file>...\" to include in what will be committed)\n#\n#       builtin-reset.c\n\ndoener@atjola:git (master) $ git reset -- builtin-reset.c\n\ndoener@atjola:git (master) $ git status\n# On branch master\nnothing to commit (working directory clean)\n\n\nThanks,\nBjörn\n"},{"id":"58107","messageId":"Pine.LNX.4.64.0711031202380.4362@racer.site","threadId":"10614","inReplyTo":"20071103111743.GA29358@atjola.homenet","subject":"Re: git reset -- path weirdness","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-03T12:03:03Z","receivedAt":"2007-11-03T12:03:03Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 3 Nov 2007, Bj?rn Steinbrink wrote:\n\n> I noticed some weirdness with git reset when a path is given. Basically \n> it seems to cycle the file through 3 states: unstaged, unmerged, \n> deleted(!) which is IMHO weird at best. A bisection showed that the \n> behaviour was introduced with the shell -> conversion of git-reset.\n\nIndeed.  I'm on it.\n\nCiao,\nDscho\n"},{"id":"58127","messageId":"Pine.LNX.4.64.0711031310350.4362@racer.site","threadId":"10614","inReplyTo":"20071103111743.GA29358@atjola.homenet","subject":"[PATCH] git-reset: do not be confused if there is nothing to reset","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-03T13:12:17Z","receivedAt":"2007-11-03T13:12:17Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThe purpose of the function update_index_from_diff() (which is the\ncallback function we give do_diff_cache()) is to update those index\nentries which differ from the given commit.\n\nSince do_diff_cache() plays games with the in-memory index, this function\ndiscarded the cache and reread it.\n\nThen, back in the function read_from_tree() we wrote the index.\n\nOf course, this broke down when there were no changes and\nupdate_index_from_diff() was not called, and therefore the mangled index\nwas not discarded.\n\nThe solution is to move the index writing into the function\nupdate_index_from_diff().\n\nNoticed by Björn Steinbrink.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin-reset.c  |   24 ++++++++++++++++++------\n t/t7102-reset.sh |    7 +++++++\n 2 files changed, 25 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin-reset.c b/builtin-reset.c\nindex e1dc31e..5467e36 100644\n--- a/builtin-reset.c\n+++ b/builtin-reset.c\n@@ -113,10 +113,17 @@ static int update_index_refresh(void)\n \treturn run_command_v_opt(argv_update_index, RUN_GIT_CMD);\n }\n \n+struct update_cb_data {\n+\tint index_fd;\n+\tstruct lock_file *lock;\n+\tint exit_code;\n+};\n+\n static void update_index_from_diff(struct diff_queue_struct *q,\n \t\tstruct diff_options *opt, void *data)\n {\n \tint i;\n+\tstruct update_cb_data *cb = data;\n \n \t/* do_diff_cache() mangled the index */\n \tdiscard_cache();\n@@ -133,29 +140,34 @@ static void update_index_from_diff(struct diff_queue_struct *q,\n \t\t} else\n \t\t\tremove_file_from_cache(one->path);\n \t}\n+\n+\tcb->exit_code = write_cache(cb->index_fd, active_cache, active_nr) ||\n+\t\tclose(cb->index_fd) ||\n+\t\tcommit_locked_index(cb->lock);\n }\n \n static int read_from_tree(const char *prefix, const char **argv,\n \t\tunsigned char *tree_sha1)\n {\n-        struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));\n-\tint index_fd;\n \tstruct diff_options opt;\n+\tstruct update_cb_data cb;\n \n \tmemset(&opt, 0, sizeof(opt));\n \tdiff_tree_setup_paths(get_pathspec(prefix, (const char **)argv), &opt);\n \topt.output_format = DIFF_FORMAT_CALLBACK;\n \topt.format_callback = update_index_from_diff;\n+\topt.format_callback_data = &cb;\n \n-\tindex_fd = hold_locked_index(lock, 1);\n+\tcb.lock = xcalloc(1, sizeof(struct lock_file));\n+\tcb.index_fd = hold_locked_index(cb.lock, 1);\n+\tcb.exit_code = 0;\n \tread_cache();\n \tif (do_diff_cache(tree_sha1, &opt))\n \t\treturn 1;\n \tdiffcore_std(&opt);\n \tdiff_flush(&opt);\n-\treturn write_cache(index_fd, active_cache, active_nr) ||\n-\t\tclose(index_fd) ||\n-\t\tcommit_locked_index(lock);\n+\n+\treturn cb.exit_code;\n }\n \n static void prepend_reflog_action(const char *action, char *buf, size_t size)\ndiff --git a/t/t7102-reset.sh b/t/t7102-reset.sh\nindex f64b1cb..cea9afb 100755\n--- a/t/t7102-reset.sh\n+++ b/t/t7102-reset.sh\n@@ -402,4 +402,11 @@ test_expect_success 'test resetting the index at give paths' '\n \n '\n \n+test_expect_success 'resetting an unmodified path is a no-op' '\n+\tgit reset --hard &&\n+\tgit reset -- file1 &&\n+\tgit diff-files --exit-code &&\n+\tgit diff-index --cached --exit-code HEAD\n+'\n+\n test_done\n-- \n1.5.3.5.1505.gd778c\n"}]}