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

3 messages from 2006-11-30 to 2006-11-30. Participants: Johannes Schindelin, Carl Worth, Junio C Hamano.
Thread: https://gitlist.dev/t/43412

## Junio C Hamano, 2006-11-30 03:02

Subject: [PATCH] git-merge: preserve and merge local changes when doing fast forward
Message-ID: <7v1wnlmyba.fsf@assigned-by-dhcp.cox.net>
URL: https://gitlist.dev/e/7v1wnlmyba.fsf%40assigned-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


```

## Carl Worth, 2006-11-30 07:32

Subject: Re: [PATCH] git-merge: preserve and merge local changes when doing fast forward
Message-ID: <87psb5tmn9.wl%cworth@cworth.org>
URL: https://gitlist.dev/e/87psb5tmn9.wl%25cworth%40cworth.org
In-Reply-To: <7v1wnlmyba.fsf@assigned-by-dhcp.cox.net>

```
On Wed, 29 Nov 2006 19:02:33 -0800, Junio C Hamano wrote:
> 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.

This looks very appealing to me. I know I've often been frustrated
when git refuses to fast-forward just because I have dirty state, (and
stashing the diff manually into a patch file, then re-applying it
after fast forward is really annoying---getting work done in spite of
the tool and not because of it).

>  * 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,

As I said above it seems very reasonable to me. As for the problem you
mention here, isn't "no good way to recover from it" the real problem,
and not this merge possibility? And is there enough information in the
index file such that one could implement a way to recover from this?

-Carl

```

## Johannes Schindelin, 2006-11-30 10:32

Subject: Re: [PATCH] git-merge: preserve and merge local changes when doing fast forward
Message-ID: <Pine.LNX.4.63.0611301129410.30004@wbgn013.biozentrum.uni-wuerzburg.de>
URL: https://gitlist.dev/e/Pine.LNX.4.63.0611301129410.30004%40wbgn013.biozentrum.uni-wuerzburg.de
In-Reply-To: <7v1wnlmyba.fsf@assigned-by-dhcp.cox.net>

```
Hi,

On Wed, 29 Nov 2006, Junio C Hamano wrote:

> 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-<...

How about "-k|--keep-changes" or "-l|--local-changes", or 
"-p|--preserve-changes"?

BTW from a user's perspective, this operation _is_ a merge, not a 
checkout. So, IMHO the compatibility with that rarely used option of 
git-checkout is neglectable.

Ciao,

```
