{"thread":{"id":"40294","subject":"Improving auto conflict resolving while merge","startedAt":"2015-09-07T17:15:46Z","lastAt":"2015-09-09T00:08:09Z","messageCount":4,"participants":["KES","Jeff King","Eugen Konkov"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"269575","messageId":"856611441646146@web13j.yandex.ru","threadId":"40294","inReplyTo":null,"subject":"Improving auto conflict resolving while merge","fromName":"KES","fromEmail":"kes-kes@yandex.ua","sentAt":"2015-09-07T17:15:46Z","receivedAt":"2015-09-07T17:15:46Z","isPatch":false,"sender":{"key":"kes-kes@yandex.ua","avatar":null},"body":"Hi.\n\n**To not apply big patches, I will supply links to public repository\n\nLets start\n\n1. git clone https://github.com/KES777/Plack\n\n2. git show ed485bf75a6\n\nNothing interesting. Usual merge conflict while merge branch 'feature/doc_contribute' to 'master'\n\nBut I was interested by this part:\n\n   my $app = sub {\n       my $env =  shift;\n \n+<<<<<<< HEAD\n+=======\n+  my $app = sub {\n+      my $env =  shift;\n+\n+>>>>>>> master\n\nI know that some code were cherry picked(??) by maintainer from by branch. Ans this is the part which are same in master and branch.\nSo I not expect conflict here. I start to dig.\n\nI compare Log4perl.pm files from branch and master \n3. git checkout feature/doc_contribution\n4. cd lib/Plack/Middleware\n5. git diff d095870 Log4perl.pm\n\nI see that both master and branch has same resulting changes:\n@@ -36,10 +35,10 @@ __END__\n \n =head1 NAME\n \n-Plack::Middleware::Log4perl - Uses Log::Log4perl to configure logger\n+Plack::Middleware::Log4perl - Uses Log::Log4perl to configure psgix.logger\n \n =head1 SYNOPSIS\n-\n+  # How to use logger in your app\n   my $app = sub {\n       my $env =  shift;\n \n@@ -53,18 +52,25 @@ Plack::Middleware::Log4perl - Uses Log::Log4perl to configure logger\n\nBut this part of code were edited in both branches too:\n\nThe branch were started at this commit: 0a5ff8427\n\n6. git diff 0a5ff8427\n\n@@ -35,14 +35,28 @@ __END__\n \n =head1 NAME\n \n-Plack::Middleware::Log4perl - Uses Log::Log4perl to configure logger\n+Plack::Middleware::Log4perl - Uses Log::Log4perl to configure psgix.logger\n \n =head1 SYNOPSIS\n+  # How to use logger in your app\n+  my $app = sub {\n+      my $env =  shift;\n \n-  use Log::Log4perl;\n+      $env->{'psgix.logger'}({ level => 'error', message => 'Hi' });\n+\n+      return [\n+          '200',\n+          [ 'Content-Type' => 'text/plain' ],\n+          [ \"Hello World\" ],\n+      ];\n+  };\n\n7. git checkout master \n8. git diff 0a5ff8427\n\n@@ -39,28 +40,41 @@ Plack::Middleware::Log4perl - Uses Log::Log4perl to configure logger\n \n =head1 SYNOPSIS\n \n-  use Log::Log4perl;\n+  my $app = sub {\n+      my $env =  shift;\n+\n+      $env->{'psgix.logger'}({ level => 'error', message => 'Hi' });\n+\n+      return [\n+          '200',\n+          [ 'Content-Type' => 'text/plain' ],\n+          [ \"Hello World\" ],\n+      ];\n+  };\n+\n\nI repeat for emphasis. In the resulting file we have same code and not expect conflict.\n\nAt this point I have same changes on master and branch.\nmaster head is d095870\nbranch head is a3db36a\nfork point is 0a5ff84\n\nComparing step-by-step \n(A)   git diff 0a5ff84..d095870\n(B)   git diff 0a5ff84..a3db36a\nFind patches which apply to same lines\n =head1 SYNOPSIS\n \n-  use Log::Log4perl;\n+  my $app = sub {\n+      my $env =  shift;\n+\n+      $env->{'psgix.logger'}({ level => 'error', message => 'Hi' });\n+\n+      return [\n+          '200',\n+          [ 'Content-Type' => 'text/plain' ],\n+          [ \"Hello World\" ],\n+      ];\n+  };\n+\n\n =head1 SYNOPSIS\n+  # How to use logger in your app\n+  my $app = sub {\n+      my $env =  shift;\n \n-  use Log::Log4perl;\n+      $env->{'psgix.logger'}({ level => 'error', message => 'Hi' });\n+\n+      return [\n+          '200',\n+          [ 'Content-Type' => 'text/plain' ],\n+          [ \"Hello World\" ],\n+      ];\n+  };\n\nAnd check with \n(C)  git diff a3db36a..d095870\n =head1 SYNOPSIS\n-  # How to use logger in your app\n+\n   my $app = sub {\n       my $env =  shift;\n \n(D) So this merge conflict (the result of `git checkout master; git merge feature/doc_contribution`)\n@@@ -36,13 -35,13 +36,19 @@@ __END_\n  \n  =head1 NAME\n  \n- Plack::Middleware::Log4perl - Uses Log::Log4perl to configure logger\n+ Plack::Middleware::Log4perl - Uses Log::Log4perl to configure psgix.logger\n  \n  =head1 SYNOPSIS\n+   # How to use logger in your app\n+   my $app = sub {\n+       my $env =  shift;\n  \n++<<<<<<< HEAD\n +  my $app = sub {\n +      my $env =  shift;\n +\n++=======\n++>>>>>>> feature/doc_contribution\n        $env->{'psgix.logger'}({ level => 'error', message => 'Hi' });\n  \n        return [\n\ncan be simplified to:\n\n@@@ -36,13 -35,13 +36,19 @@@ __END_\n  \n  =head1 NAME\n  \n- Plack::Middleware::Log4perl - Uses Log::Log4perl to configure logger\n+ Plack::Middleware::Log4perl - Uses Log::Log4perl to configure psgix.logger\n  \n  =head1 SYNOPSIS\n+   # How to use logger in your app\n    my $app = sub {\n        my $env =  shift;\n  \n\nNEXT\nNext merge conflict seems this:\n(A)\n+  };\n+\n \n+  # Use your own Log4perl configuration\n+  use Log::Log4perl;\n   Log::Log4perl::init('/path/to/log4perl.conf');\n\n(B)\n+  };\n \n+\n+  # Initialization. Case#1\n+  use Log::Log4perl;\n   Log::Log4perl::init('/path/to/log4perl.conf');\n\nComparing to (C)\n@@ -53,18 +52,25 @@\n   };\n \n \n-  # Use your own Log4perl configuration\n+  # Initialization. Case#1\n   use Log::Log4perl;\n   Log::Log4perl::init('/path/to/log4perl.conf');\n\nSo current merge conflict (D) \n@@@ -51,20 -50,27 +57,33 @@@\n            [ \"Hello World\" ],\n        ];\n    };\n++<<<<<<< HEAD\n +\n +\n +  # Use your own Log4perl configuration\n++=======\n+ \n+ \n+   # Initialization. Case#1\n++>>>>>>> feature/doc_contribution\n    use Log::Log4perl;\n    Log::Log4perl::init('/path/to/log4perl.conf');\n\nCan be simplified to: (E) \n@@@ -51,20 -50,27 +57,33 @@@\n            [ \"Hello World\" ],\n        ];\n    };\n\n\n++<<<<<<< HEAD\n +  # Use your own Log4perl configuration\n++=======\n+   # Initialization. Case#1\n++>>>>>>> feature/doc_contribution\n    use Log::Log4perl;\n    Log::Log4perl::init('/path/to/log4perl.conf');\n\nNOTICE: in (C) only two lines are different.\n\nNEXT\n(A)\n-  # Or let middleware to configure log4perl\n-  enable \"Log4perl\", category => \"plack\", conf => '/path/to/log.conf';\n+  # Configure with Log4perl middleware options\n+  builder {\n+      enable \"Log4perl\", category => \"plack\", conf => '/path/to/log4perl.conf';\n+      $app;\n+  }\n\n(B)\n-  # Or let middleware to configure log4perl\n-  enable \"Log4perl\", category => \"plack\", conf => '/path/to/log.conf';\n+\n+  # Initialization. Case#2\n+  # Let middleware to configure log4perl\n+  builder {\n+      enable \"Log4perl\", category => \"plack\", conf => '/path/to/log4perl.conf';\n+      $app;\n+  }\n\n(C)\n\n\n-  # Configure with Log4perl middleware options\n+  # Initialization. Case#2\n+  # Let middleware to configure log4perl\n   builder {\n       enable \"Log4perl\", category => \"plack\", conf => '/path/to/log4perl.conf';\n       $app;\n\n\n(D)\n  \n++<<<<<<< HEAD\n +  # Configure with Log4perl middleware options\n++=======\n+ \n+   # Initialization. Case#2\n+   # Let middleware to configure log4perl\n++>>>>>>> feature/doc_contribution\n    builder {\n        enable \"Log4perl\", category => \"plack\", conf => '/path/to/log4perl.conf';\n        $app;\n\n->(E) Notice, that in (C) one line is deleted and two added\n++<<<<<<< HEAD\n +  # Configure with Log4perl middleware options\n++=======\n+   # Initialization. Case#2\n+   # Let middleware to configure log4perl\n++>>>>>>> feature/doc_contribution\n    builder {\n        enable \"Log4perl\", category => \"plack\", conf => '/path/to/log4perl.conf';\n        $app;\n\n\nNEXT\n(A)\n =head1 DESCRIPTION\n \n Log4perl is a L<Plack::Middleware> component that allows you to use\n-L<Log::Log4perl> to configure the logging object, C<psgix.logger>.\n+L<Log::Log4perl> to configure the logging object C<psgix.logger> for a\n+given category.\n \n =head1 CONFIGURATION\n\n(B)\n =head1 DESCRIPTION\n \n-Log4perl is a L<Plack::Middleware> component that allows you to use\n-L<Log::Log4perl> to configure the logging object, C<psgix.logger>.\n+Log4perl is a L<Plack::Middleware> component that initialize the logging object\n+C<psgix.logger> by L<Log::Log4perl> logger with giving C<category>.\n \n =head1 CONFIGURATION\n\n(C)\n@@ -72,9 +78,8 @@\n \n =head1 DESCRIPTION\n \n-Log4perl is a L<Plack::Middleware> component that allows you to use\n-L<Log::Log4perl> to configure the logging object C<psgix.logger> for a\n-given category.\n+Log4perl is a L<Plack::Middleware> component that initialize the logging object\n+C<psgix.logger> by L<Log::Log4perl> logger with giving C<category>.\n \n =head1 CONFIGURATION\n\n(D)\n@@@ -72,9 -78,8 +91,14 @@@\n  \n  =head1 DESCRIPTION\n  \n++<<<<<<< HEAD\n +Log4perl is a L<Plack::Middleware> component that allows you to use\n +L<Log::Log4perl> to configure the logging object C<psgix.logger> for a\n +given category.\n++=======\n+ Log4perl is a L<Plack::Middleware> component that initialize the logging object\n+ C<psgix.logger> by L<Log::Log4perl> logger with giving C<category>.\n++>>>>>>> feature/doc_contribution\n  \n  =head1 CONFIGURATION\n  \n\nIn this example (E) is same as (D)\n\n\n\nFeel free to ask how steps are done if you are not clear with mine explanation.\n"},{"id":"269598","messageId":"20150908070645.GH26331@sigill.intra.peff.net","threadId":"40294","inReplyTo":"856611441646146@web13j.yandex.ru","subject":"Re: Improving auto conflict resolving while merge","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-09-08T07:06:46Z","receivedAt":"2015-09-08T07:06:46Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Sep 07, 2015 at 08:15:46PM +0300, KES wrote:\n\n> 1. git clone https://github.com/KES777/Plack\n> [...]\n> At this point I have same changes on master and branch.\n> master head is d095870\n> branch head is a3db36a\n> fork point is 0a5ff84\n\nI tried re-merging d095870 and a3db36a. I think what is happening is\nthat even though you have many similar hunks near each, there are still\nsome differences in the area, and they are close enough that the merge\nisn't sure what is right. We err on the side of conservatism with\nconflicts, because it's hard to say what is dependent and what is not.\n\nFor example, if you have the content:\n\n  foo();\n  bar();\n  baz();\n\nand one side makes it:\n\n  foo();\n  x = 1;\n  bar();\n  baz();\n\nand the other side does:\n\n  foo();\n  bar();\n  y = 2;\n  baz();\n\nyou _could_ argue that those changes are independent (and write a merge\nalgorithm that silently merges them). They're touching two different\nlines, and doing two different things. But it's close enough that\nthere's a good chance the two need to be reconciled, and a human should\nat least take a look.\n\nI think what further confuses things in your case is that the content\nadded by the two sides contains a lot of similar lines (because of the\ncherry-pick), and the default \"merge\" conflict-markers try to shrink the\nsize of the conflicts.\n\nTry running:\n\n  git config merge.conflictstyle diff3\n\nand re-doing the merge. It will give you a much better sense of how git\nis breaking down the hunks (because it does not try to shrink the\nconflicts, and because it shows the base content for each conflict).\n\n-Peff\n"},{"id":"269631","messageId":"20150908220357.GD24159@sigill.intra.peff.net","threadId":"40294","inReplyTo":"1059528292.20150908210809@yandex.ru","subject":"Re: Improving auto conflict resolving while merge","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-09-08T22:03:57Z","receivedAt":"2015-09-08T22:03:57Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Sep 08, 2015 at 09:08:09PM -0300, Eugen Konkov wrote:\n\n> JK> you _could_ argue that those changes are independent But it's close \n> JK> enough that there's a good chance the two need to be reconciled, \n> JK> and a human should at least take a look.\n> \n> You are right and your words make sense. But this thought may apply\n> for this: We have one method/function about 200 lines. One author make\n> change at line 1 of this method and other on 199 line. Both changes\n> are done in one method so **human should at least take a look**\n\nRight, there is definitely a concept of \"close enough\" here, and git\ncannot catch everything. Semantic changes may even happen across files\n(e.g., function interface changes). So you do need to rely on things\nlike testing and compilation to verify a merge result.\n\nBut I would agree there is room for being able to tune the \"closeness\"\nof changes that cause a conflict. Right now that isn't implemented, and\nI'm not familiar enough with the xdiff merge code to even point you in\nthe right direction.\n\n-Peff\n"},{"id":"269616","messageId":"1059528292.20150908210809@yandex.ru","threadId":"40294","inReplyTo":"20150908070645.GH26331@sigill.intra.peff.net","subject":"Re[2]: Improving auto conflict resolving while merge","fromName":"Eugen Konkov","fromEmail":"kes-kes@yandex.ru","sentAt":"2015-09-09T00:08:09Z","receivedAt":"2015-09-09T00:08:09Z","isPatch":false,"sender":{"key":"kes-kes@yandex.ru","avatar":null},"body":"Hi, Jeff.\n\nJK> For example, if you have the content:\n\nJK>   foo();\nJK>   bar();\nJK>   baz();\n\nJK> and one side makes it:\n\nJK>   foo();\nJK>   x = 1;\nJK>   bar();\nJK>   baz();\n\nJK> and the other side does:\n\nJK>   foo();\nJK>   bar();\nJK>   y = 2;\nJK>   baz();\n\nJK> you _could_ argue that those changes are independent But it's close \nJK> enough that there's a good chance the two need to be reconciled, \nJK> and a human should at least take a look.\n\nYou are right and your words make sense. But this thought may apply for this: We have one method/function about 200 lines. One author make change at line 1 of this method and other on 199 line. Both changes are done in one method so **human should at least take a look**\n\nExample 2:\none author make change in method 1\nsecond author make change in method 2\nMethod 1 is called from method 2. Those changes work fine on its own branch and does not work together. **human should at least take a look**\n\nThis task is not for human and must be left for test system. So your example and two mine must not rise conflicts. This make useless noise. \n\nAnother example of useless merge conflicts\n\nA--C--C'--F--?     master\n \\  \\       /\n  B--C--D--G       feature\n\n\nHere I start branch feature.\nWhile developing update my branch from master by (C) changes\nWhile developing feature (C) were changed by (C') on master\nWhen I merge feature branch back to master I will get merge conflicts on lines in patch (C). I am not author of (C) and I do not care about it. Even  more I can not care and must not.\n\nImplemented option (like --theirs in last example) to not be so conservative and do not rise merge conflicts for enough close changes will be good.\n"}]}