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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxx>
---

 * 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


-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]