{"thread":{"id":"43412","subject":"Re: [PATCH] git-merge: preserve and merge local changes when doing fast forward","startedAt":"2006-11-30T03:02:33Z","lastAt":"2006-11-30T10:32:03Z","messageCount":3,"participants":["Johannes Schindelin","Carl Worth","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"298577","messageId":"7v1wnlmyba.fsf@assigned-by-dhcp.cox.net","threadId":"43412","inReplyTo":null,"subject":"[PATCH] git-merge: preserve and merge local changes when doing fast forward","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-11-30T03:02:33Z","receivedAt":"2006-11-30T03:02:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The idea and the logic are identical to what \"checkout -m\" does\nwhen switching the branches.  Instead of refusing the two-way\nmerge, perform the three-way merge between the old head, the\nworking tree and the new head, and leave the (potentially\nconflicted) merge result in the working tree.\n\nIf this turns out to be a sane thing to do, we probably should\nmake the common logic between \"checkout -m\" and this into a\nbuilt-in command.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n * I am not sure if this is worth doing in general; it can leave\n   a huge mess if the conflict with the merge and the local\n   change is too extensive and does not give a good way to\n   recover from it, and that is why we require an explicit \"-m\"\n   to \"git checkout\" for this behaviour.  Perhaps we would want\n   a new option to git-merge to allow preserving the local\n   changes, but the obvious candidate -m is taken for something\n   else per recent popular request X-<...\n\n git-merge.sh |   42 +++++++++++++++++++++++++++++++++++++++++-\n 1 files changed, 41 insertions(+), 1 deletions(-)\n\ndiff --git a/git-merge.sh b/git-merge.sh\nindex 75af10d..324991f 100755\n--- a/git-merge.sh\n+++ b/git-merge.sh\n@@ -91,6 +91,46 @@ finish () {\n \tesac\n }\n \n+merge_local_changes () {\n+\tmerge_error=$(git-read-tree -m -u $1 $2 2>&1) || (\n+\t\t# Match the index to the working tree, and do a three-way.\n+\t\tgit diff-files --name-only |\n+\t\tgit update-index --remove --stdin &&\n+\t\twork=`git write-tree` &&\n+\t\tgit read-tree --reset -u $2 &&\n+\t\tgit read-tree -m -u --aggressive $1 $2 $work || exit\n+\n+\t\techo >&2 \"Carrying local changes forward.\"\n+\t\tif result=`git write-tree 2>/dev/null`\n+\t\tthen\n+\t\t\techo >&2 \"Trivially automerged.\"\n+\t\telse\n+\t\t\tgit merge-index -o git-merge-one-file -a\n+\t\tfi\n+\n+\t\t# Do not register the cleanly merged paths in the index\n+\t\t# yet; this is not a real merge before committing, but\n+\t\t# just carrying the working tree changes along.\n+\t\tunmerged=`git ls-files -u`\n+\t\tgit read-tree --reset $2\n+\t\tcase \"$unmerged\" in\n+\t\t'')\t;;\n+\t\t*)\n+\t\t\t(\n+\t\t\t\tz40=0000000000000000000000000000000000000000\n+\t\t\t\techo \"$unmerged\" |\n+\t\t\t\tsed -e 's/^[0-7]* [0-9a-f]* /'\"0 $z40 /\"\n+\t\t\t\techo \"$unmerged\"\n+\t\t\t) | git update-index --index-info\n+\n+\t\t\techo >&2 \"Conflicts in locally modified files:\"\n+\t\t\tgit diff --name-only --diff-filter=U >&2\n+\t\t\t;;\n+\t\tesac\n+\t\texit 0\n+\t)\n+}\n+\n case \"$#\" in 0) usage ;; esac\n \n rloga= have_message=\n@@ -264,7 +304,7 @@ f,*)\n \techo \"Updating $(git-rev-parse --short $head)..$(git-rev-parse --short $1)\"\n \tgit-update-index --refresh 2>/dev/null\n \tnew_head=$(git-rev-parse --verify \"$1^0\") &&\n-\tgit-read-tree -u -v -m $head \"$new_head\" &&\n+\tmerge_local_changes $head $new_head &&\n \tfinish \"$new_head\" \"Fast forward\"\n \tdropsave\n \texit 0\n-- \n1.4.4.1.gc419\n\n"},{"id":"296339","messageId":"87psb5tmn9.wl%cworth@cworth.org","threadId":"43412","inReplyTo":"7v1wnlmyba.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git-merge: preserve and merge local changes when doing fast forward","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2006-11-30T07:32:42Z","receivedAt":"2006-11-30T07:32:42Z","isPatch":true,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Wed, 29 Nov 2006 19:02:33 -0800, Junio C Hamano wrote:\n> The idea and the logic are identical to what \"checkout -m\" does\n> when switching the branches.  Instead of refusing the two-way\n> merge, perform the three-way merge between the old head, the\n> working tree and the new head, and leave the (potentially\n> conflicted) merge result in the working tree.\n\nThis looks very appealing to me. I know I've often been frustrated\nwhen git refuses to fast-forward just because I have dirty state, (and\nstashing the diff manually into a patch file, then re-applying it\nafter fast forward is really annoying---getting work done in spite of\nthe tool and not because of it).\n\n>  * I am not sure if this is worth doing in general; it can leave\n>    a huge mess if the conflict with the merge and the local\n>    change is too extensive and does not give a good way to\n>    recover from it,\n\nAs I said above it seems very reasonable to me. As for the problem you\nmention here, isn't \"no good way to recover from it\" the real problem,\nand not this merge possibility? And is there enough information in the\nindex file such that one could implement a way to recover from this?\n\n-Carl\n"},{"id":"294657","messageId":"Pine.LNX.4.63.0611301129410.30004@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43412","inReplyTo":"7v1wnlmyba.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] git-merge: preserve and merge local changes when doing fast forward","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-11-30T10:32:03Z","receivedAt":"2006-11-30T10:32:03Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 29 Nov 2006, Junio C Hamano wrote:\n\n> Perhaps we would want a new option to git-merge to allow preserving the \n> local changes, but the obvious candidate -m is taken for something else \n> per recent popular request X-<...\n\nHow about \"-k|--keep-changes\" or \"-l|--local-changes\", or \n\"-p|--preserve-changes\"?\n\nBTW from a user's perspective, this operation _is_ a merge, not a \ncheckout. So, IMHO the compatibility with that rarely used option of \ngit-checkout is neglectable.\n\nCiao,\n"}]}