{"thread":{"id":"37216","subject":"Amending merge commits?","startedAt":"2014-07-25T22:03:14Z","lastAt":"2014-07-28T20:53:24Z","messageCount":8,"participants":["Besen, David","David Besen","Jonathan Nieder","Sergei Organov"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"246748","messageId":"22F01493C523F940B4B5E53BB6D0F5352275F207@G5W2738.americas.hpqcorp.net","threadId":"37216","inReplyTo":null,"subject":"Amending merge commits?","fromName":"Besen, David","fromEmail":"david.besen@hp.com","sentAt":"2014-07-25T22:03:14Z","receivedAt":"2014-07-25T22:03:14Z","isPatch":false,"sender":{"key":"david.besen@hp.com","avatar":null},"body":"\nHi folks,\n\nI think one of my coworkers has stumbled on a git bug -- if you amend a merge commit, and then pull, your amends are lost.\n\nIs this expected behavior?\n\nI've reproduced the problem in a script (attached).  I ran it against a couple of versions of git (1.7.1, 1.7.9, 1.8.4, 2.0.0) and in each case it seemed to lose the amend.\n\n- Dave\n\n"},{"id":"246750","messageId":"loom.20140726T001014-124@post.gmane.org","threadId":"37216","inReplyTo":"22F01493C523F940B4B5E53BB6D0F5352275F207@G5W2738.americas.hpqcorp.net","subject":"Re: Amending merge commits?","fromName":"David Besen","fromEmail":"david.besen@hp.com","sentAt":"2014-07-25T22:11:02Z","receivedAt":"2014-07-25T22:11:02Z","isPatch":false,"sender":{"key":"david.besen@hp.com","avatar":null},"body":"Besen, David <david.besen <at> hp.com> writes:\n\n> \n> \n> Hi folks,\n> \n> I think one of my coworkers has stumbled on a git bug -- if you amend a \nmerge commit, and then pull, your amends\n> are lost.\n> \n> Is this expected behavior?\n> \n> I've reproduced the problem in a script (attached).  I ran it against a \ncouple of versions of git (1.7.1,\n> 1.7.9, 1.8.4, 2.0.0) and in each case it seemed to lose the amend.\n> \n> - Dave\n> \n> \n> Attachment (amend-merge.sh): application/octet-stream, 1061 bytes\n\n\nWhoops, accidentally encoded the script, here it is inline:\n\n#!/bin/bash\n\nset -ex\n\nif [ -z \"$GIT\" ]; then GIT=git; fi\nGIT_MERGE_AUTOEDIT=no\n\n# Clean up from the last run\nrm -rf repo.git repo repo2 || :\n\n# Set up a bare \"remote\" repo\n$GIT init --bare repo.git\n\n# Check out the \"remote\" repo\n$GIT clone repo.git repo\n\n# Add a commit\ncd repo\necho \"file\" > file.txt\n$GIT add file.txt\n$GIT commit -m \"Add file.txt\"\n$GIT push origin master\n\n# Make a branch\n$GIT checkout -b mybranch\n\n# Add a commit on the branch\necho \"mybranch\" >> file.txt\n$GIT add .\n$GIT commit -m \"Add 'mybranch' line\"\n\n# Go back to master\n$GIT checkout master\n\n# Merge in mybranch to create a merge commit\n$GIT merge --no-ff mybranch\n\n# Push that back\n$GIT push\n\n# Amend the merge commit\necho \"amended\" >> file.txt\n$GIT add .\n$GIT commit -C HEAD --amend\n\ncd ..\n\n# Make a second checkout\n$GIT clone repo.git repo2\ncd repo2\n\n# Add some unrelated changes to be pulled\necho \"repo2\" > file2.txt\n$GIT add .\n$GIT commit -m \"Add file2\"\n$GIT push\n\ncd ..\ncd repo\n\n# Pull\n$GIT pull --rebase\n\n# Now, we expect the text \"amended\" to be in file.txt\ngrep amended file.txt\n"},{"id":"246751","messageId":"20140725221911.GL12427@google.com","threadId":"37216","inReplyTo":"22F01493C523F940B4B5E53BB6D0F5352275F207@G5W2738.americas.hpqcorp.net","subject":"Re: Amending merge commits?","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2014-07-25T22:19:11Z","receivedAt":"2014-07-25T22:19:11Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Besen, David wrote:\n\n> I think one of my coworkers has stumbled on a git bug -- if you\n> amend a merge commit, and then pull, your amends are lost.\n\nThis is how pull --rebase works.  It turns your single-parent commits\ninto a sequence of patches on top of upstream and completely ignores\nyour merge commits.\n\nThere is a --rebase=preserve option that makes a halfhearted attempt\nto preserve your merges --- perhaps that would help?  The\ngit-rebase(1) documentation has more details.\n\nIn an ideal world, I think pull --rebase would do the following:\n\n 1. Do the same thing it does today\n 2. Behind the scenes, *also* try a 'pull --merge' but don't save\n    the result.\n 3. Compare the results.  If they differ, show a diff and explain\n    to the user what happened.\n\nI may be the only one that wants that, though.\n\nHope that helps,\nJonathan\n"},{"id":"246752","messageId":"22F01493C523F940B4B5E53BB6D0F5352275F25B@G5W2738.americas.hpqcorp.net","threadId":"37216","inReplyTo":"20140725221911.GL12427@google.com","subject":"RE: Amending merge commits?","fromName":"Besen, David","fromEmail":"david.besen@hp.com","sentAt":"2014-07-25T22:23:37Z","receivedAt":"2014-07-25T22:23:37Z","isPatch":false,"sender":{"key":"david.besen@hp.com","avatar":null},"body":"Ah thanks, I'll RTFM better in the future.\n\n- Dave\n\n-----Original Message-----\nFrom: Jonathan Nieder [mailto:jrnieder@gmail.com] \nSent: Friday, July 25, 2014 4:19 PM\nTo: Besen, David\nCc: git@vger.kernel.org\nSubject: Re: Amending merge commits?\n\nBesen, David wrote:\n\n> I think one of my coworkers has stumbled on a git bug -- if you\n> amend a merge commit, and then pull, your amends are lost.\n\nThis is how pull --rebase works.  It turns your single-parent commits\ninto a sequence of patches on top of upstream and completely ignores\nyour merge commits.\n\nThere is a --rebase=preserve option that makes a halfhearted attempt\nto preserve your merges --- perhaps that would help?  The\ngit-rebase(1) documentation has more details.\n\nIn an ideal world, I think pull --rebase would do the following:\n\n 1. Do the same thing it does today\n 2. Behind the scenes, *also* try a 'pull --merge' but don't save\n    the result.\n 3. Compare the results.  If they differ, show a diff and explain\n    to the user what happened.\n\nI may be the only one that wants that, though.\n\nHope that helps,\nJonathan\n"},{"id":"246753","messageId":"20140725223146.GM12427@google.com","threadId":"37216","inReplyTo":"22F01493C523F940B4B5E53BB6D0F5352275F25B@G5W2738.americas.hpqcorp.net","subject":"Re: Amending merge commits?","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2014-07-25T22:31:46Z","receivedAt":"2014-07-25T22:31:46Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"David Besen wrote:\n> Jonathan Nieder wrote:\n\n>> This is how pull --rebase works.  It turns your single-parent commits\n>> into a sequence of patches on top of upstream and completely ignores\n>> your merge commits.\n>>\n>> There is a --rebase=preserve option that makes a halfhearted attempt\n>> to preserve your merges --- perhaps that would help?  The\n>> git-rebase(1) documentation has more details.\n>\n> Ah thanks, I'll RTFM better in the future.\n\nNo, not a problem.  It's very useful to see examples of where git's\nbehavior was counterintuitive and the documentation was more obscure\nthan it could have been.\n\nI should also emphasize the \"halfhearted\" above.  There's a lot of\nroom for improvement in rebase --preserve-merges's handling of \"evil\"\nand otherwise amended merges.\n\nThanks again,\nJonathan\n"},{"id":"246831","messageId":"87vbqhb7g9.fsf@osv.gnss.ru","threadId":"37216","inReplyTo":"20140725223146.GM12427@google.com","subject":"Re: Amending merge commits?","fromName":"Sergei Organov","fromEmail":"osv@javad.com","sentAt":"2014-07-28T19:37:42Z","receivedAt":"2014-07-28T19:37:42Z","isPatch":false,"sender":{"key":"osv@javad.com","avatar":null},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> David Besen wrote:\n>> Jonathan Nieder wrote:\n>\n>>> This is how pull --rebase works.  It turns your single-parent commits\n>>> into a sequence of patches on top of upstream and completely ignores\n>>> your merge commits.\n>>>\n>>> There is a --rebase=preserve option that makes a halfhearted attempt\n>>> to preserve your merges --- perhaps that would help?  The\n>>> git-rebase(1) documentation has more details.\n>>\n>> Ah thanks, I'll RTFM better in the future.\n>\n> No, not a problem.  It's very useful to see examples of where git's\n> behavior was counterintuitive and the documentation was more obscure\n> than it could have been.\n\nShould documentaion warn that \"git pull --rebase=true\" (and\npull.merge=true configuration) could be harmful, and that\n--rebase=preserve (and pull.merge=preserve) should better be used\ninstead?\n\nIs there any scenario at all where pull --rebase=true wins over\npreserve?\n\n-- \nSergey.\n"},{"id":"246832","messageId":"20140728200037.GN12427@google.com","threadId":"37216","inReplyTo":"87vbqhb7g9.fsf@osv.gnss.ru","subject":"Re: Amending merge commits?","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2014-07-28T20:00:37Z","receivedAt":"2014-07-28T20:00:37Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Sergei Organov wrote:\n\n> Is there any scenario at all where pull --rebase=true wins over\n> preserve?\n\nBasically always in my book. ;-)\n\nWhen people turn on 'pull --rebase', they are asking for a clean,\nsimplified history where their changes are small discrete patches in a\nclump on top of upstream.\n\nWhen someone has made a merge by mistake (with 'git pull' before\nremembering to do an autosetuprebase, or with 'git merge' instead of\ncherry-picking some patches they needed), the current --rebase=true\nbehavior can be a good way of cleaning up.\n\nThat said, in some specific workflows, --rebase=preserve may work\nbetter than --rebase=true.  My hunch is that even those workflows are\nnot currently handled well with --rebase=preserve, alas.\n\nA clearer explanation of --rebase (maybe with sub-headings for each\nchoice *true*, *false*, and *preserve*?) sounds useful.  An\nillustration in the EXAMPLES section of git-pull(1) of the difference\nbetween these three modes and when to use them would be even more\nhelpful.\n\nThanks,\nJonathan\n"},{"id":"246834","messageId":"87lhrdb3y3.fsf@osv.gnss.ru","threadId":"37216","inReplyTo":"20140728200037.GN12427@google.com","subject":"Re: Amending merge commits?","fromName":"Sergei Organov","fromEmail":"osv@javad.com","sentAt":"2014-07-28T20:53:24Z","receivedAt":"2014-07-28T20:53:24Z","isPatch":false,"sender":{"key":"osv@javad.com","avatar":null},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> Sergei Organov wrote:\n>\n>> Is there any scenario at all where pull --rebase=true wins over\n>> preserve?\n>\n> Basically always in my book. ;-)\n>\n> When people turn on 'pull --rebase', they are asking for a clean,\n> simplified history where their changes are small discrete patches in a\n> clump on top of upstream.\n\nI think they rather ask for avoiding tons of meaningless automatic\nmerges resulting from periodic pulling from upstream.\n\nThose subset of the above who only do small discrete patches don't do\nmerges to their tracking branches, except by mistake, right? If so,\n'pull --rebase=preserve' makes no difference compared to --rebase=true\nto their normal workflow. Moreover,if someone merges something to his\ntracking branch by mistake, how is it different from making merge to any\nother branch by mistake? Just fix the mistake by resetting to previous\nstate.\n\nOn the other hand, if someone decides to merge something else to his\ntracking branch by purpose, both --rebase=preserve and --rebase=false\nperform as expected, while --rebase=true may easily lead to huge\nsurprise. Please refer also to this thread for one such case:\n\nhttp://www.mail-archive.com/git%40vger.kernel.org/msg55605.html\n\n> When someone has made a merge by mistake (with 'git pull' before\n> remembering to do an autosetuprebase, or with 'git merge' instead of\n> cherry-picking some patches they needed), the current --rebase=true\n> behavior can be a good way of cleaning up.\n\nOnce again, in case of mistake they are free to use --rebase=true, and\neven then using 'git rebase' directly is probably cleaner. That said, I\ndon't argue --rebase=true could be sometimes useful. It's just that I\nthink --rebase=preserve is safer, so it should be a good idea to suggest\nto use it (in favor of --rebase=true) in general.\n\n> That said, in some specific workflows, --rebase=preserve may work\n> better than --rebase=true.\n\nIt does indeed, and I don't think my aforementioned workflow is too\nspecific.\n\n> My hunch is that even those workflows are not currently handled well\n> with --rebase=preserve, alas.\n\n--rebase=preserve works fine for the aforementioned workflow. At least\nsimple tests I performed so far ran fine. I'd like to learn though which\nnasty drawbacks --rebase=preserve has for tracking branches compared to\n--rebase=true, if any.\n\n> A clearer explanation of --rebase (maybe with sub-headings for each\n> choice *true*, *false*, and *preserve*?) sounds useful.  An\n> illustration in the EXAMPLES section of git-pull(1) of the difference\n> between these three modes and when to use them would be even more\n> helpful.\n\nThat would be an improvement anyway, indeed.\n\n-- \nSergey.\n"}]}