git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] git-merge: preserve and merge local changes when doing fast forward

From
Junio C Hamano <junkio@cox.net>
Date
Nov 30, 2006, 03:02 UTC
Message-ID
<7v1wnlmyba.fsf@assigned-by-dhcp.cox.net>

The idea and the logic are identical to what "checkout -m" does when switching the branches. Instead of refusing the two-way merge, perform the three-way merge between the old head, the working tree and the new head, and leave the (potentially conflicted) merge result in the working tree.

If this turns out to be a sane thing to do, we probably should make the common logic between "checkout -m" and this into a built-in command.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 * I am not sure if this is worth doing in general; it can leave
   a huge mess if the conflict with the merge and the local
   change is too extensive and does not give a good way to
   recover from it, and that is why we require an explicit "-m"
   to "git checkout" for this behaviour.  Perhaps we would want
   a new option to git-merge to allow preserving the local
   changes, but the obvious candidate -m is taken for something
   else per recent popular request X-<...
 git-merge.sh |   42 +++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 41 insertions(+), 1 deletions(-)
diff --git a/git-merge.sh b/git-merge.sh
index 75af10d..324991f 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -91,6 +91,46 @@ finish () {
 	esac
 }
 
+merge_local_changes () {
+	merge_error=$(git-read-tree -m -u $1 $2 2>&1) || (
+		# Match the index to the working tree, and do a three-way.
+		git diff-files --name-only |
+		git update-index --remove --stdin &&
+		work=`git write-tree` &&
+		git read-tree --reset -u $2 &&
+		git read-tree -m -u --aggressive $1 $2 $work || exit
+
+		echo >&2 "Carrying local changes forward."
+		if result=`git write-tree 2>/dev/null`
+		then
+			echo >&2 "Trivially automerged."
+		else
+			git merge-index -o git-merge-one-file -a
+		fi
+
+		# Do not register the cleanly merged paths in the index
+		# yet; this is not a real merge before committing, but
+		# just carrying the working tree changes along.
+		unmerged=`git ls-files -u`
+		git read-tree --reset $2
+		case "$unmerged" in
+		'')	;;
+		*)
+			(
+				z40=0000000000000000000000000000000000000000
+				echo "$unmerged" |
+				sed -e 's/^[0-7]* [0-9a-f]* /'"0 $z40 /"
+				echo "$unmerged"
+			) | git update-index --index-info
+
+			echo >&2 "Conflicts in locally modified files:"
+			git diff --name-only --diff-filter=U >&2
+			;;
+		esac
+		exit 0
+	)
+}
+
 case "$#" in 0) usage ;; esac
 
 rloga= have_message=
@@ -264,7 +304,7 @@ f,*)
 	echo "Updating $(git-rev-parse --short $head)..$(git-rev-parse --short $1)"
 	git-update-index --refresh 2>/dev/null
 	new_head=$(git-rev-parse --verify "$1^0") &&
-	git-read-tree -u -v -m $head "$new_head" &&
+	merge_local_changes $head $new_head &&
 	finish "$new_head" "Fast forward"
 	dropsave
 	exit 0
-- 
1.4.4.1.gc419
Next: Carl Worth
Message 1 of 3 in “git-merge: preserve and merge local changes when doing fast forward”
  1. git-merge: preserve and merge local changes when doing fast forwardJunio C Hamano, Nov 30, 2006
  2. Carl WorthNov 30, 2006
  3. Johannes SchindelinNov 30, 2006

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.