{"thread":{"id":"49168","subject":"Do not raise conflict when a code in a patch was already added","startedAt":"2018-08-20T10:30:34Z","lastAt":"2018-08-21T12:10:34Z","messageCount":5,"participants":["Konstantin Kharlamov","Phillip Wood","Johannes Sixt","Igor Djordjevic"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"356079","messageId":"fae8346d-398f-e984-5aa5-e3dc3ee71d70@yandex.ru","threadId":"49168","inReplyTo":null,"subject":"Do not raise conflict when a code in a patch was already added","fromName":"Konstantin Kharlamov","fromEmail":"hi-angel@yandex.ru","sentAt":"2018-08-20T10:22:37Z","receivedAt":"2018-08-20T10:30:34Z","isPatch":false,"sender":{"key":"hi-angel@yandex.ru","avatar":null},"body":"So, steps-to-reproduce below rather full of trivia like setting up a\nrepo, but the TL;DR is:\n\nUpon using `git rebase -i HEAD~1` and then `git add -p` to add part of a\n\"hunk\" as one commit, and then using `git rebase --continue` so the\nother part of hunk would be left in top commit; git raises a conflict.\n\nIt's spectacular, that content of one of inserted conflict markers is\nempty, so all you have to do is to remove the markers, and use `git add`\non the file, and then `git rebase --continue`\n\nIts a lot of unncessary actions, git could just figure that the code it\nsees in the patch is already there, being a part of another commit.\n\nMaybe git could issue a warning, or to question a user interactively \n(y/n); but raising a conflict IMO is unnecessary.\n\n# Steps to reproduce\n\nIn empty dir execute:\n\n\t$ git init\n\t$ touch test\n\tInitialized empty Git repository in /tmp/test/.git/\n\t$ git add test\n\t$ git commit\n\t[master (root-commit) a7ce543] 1st commit\n\t 1 file changed, 2 insertions(+)\n\t create mode 100644 test\n\t$ echo -e \"foo\\nbar\" > test             # content you'll want to break\n\t$ git add -u && git commit\n\t[detached HEAD 9e28331] 2-nd commit\n\t 1 file changed, 2 insertions(+)\n\t$ git rebase -i --root\n\tStopped at a7ce543...  1st commit\n\tYou can amend the commit now, with\n\n\t  git commit --amend\n\n\tOnce you are satisfied with your changes, run\n\n\t  git rebase --continue\n\nPut \"edit\" for the 2-nd commit\n\n\t$ git reset HEAD^\n\tUnstaged changes after reset:\n\tM       test\n\t$ git add -p\n\tdiff --git a/test b/test\n\tindex e69de29..3bd1f0e 100644\n\t--- a/test\n\t+++ b/test\n\t@@ -0,0 +1,2 @@\n\t+foo\n\t+bar\n\tStage this hunk [y,n,q,a,d,e,?]? e\n\n\t╭─constantine@constantine-N61Ja  /tmp/test ‹node-›  ‹› (e721fa3*)\n\t╰─$ git commit\n\t[detached HEAD 27b2f63] add foo\n\t 1 file changed, 1 insertion(+)\n\t╭─constantine@constantine-N61Ja  /tmp/test ‹node-›  ‹› (27b2f63*)\n\t╰─$ git rebase --continue\n\ttest: needs update\n\tYou must edit all merge conflicts and then\n\tmark them as resolved using git add\n\nWhat happened is that it's obvious that the hunk was broken to multiple\ncommits, and git should figure that out, and not to raise a conflict.\n\nSide note: for some reason in the test git didn't insert conflict\nmarkers. It did in real-world usecase though, and there was simply no\ncontent inside one of them.\n"},{"id":"356106","messageId":"ab5021a9-6980-b96c-9d51-cc301844f2af@talktalk.net","threadId":"49168","inReplyTo":"fae8346d-398f-e984-5aa5-e3dc3ee71d70@yandex.ru","subject":"Re: Do not raise conflict when a code in a patch was already added","fromName":"Phillip Wood","fromEmail":"phillip.wood@talktalk.net","sentAt":"2018-08-20T17:40:49Z","receivedAt":"2018-08-20T17:40:54Z","isPatch":false,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 20/08/2018 11:22, Konstantin Kharlamov wrote:\n> So, steps-to-reproduce below rather full of trivia like setting up a\n> repo, but the TL;DR is:\n> \n> Upon using `git rebase -i HEAD~1` and then `git add -p` to add part of a\n> \"hunk\" as one commit, and then using `git rebase --continue` so the\n> other part of hunk would be left in top commit; git raises a conflict.\n\nI think this is a misleading error message as in your example below\nthere are no conflicts, just unstaged changes. git-rebase.sh has the\nfollowing code\n\n\ngit update-index --ignore-submodules --refresh &&\n        git diff-files --quiet --ignore-submodules || {\n                echo \"$(gettext \"You must edit all merge conflicts and then\nmark them as resolved using git add\")\"\n                exit 1\n\nI think this pre-dates interactive rebases when the only unstaged\nchanges could be conflicts.\n\n> \n> It's spectacular, that content of one of inserted conflict markers is\n> empty, so all you have to do is to remove the markers, and use `git add`\n> on the file, and then `git rebase --continue`\n> \n> Its a lot of unncessary actions, git could just figure that the code it\n> sees in the patch is already there, being a part of another commit.\n\nIf there are conflict markers where one side is empty it means that some\nlines from the merge base (which for a rebase is the parent of the\ncommit being picked) have been deleted on one side and modified on the\nother. Git cannot know if you want to use the deleted version or the\nmodified version. You can use 'git diff --cc' to see the combined diff\nwhich should show the lines being deleted on both sides and an addition\non the side with the modified lines. You can also set the\nmerge.conflictStyle config variable to diff3 to see the original text as\nwell as the text from the merge heads.\n\nBest Wishes\n\nPhillip\n\n> \n> Maybe git could issue a warning, or to question a user interactively\n> (y/n); but raising a conflict IMO is unnecessary.\n> \n> # Steps to reproduce\n> \n> In empty dir execute:\n> \n>     $ git init\n>     $ touch test\n>     Initialized empty Git repository in /tmp/test/.git/\n>     $ git add test\n>     $ git commit\n>     [master (root-commit) a7ce543] 1st commit\n>      1 file changed, 2 insertions(+)\n>      create mode 100644 test\n>     $ echo -e \"foo\\nbar\" > test             # content you'll want to break\n>     $ git add -u && git commit\n>     [detached HEAD 9e28331] 2-nd commit\n>      1 file changed, 2 insertions(+)\n>     $ git rebase -i --root\n>     Stopped at a7ce543...  1st commit\n>     You can amend the commit now, with\n> \n>       git commit --amend\n> \n>     Once you are satisfied with your changes, run\n> \n>       git rebase --continue\n> \n> Put \"edit\" for the 2-nd commit\n> \n>     $ git reset HEAD^\n>     Unstaged changes after reset:\n>     M       test\n>     $ git add -p\n>     diff --git a/test b/test\n>     index e69de29..3bd1f0e 100644\n>     --- a/test\n>     +++ b/test\n>     @@ -0,0 +1,2 @@\n>     +foo\n>     +bar\n>     Stage this hunk [y,n,q,a,d,e,?]? e\n> \n>     ╭─constantine@constantine-N61Ja  /tmp/test ‹node-›  ‹› (e721fa3*)\n>     ╰─$ git commit\n>     [detached HEAD 27b2f63] add foo\n>      1 file changed, 1 insertion(+)\n>     ╭─constantine@constantine-N61Ja  /tmp/test ‹node-›  ‹› (27b2f63*)\n>     ╰─$ git rebase --continue\n>     test: needs update\n>     You must edit all merge conflicts and then\n>     mark them as resolved using git add\n> \n> What happened is that it's obvious that the hunk was broken to multiple\n> commits, and git should figure that out, and not to raise a conflict.\n> \n> Side note: for some reason in the test git didn't insert conflict\n> markers. It did in real-world usecase though, and there was simply no\n> content inside one of them.\n> \n\n"},{"id":"356125","messageId":"0d36d185-23d5-a656-67dd-5df86abed3e9@kdbg.org","threadId":"49168","inReplyTo":"ab5021a9-6980-b96c-9d51-cc301844f2af@talktalk.net","subject":"Re: Do not raise conflict when a code in a patch was already added","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2018-08-20T19:22:46Z","receivedAt":"2018-08-20T19:22:52Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 20.08.2018 um 19:40 schrieb Phillip Wood:\n> On 20/08/2018 11:22, Konstantin Kharlamov wrote:\n>> It's spectacular, that content of one of inserted conflict markers is\n>> empty, so all you have to do is to remove the markers, and use `git add`\n>> on the file, and then `git rebase --continue`\n>>\n>> Its a lot of unncessary actions, git could just figure that the code it\n>> sees in the patch is already there, being a part of another commit.\n> \n> If there are conflict markers where one side is empty it means that some\n> lines from the merge base (which for a rebase is the parent of the\n> commit being picked) have been deleted on one side and modified on the\n> other. Git cannot know if you want to use the deleted version or the\n> modified version.\n\nThere's another possibility (and I think it is what happens actually in \nKonstantin's case): When one side added lines 1 2 and the other side \nadded 1 2 3, then the actual conflict is << 1 2 == 1 2 3 >>, but our \nmerge code is able to move the identical part out of the conflicted \nsection: 1 2 << == 3 >>. But this is just a courtesy for the user; the \nreal conflict is the original one. Without this optimization, the work \nto resolve the conflict would be slightly more arduous.\n\n-- Hannes\n"},{"id":"356162","messageId":"e5f65c19-0f49-d48e-c600-7dfcd95f3218@yandex.ru","threadId":"49168","inReplyTo":"0d36d185-23d5-a656-67dd-5df86abed3e9@kdbg.org","subject":"Re: Do not raise conflict when a code in a patch was already added","fromName":"Konstantin Kharlamov","fromEmail":"hi-angel@yandex.ru","sentAt":"2018-08-21T09:37:54Z","receivedAt":"2018-08-21T09:45:35Z","isPatch":false,"sender":{"key":"hi-angel@yandex.ru","avatar":null},"body":"\n\nOn 20.08.2018 22:22, Johannes Sixt wrote:\n> Am 20.08.2018 um 19:40 schrieb Phillip Wood:\n>> On 20/08/2018 11:22, Konstantin Kharlamov wrote:\n>>> It's spectacular, that content of one of inserted conflict markers is\n>>> empty, so all you have to do is to remove the markers, and use `git add`\n>>> on the file, and then `git rebase --continue`\n>>>\n>>> Its a lot of unncessary actions, git could just figure that the code it\n>>> sees in the patch is already there, being a part of another commit.\n>>\n>> If there are conflict markers where one side is empty it means that some\n>> lines from the merge base (which for a rebase is the parent of the\n>> commit being picked) have been deleted on one side and modified on the\n>> other. Git cannot know if you want to use the deleted version or the\n>> modified version.\n> \n> There's another possibility (and I think it is what happens actually in \n> Konstantin's case): When one side added lines 1 2 and the other side \n> added 1 2 3, then the actual conflict is << 1 2 == 1 2 3 >>, but our \n> merge code is able to move the identical part out of the conflicted \n> section: 1 2 << == 3 >>. But this is just a courtesy for the user; the \n> real conflict is the original one. Without this optimization, the work \n> to resolve the conflict would be slightly more arduous.\n\nYeah, thanks, that's what happens. And I'm wondering, is it really \nneeded to raise a conflict there? Would it be worth to just apply the \nline \"3\", possibly with a warning or an interactive question to user \n(apply/raise) that identical parts were ignored?\n"},{"id":"356164","messageId":"32354ab0-1d17-0be3-679a-75f6287a6bab@gmail.com","threadId":"49168","inReplyTo":"e5f65c19-0f49-d48e-c600-7dfcd95f3218@yandex.ru","subject":"Re: Do not raise conflict when a code in a patch was already added","fromName":"Igor Djordjevic","fromEmail":"igor.d.djordjevic@gmail.com","sentAt":"2018-08-21T12:10:17Z","receivedAt":"2018-08-21T12:10:34Z","isPatch":false,"sender":{"key":"igor.d.djordjevic@gmail.com","avatar":null},"body":"Hi Konstantin,\n\nOn 21/08/2018 11:37, Konstantin Kharlamov wrote:\n> \n> > There's another possibility (and I think it is what happens \n> > actually in Konstantin's case): When one side added lines 1 2 and the \n> > other side added 1 2 3, then the actual conflict is \n> > << 1 2 == 1 2 3 >>, but our merge code is able to move the identical \n> > part out of the conflicted section: 1 2 << == 3 >>. But this is just \n> > a courtesy for the user; the real conflict is the original one. \n> > Without this optimization, the work to resolve the conflict would be \n> > slightly more arduous.\n> \n> Yeah, thanks, that's what happens. And I'm wondering, is it really \n> needed to raise a conflict there? Would it be worth to just apply the \n> line \"3\", possibly with a warning or an interactive question to user \n> (apply/raise) that identical parts were ignored?\n\nI see how this might make sense in the given example of \"A added 1 \nand 2, B added 1 and 2 and 3\", but I'm afraid that might be a too \nnarrow view.\n\nWhat we actually don't know is if A deliberately chose not to include \n3, or even worse, if A started from having \"1 and 2 and 3\" in there, \nand then decided to remove 3.\n\nIn both these situation just applying 3 would be wrong, and raising a \nconflict seems as the most (and only?) sensible solution.\n\nApplying _and_ asking for confirmation might be interesting, but I'm \nafraid it would favor specific use case only, being an annoyance in \nall the others (where it should really be a conflict, and you now \nhave additional prompt to deal with).\n\nThat said, it would indeed be nice to have a way to communicate to \n`git rebase` that we are just splitting later commit into smaller \nparts preceding it, so situations like this could be resolved \nautomatically and without conflicts, as you'd expected - but only \nwithin that narrow, user-provided/communicated context, not in \ngeneral case.\n\nRegards, Buga\n"}]}