{"thread":{"id":"48716","subject":"[PATCH] unpack-trees: do not fail reset because of unmerged skipped entry","startedAt":"2018-06-15T04:43:09Z","lastAt":"2018-07-11T16:36:04Z","messageCount":9,"participants":["Max Kirillov","Junio C Hamano","Duy Nguyen"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"350231","messageId":"20180615044251.10597-1-max@max630.net","threadId":"48716","inReplyTo":null,"subject":"[PATCH] unpack-trees: do not fail reset because of unmerged skipped entry","fromName":"Max Kirillov","fromEmail":"max@max630.net","sentAt":"2018-06-15T04:42:51Z","receivedAt":"2018-06-15T04:43:09Z","isPatch":true,"sender":{"key":"max@max630.net","avatar":"https://avatars.githubusercontent.com/u/381560?v=4"},"body":"After modify/delete merge conflict happens in a file skipped by sparse\ncheckout, \"git reset --merge\", which implements the \"--abort\" actions, and\n\"git reset --hard\" fail with message \"Entry * not uptodate. Cannot update\nsparse checkout.\" The reason is that the entry is verified in\napply_sparse_checkout() for being up-to-date even when it has a conflict.\nChecking conflicted entry for being up-to-date is not performed in other\ncases. One obvious reason to not check it is that it is already modified\nby inserting conflict marks.\n\nFix by not checking conflicted entries before performing reset.\nAlso, add test case which verifies the issue is fixed.\n\nSigned-off-by: Max Kirillov <max@max630.net>\n---\nI have tried to use sparse-checkout for merging and cherrypicking, to save on IO\nand disk space. It works, mostly, but there are issues here and there.\nThis one was low hanging, and also pretty annoying.\n\n t/t3035-merge-sparse.sh | 46 +++++++++++++++++++++++++++++++++++++++++\n unpack-trees.c          |  2 +-\n 2 files changed, 47 insertions(+), 1 deletion(-)\n create mode 100755 t/t3035-merge-sparse.sh\n\ndiff --git a/t/t3035-merge-sparse.sh b/t/t3035-merge-sparse.sh\nnew file mode 100755\nindex 0000000000..c6b2b0b82a\n--- /dev/null\n+++ b/t/t3035-merge-sparse.sh\n@@ -0,0 +1,46 @@\n+#!/bin/sh\n+\n+test_description='merge with sparse files'\n+\n+. ./test-lib.sh\n+\n+# test_file $filename $content\n+test_file () {\n+\techo \"$2\" > \"$1\" &&\n+\tgit add \"$1\"\n+}\n+\n+# test_commit_this $message_and_tag\n+test_commit_this () {\n+\tgit commit -m \"$1\" &&\n+\tgit tag \"$1\"\n+}\n+\n+test_expect_success 'setup' '\n+\ttest_file checked-out init &&\n+\ttest_file modify_delete modify_delete_init &&\n+\ttest_commit_this init &&\n+\ttest_file modify_delete modify_delete_theirs &&\n+\ttest_commit_this theirs &&\n+\tgit reset --hard init &&\n+\tgit rm modify_delete &&\n+\ttest_commit_this ours &&\n+\tgit config core.sparseCheckout true &&\n+\techo \"/checked-out\" >.git/info/sparse-checkout &&\n+\tgit reset --hard &&\n+\t! git merge theirs\n+'\n+\n+test_expect_success 'reset --hard works after the conflict' '\n+\tgit reset --hard\n+'\n+\n+test_expect_success 'setup: conflict back' '\n+\t! git merge theirs\n+'\n+\n+test_expect_success 'Merge abort works after the conflict' '\n+\tgit merge --abort\n+'\n+\n+test_done\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex e73745051e..65ae0721a6 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -468,7 +468,7 @@ static int apply_sparse_checkout(struct index_state *istate,\n \t\t * also stat info may have lost after merged_entry() so calling\n \t\t * verify_uptodate() again may fail\n \t\t */\n-\t\tif (!(ce->ce_flags & CE_UPDATE) && verify_uptodate_sparse(ce, o))\n+\t\tif (!(ce->ce_flags & CE_UPDATE) && !(ce->ce_flags & CE_CONFLICTED) && verify_uptodate_sparse(ce, o))\n \t\t\treturn -1;\n \t\tce->ce_flags |= CE_WT_REMOVE;\n \t\tce->ce_flags &= ~CE_UPDATE;\n-- \n2.17.0.1185.g782057d875\n\n"},{"id":"350297","messageId":"xmqqh8m3zurz.fsf@gitster-ct.c.googlers.com","threadId":"48716","inReplyTo":"20180615044251.10597-1-max@max630.net","subject":"Re: [PATCH] unpack-trees: do not fail reset because of unmerged skipped entry","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-06-15T19:58:40Z","receivedAt":"2018-06-15T19:58:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Max Kirillov <max@max630.net> writes:\n\n> After modify/delete merge conflict happens in a file skipped by sparse\n> checkout, \"git reset --merge\", which implements the \"--abort\" actions, and\n> \"git reset --hard\" fail with message \"Entry * not uptodate. Cannot update\n> sparse checkout.\" The reason is that the entry is verified in\n> apply_sparse_checkout() for being up-to-date even when it has a conflict.\n> Checking conflicted entry for being up-to-date is not performed in other\n> cases. One obvious reason to not check it is that it is already modified\n> by inserting conflict marks.\n>\n> Fix by not checking conflicted entries before performing reset.\n> Also, add test case which verifies the issue is fixed.\n\nI do not know offhand if \"reset --merge\" should force succeeding in\nsuch a case, but I agree that it is criminal to stop \"reset --hard\"\nwith \"not uptodate\", as the whole point of \"hard reset\" is to get\nrid of the 'not up-to-date' modification.\n\nI guess not may people make serious use of sparsely checked-out\nworking tree and that is why such a failure is reported this late\nafter the feature was introduced?\n\n> +test_expect_success 'reset --hard works after the conflict' '\n> +\tgit reset --hard\n> +'\n\nDo we want to verify the state after the 'hard' reset succeeds as\nwell?  Things like \n\n - all paths in the HEAD and all paths in the index are identical;\n\n - paths that do exist in the working tree are all identical to HEAD\n   version; and\n\n - paths that do not exist in the working tree are missing due to\n   the sparse checkout setting (iow, it is a bug if a path that is\n   outside the \"sparse\" setting is missing from the working tree).\n\n> +test_expect_success 'setup: conflict back' '\n> +\t! git merge theirs\n> +'\n> +\n> +test_expect_success 'Merge abort works after the conflict' '\n> +\tgit merge --abort\n> +'\n\nLikewise here.\n\n\n> +test_done\n> diff --git a/unpack-trees.c b/unpack-trees.c\n> index e73745051e..65ae0721a6 100644\n> --- a/unpack-trees.c\n> +++ b/unpack-trees.c\n> @@ -468,7 +468,7 @@ static int apply_sparse_checkout(struct index_state *istate,\n>  \t\t * also stat info may have lost after merged_entry() so calling\n>  \t\t * verify_uptodate() again may fail\n>  \t\t */\n> -\t\tif (!(ce->ce_flags & CE_UPDATE) && verify_uptodate_sparse(ce, o))\n> +\t\tif (!(ce->ce_flags & CE_UPDATE) && !(ce->ce_flags & CE_CONFLICTED) && verify_uptodate_sparse(ce, o))\n>  \t\t\treturn -1;\n>  \t\tce->ce_flags |= CE_WT_REMOVE;\n>  \t\tce->ce_flags &= ~CE_UPDATE;\n\nThanks.\n"},{"id":"350306","messageId":"20180616051444.GA29754@duynguyen.home","threadId":"48716","inReplyTo":"20180615044251.10597-1-max@max630.net","subject":"Re: [PATCH] unpack-trees: do not fail reset because of unmerged skipped entry","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-06-16T05:14:44Z","receivedAt":"2018-06-16T05:14:55Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Fri, Jun 15, 2018 at 07:42:51AM +0300, Max Kirillov wrote:\n> After modify/delete merge conflict happens in a file skipped by sparse\n> checkout, \"git reset --merge\", which implements the \"--abort\" actions, and\n> \"git reset --hard\" fail with message \"Entry * not uptodate. Cannot update\n> sparse checkout.\" The reason is that the entry is verified in\n> apply_sparse_checkout() for being up-to-date even when it has a conflict.\n\nConflicted entries should not be skipped by design. Even if you\nspecify sparse patterns to ignore them, they must be checked out. When\na conflicted entry appears in apply_sparse_checkout() something else\nis already wrong.\n\nI think this is a better fix along that line. As you can see we\nalready un-skip staged entries. But I think I forgot (or did not know)\nabout CE_CONFLICTED. This change passes your new tests, but I didn't\ntry to run the whole test suite to see if I broke anything else.\n\n-- 8< --\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 3a85a02a77..eb544ee1b3 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1246,7 +1246,7 @@ static void mark_new_skip_worktree(struct exclude_list *el,\n \t\tif (select_flag && !(ce->ce_flags & select_flag))\n \t\t\tcontinue;\n \n-\t\tif (!ce_stage(ce))\n+\t\tif (!ce_stage(ce) && !(ce->ce_flags & CE_CONFLICTED))\n \t\t\tce->ce_flags |= skip_wt_flag;\n \t\telse\n \t\t\tce->ce_flags &= ~skip_wt_flag;\n-- 8< --\n\n> Checking conflicted entry for being up-to-date is not performed in other\n> cases. One obvious reason to not check it is that it is already modified\n> by inserting conflict marks.\n> \n> Fix by not checking conflicted entries before performing reset.\n> Also, add test case which verifies the issue is fixed.\n> \n> Signed-off-by: Max Kirillov <max@max630.net>\n> ---\n> I have tried to use sparse-checkout for merging and cherrypicking, to save on IO\n> and disk space. It works, mostly, but there are issues here and there.\n> This one was low hanging, and also pretty annoying.\n> \n>  t/t3035-merge-sparse.sh | 46 +++++++++++++++++++++++++++++++++++++++++\n>  unpack-trees.c          |  2 +-\n>  2 files changed, 47 insertions(+), 1 deletion(-)\n>  create mode 100755 t/t3035-merge-sparse.sh\n> \n> diff --git a/t/t3035-merge-sparse.sh b/t/t3035-merge-sparse.sh\n> new file mode 100755\n> index 0000000000..c6b2b0b82a\n> --- /dev/null\n> +++ b/t/t3035-merge-sparse.sh\n> @@ -0,0 +1,46 @@\n> +#!/bin/sh\n> +\n> +test_description='merge with sparse files'\n> +\n> +. ./test-lib.sh\n> +\n> +# test_file $filename $content\n> +test_file () {\n> +\techo \"$2\" > \"$1\" &&\n> +\tgit add \"$1\"\n> +}\n> +\n> +# test_commit_this $message_and_tag\n> +test_commit_this () {\n> +\tgit commit -m \"$1\" &&\n> +\tgit tag \"$1\"\n> +}\n> +\n> +test_expect_success 'setup' '\n> +\ttest_file checked-out init &&\n> +\ttest_file modify_delete modify_delete_init &&\n> +\ttest_commit_this init &&\n> +\ttest_file modify_delete modify_delete_theirs &&\n> +\ttest_commit_this theirs &&\n> +\tgit reset --hard init &&\n> +\tgit rm modify_delete &&\n> +\ttest_commit_this ours &&\n> +\tgit config core.sparseCheckout true &&\n> +\techo \"/checked-out\" >.git/info/sparse-checkout &&\n> +\tgit reset --hard &&\n> +\t! git merge theirs\n> +'\n> +\n> +test_expect_success 'reset --hard works after the conflict' '\n> +\tgit reset --hard\n> +'\n> +\n> +test_expect_success 'setup: conflict back' '\n> +\t! git merge theirs\n> +'\n> +\n> +test_expect_success 'Merge abort works after the conflict' '\n> +\tgit merge --abort\n> +'\n> +\n> +test_done\n> diff --git a/unpack-trees.c b/unpack-trees.c\n> index e73745051e..65ae0721a6 100644\n> --- a/unpack-trees.c\n> +++ b/unpack-trees.c\n> @@ -468,7 +468,7 @@ static int apply_sparse_checkout(struct index_state *istate,\n>  \t\t * also stat info may have lost after merged_entry() so calling\n>  \t\t * verify_uptodate() again may fail\n>  \t\t */\n> -\t\tif (!(ce->ce_flags & CE_UPDATE) && verify_uptodate_sparse(ce, o))\n> +\t\tif (!(ce->ce_flags & CE_UPDATE) && !(ce->ce_flags & CE_CONFLICTED) && verify_uptodate_sparse(ce, o))\n>  \t\t\treturn -1;\n>  \t\tce->ce_flags |= CE_WT_REMOVE;\n>  \t\tce->ce_flags &= ~CE_UPDATE;\n> -- \n> 2.17.0.1185.g782057d875\n> \n"},{"id":"350323","messageId":"CAF7_NFR8dKZtbRr+p_HGECdZhyqSWAsMuZ2JthXefGyFL+57zA@mail.gmail.com","threadId":"48716","inReplyTo":"xmqqh8m3zurz.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH] unpack-trees: do not fail reset because of unmerged skipped entry","fromName":"Max Kirillov","fromEmail":"max@max630.net","sentAt":"2018-06-16T08:22:43Z","receivedAt":"2018-06-16T08:22:49Z","isPatch":true,"sender":{"key":"max@max630.net","avatar":"https://avatars.githubusercontent.com/u/381560?v=4"},"body":"> I do not know offhand if \"reset --merge\" should force succeeding in\nsuch a case, but I agree that it is criminal to stop \"reset --hard\"\nwith \"not uptodate\", as the whole point of \"hard reset\" is to get\nrid of the 'not up-to-date' modification.\n\nI originally had a fix just for \"reset --hard\". It was in\nverify_uptodate_1(), to move check for \"->reset\" earlier. But then I\nfound that \"merge --abort\" does not use \"reset --hard\", but rather\n--merge, so I fixed that. Because --merge should work also, shouldn't\nit?\n\nActually, I think that fix in verify_uptodate_1() was right, I just\ndid not find what it affects, after the other fix\n"},{"id":"352169","messageId":"20180710192153.GA2050@jessie.local","threadId":"48716","inReplyTo":"20180616051444.GA29754@duynguyen.home","subject":"Re: [PATCH] unpack-trees: do not fail reset because of unmerged skipped entry","fromName":"Max Kirillov","fromEmail":"max@max630.net","sentAt":"2018-07-10T19:21:53Z","receivedAt":"2018-07-10T19:22:03Z","isPatch":true,"sender":{"key":"max@max630.net","avatar":"https://avatars.githubusercontent.com/u/381560?v=4"},"body":"On Sat, Jun 16, 2018 at 07:14:44AM +0200, Duy Nguyen wrote:\n> -- 8< --\n> diff --git a/unpack-trees.c b/unpack-trees.c\n> index 3a85a02a77..eb544ee1b3 100644\n> --- a/unpack-trees.c\n> +++ b/unpack-trees.c\n> @@ -1246,7 +1246,7 @@ static void mark_new_skip_worktree(struct exclude_list *el,\n>  \t\tif (select_flag && !(ce->ce_flags & select_flag))\n>  \t\t\tcontinue;\n>  \n> -\t\tif (!ce_stage(ce))\n> +\t\tif (!ce_stage(ce) && !(ce->ce_flags & CE_CONFLICTED))\n>  \t\t\tce->ce_flags |= skip_wt_flag;\n>  \t\telse\n>  \t\t\tce->ce_flags &= ~skip_wt_flag;\n> -- 8< --\n\nI tried your fix and it is working. I put it instead of my original fix. Would you sign it off?\n"},{"id":"352170","messageId":"20180710192309.GB2050@jessie.local","threadId":"48716","inReplyTo":"xmqqh8m3zurz.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH] unpack-trees: do not fail reset because of unmerged skipped entry","fromName":"Max Kirillov","fromEmail":"max@max630.net","sentAt":"2018-07-10T19:23:10Z","receivedAt":"2018-07-10T19:23:15Z","isPatch":true,"sender":{"key":"max@max630.net","avatar":"https://avatars.githubusercontent.com/u/381560?v=4"},"body":"On Fri, Jun 15, 2018 at 12:58:40PM -0700, Junio C Hamano wrote:\n> Do we want to verify the state after the 'hard' reset succeeds as\n> well?  Things like \n> \n>  - all paths in the HEAD and all paths in the index are identical;\n> \n>  - paths that do exist in the working tree are all identical to HEAD\n>    version; and\n> \n>  - paths that do not exist in the working tree are missing due to\n>    the sparse checkout setting (iow, it is a bug if a path that is\n>    outside the \"sparse\" setting is missing from the working tree).\n\nI implemented the additional check, it is a bit different\nliterally, but should be equivalent for this case\n"},{"id":"352171","messageId":"20180710191748.17339-1-max@max630.net","threadId":"48716","inReplyTo":"20180615044251.10597-1-max@max630.net","subject":"[PATCH v2] unpack-trees: do not fail reset because of unmerged skipped entry","fromName":"Max Kirillov","fromEmail":"max@max630.net","sentAt":"2018-07-10T19:17:48Z","receivedAt":"2018-07-10T19:25:23Z","isPatch":true,"sender":{"key":"max@max630.net","avatar":"https://avatars.githubusercontent.com/u/381560?v=4"},"body":"After modify/delete merge conflict happens in a file skipped by sparse\ncheckout, \"git reset --merge\", which implements the \"--abort\" actions,\nand \"git reset --hard\" fail with message \"Entry * not uptodate. Cannot\nupdate sparse checkout.\"\n\nAs explained in [1], the up-to-date checker mistakenly treats conflicted\nentry which does not exist in HEAD as still skipped by sparse checkout.\n\nUse the fix suggested in [1]. Also, add test case which verifies the\nissue is fixed.\n\n[1] https://public-inbox.org/git/20180616051444.GA29754@duynguyen.home/\n\nFix-authored-by: Duy Nguyen <pclouds@gmail.com>\nSigned-off-by: Max Kirillov <max@max630.net>\n---\n* used the right fix. Probably there should be sign off?\n* add extra check that state is correct after the reset. it is literally\n  different from the one described by Junio but should be equivalent for this\n  case\n\n t/t3035-merge-sparse.sh | 59 +++++++++++++++++++++++++++++++++++++++++++++++++\n unpack-trees.c          |  2 +-\n 2 files changed, 60 insertions(+), 1 deletion(-)\n create mode 100755 t/t3035-merge-sparse.sh\n\ndiff --git a/t/t3035-merge-sparse.sh b/t/t3035-merge-sparse.sh\nnew file mode 100755\nindex 0000000..0c0b433\n--- /dev/null\n+++ b/t/t3035-merge-sparse.sh\n@@ -0,0 +1,59 @@\n+#!/bin/sh\n+\n+test_description='merge with sparse files'\n+\n+. ./test-lib.sh\n+\n+# test_file $filename $content\n+test_file () {\n+\techo \"$2\" > \"$1\" &&\n+\tgit add \"$1\"\n+}\n+\n+# test_commit_this $message_and_tag\n+test_commit_this () {\n+\tgit commit -m \"$1\" &&\n+\tgit tag \"$1\"\n+}\n+\n+test_expect_success 'setup' '\n+\t: >empty &&\n+\ttest_file checked-out init &&\n+\ttest_file modify_delete modify_delete_init &&\n+\ttest_commit_this init &&\n+\ttest_file modify_delete modify_delete_theirs &&\n+\ttest_commit_this theirs &&\n+\tgit reset --hard init &&\n+\tgit rm modify_delete &&\n+\ttest_commit_this ours &&\n+\tgit config core.sparseCheckout true &&\n+\techo \"/checked-out\" >.git/info/sparse-checkout &&\n+\tgit reset --hard &&\n+\t! git merge theirs\n+'\n+\n+test_expect_success 'reset --hard works after the conflict' '\n+\tgit reset --hard\n+'\n+\n+test_expect_success 'is reset properly' '\n+\tgit status --porcelain -- modify_delete >out &&\n+\ttest_cmp empty out &&\n+\ttest_path_is_missing modify_delete\n+'\n+\n+test_expect_success 'setup: conflict back' '\n+\t! git merge theirs\n+'\n+\n+test_expect_success 'Merge abort works after the conflict' '\n+\tgit merge --abort\n+'\n+\n+test_expect_success 'is aborted properly' '\n+\tgit status --porcelain -- modify_delete >out &&\n+\ttest_cmp empty out &&\n+\ttest_path_is_missing modify_delete\n+'\n+\n+test_done\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 3a85a02..eb544ee 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1246,7 +1246,7 @@ static void mark_new_skip_worktree(struct exclude_list *el,\n \t\tif (select_flag && !(ce->ce_flags & select_flag))\n \t\t\tcontinue;\n \n-\t\tif (!ce_stage(ce))\n+\t\tif (!ce_stage(ce) && !(ce->ce_flags & CE_CONFLICTED))\n \t\t\tce->ce_flags |= skip_wt_flag;\n \t\telse\n \t\t\tce->ce_flags &= ~skip_wt_flag;\n-- \n2.0.0\n\n"},{"id":"352255","messageId":"CACsJy8BVadBd1T2yoUhnxd21=c8SVaFqPXT8kk4NfnzGyBNOCw@mail.gmail.com","threadId":"48716","inReplyTo":"20180710192153.GA2050@jessie.local","subject":"Re: [PATCH] unpack-trees: do not fail reset because of unmerged skipped entry","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-07-11T15:25:46Z","receivedAt":"2018-07-11T15:26:19Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Jul 10, 2018 at 9:22 PM Max Kirillov <max@max630.net> wrote:\n>\n> On Sat, Jun 16, 2018 at 07:14:44AM +0200, Duy Nguyen wrote:\n> > -- 8< --\n> > diff --git a/unpack-trees.c b/unpack-trees.c\n> > index 3a85a02a77..eb544ee1b3 100644\n> > --- a/unpack-trees.c\n> > +++ b/unpack-trees.c\n> > @@ -1246,7 +1246,7 @@ static void mark_new_skip_worktree(struct exclude_list *el,\n> >               if (select_flag && !(ce->ce_flags & select_flag))\n> >                       continue;\n> >\n> > -             if (!ce_stage(ce))\n> > +             if (!ce_stage(ce) && !(ce->ce_flags & CE_CONFLICTED))\n> >                       ce->ce_flags |= skip_wt_flag;\n> >               else\n> >                       ce->ce_flags &= ~skip_wt_flag;\n> > -- 8< --\n>\n> I tried your fix and it is working. I put it instead of my original fix. Would you sign it off?\n\nSigned-off-by: Duy Nguyen <pclouds@gmail.com>\n-- \nDuy\n"},{"id":"352268","messageId":"xmqq1sc94tn4.fsf@gitster-ct.c.googlers.com","threadId":"48716","inReplyTo":"CACsJy8BVadBd1T2yoUhnxd21=c8SVaFqPXT8kk4NfnzGyBNOCw@mail.gmail.com","subject":"Re: [PATCH] unpack-trees: do not fail reset because of unmerged skipped entry","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-07-11T16:35:59Z","receivedAt":"2018-07-11T16:36:04Z","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, Jul 10, 2018 at 9:22 PM Max Kirillov <max@max630.net> wrote:\n>>\n>> On Sat, Jun 16, 2018 at 07:14:44AM +0200, Duy Nguyen wrote:\n>> > -- 8< --\n>> > diff --git a/unpack-trees.c b/unpack-trees.c\n>> > index 3a85a02a77..eb544ee1b3 100644\n>> > --- a/unpack-trees.c\n>> > +++ b/unpack-trees.c\n>> > @@ -1246,7 +1246,7 @@ static void mark_new_skip_worktree(struct exclude_list *el,\n>> >               if (select_flag && !(ce->ce_flags & select_flag))\n>> >                       continue;\n>> >\n>> > -             if (!ce_stage(ce))\n>> > +             if (!ce_stage(ce) && !(ce->ce_flags & CE_CONFLICTED))\n>> >                       ce->ce_flags |= skip_wt_flag;\n>> >               else\n>> >                       ce->ce_flags &= ~skip_wt_flag;\n>> > -- 8< --\n>>\n>> I tried your fix and it is working. I put it instead of my original fix. Would you sign it off?\n>\n> Signed-off-by: Duy Nguyen <pclouds@gmail.com>\n\nThanks, both.\n"}]}