{"thread":{"id":"21102","subject":"Redundant merges?","startedAt":"2009-09-30T21:15:50Z","lastAt":"2009-10-01T03:34:11Z","messageCount":2,"participants":["skillzero@gmail.com","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"124048","messageId":"2729632a0909301415p7fe0da44l9453fca70bd523ca@mail.gmail.com","threadId":"21102","inReplyTo":null,"subject":"Redundant merges?","fromName":"","fromEmail":"skillzero@gmail.com","sentAt":"2009-09-30T21:15:50Z","receivedAt":"2009-09-30T21:15:50Z","isPatch":false,"sender":{"key":"skillzero@gmail.com","avatar":null},"body":"Is there a way to avoid redundant merges when merging maint to master\nif both maint and master have already merged in the same topic\nbranches? For example, assuming the git.git repository:\n\n1. A bug was found and a topic branch (with a merge-base at or before\nmaint) is created with the fix.\n2. The fix looks good so it's merged into master.\n3. maint is already past the freeze date so the fix isn't merged into\nmaint (bug is not super critical).\n4. maint is delayed for some reason and is accepting fixes.\n5. Topic branch from step 1 is merged into maint.\n6. maint is merged into master.\n\nWhat I see is two merge commits that merge the same topic. I think I\nunderstand why it's doing this (the merge commit is just another\ncommit so it merges it). But could it look at what the merge did and\nrealize that it already has the commit that the merge commit merged\nand do nothing in this case?\n"},{"id":"124064","messageId":"20091001033411.GB30094@coredump.intra.peff.net","threadId":"21102","inReplyTo":"2729632a0909301415p7fe0da44l9453fca70bd523ca@mail.gmail.com","subject":"Re: Redundant merges?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-10-01T03:34:11Z","receivedAt":"2009-10-01T03:34:11Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Sep 30, 2009 at 02:15:50PM -0700, skillzero@gmail.com wrote:\n\n> Is there a way to avoid redundant merges when merging maint to master\n> if both maint and master have already merged in the same topic\n> branches? For example, assuming the git.git repository:\n> \n> 1. A bug was found and a topic branch (with a merge-base at or before\n> maint) is created with the fix.\n> 2. The fix looks good so it's merged into master.\n> 3. maint is already past the freeze date so the fix isn't merged into\n> maint (bug is not super critical).\n> 4. maint is delayed for some reason and is accepting fixes.\n> 5. Topic branch from step 1 is merged into maint.\n> 6. maint is merged into master.\n\nNot without losing the shape of history (which is immutable in git).\n\nWe can suppress the merge if you do it in this order:\n\n  1. maint merges topic\n  2. master merges maint\n  3. master merges topic\n\nIn step (3), we see that we already have everything from topic. It works\nbecause the merges happened linearly along a line of history.\n\nBut you are merging in a non-linear way:\n\n  1. maint merges topic\n  2. master merges topic\n  3. master merges maint\n\nSo the merging of the topic branches happened \"simultaneously\" with\nrespect to the history topology. Any attempt to _not_ have a merge\ncommit between master and maint in step (3) would have to rewrite one of\nthe merges from (1) or (2), which would change history.\n\n> What I see is two merge commits that merge the same topic. I think I\n> understand why it's doing this (the merge commit is just another\n> commit so it merges it). But could it look at what the merge did and\n> realize that it already has the commit that the merge commit merged\n> and do nothing in this case?\n\nBut there isn't nothing to do. You don't have to merge the topic\nbranch, but you do have to merge the current state of 'maint'. In\naddition to keeping the history information (the fact that the topic was\nmerged, by whom, and when), we also need to record the state of any\nconflict resolution that occurred. And when we merge it into master, we\nneed to resolve any conflicts introduced by the different ways in which\nmaster and maint incorporated the changes from the topic.\n\nFor an example, try setting up the repo described by the script below,\nchecking \"gitk --all\", and then doing the merges in the two orders I\nspecified above. In the second case, you will get conflicts that need\nresolving for all three merges, whereas in the first, there can be no\nconflict for the step (3).\n\n-- >8 --\n#!/bin/sh\n\nrm -rf repo\nmkdir repo && cd repo && git init\n\ncommit() {\n  echo $1 >>file && git add file && git commit -m \"$1\"\n}\n\ncommit base\ngit checkout -b maint\ncommit maint\ngit checkout master\ncommit master\n\ngit checkout -b topic maint^\ncommit topic\n"}]}