about summary refs log tree commit diff
path: root/git-merge-octopus.sh
diff options
context:
space:
mode:
authorVincent Ambo <Vincent Ambo>2020-01-11T23·36+0000
committerVincent Ambo <Vincent Ambo>2020-01-11T23·36+0000
commit1b593e1ea4d2af0f6444d9a7788d5d99abd6fde5 (patch)
treee3accb9beed5c4c1b5a05c99db71ab2841f0ed04 /git-merge-octopus.sh
Squashed 'third_party/git/' content from commit cb71568594
git-subtree-dir: third_party/git
git-subtree-split: cb715685942260375e1eb8153b0768a376e4ece7
Diffstat (limited to 'git-merge-octopus.sh')
-rwxr-xr-xgit-merge-octopus.sh112
1 files changed, 112 insertions, 0 deletions
diff --git a/git-merge-octopus.sh b/git-merge-octopus.sh
new file mode 100755
index 000000000000..7d19d379512b
--- /dev/null
+++ b/git-merge-octopus.sh
@@ -0,0 +1,112 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano
+#
+# Resolve two or more trees.
+#
+
+. git-sh-setup
+
+LF='
+'
+
+# The first parameters up to -- are merge bases; the rest are heads.
+bases= head= remotes= sep_seen=
+for arg
+do
+	case ",$sep_seen,$head,$arg," in
+	*,--,)
+		sep_seen=yes
+		;;
+	,yes,,*)
+		head=$arg
+		;;
+	,yes,*)
+		remotes="$remotes$arg "
+		;;
+	*)
+		bases="$bases$arg "
+		;;
+	esac
+done
+
+# Reject if this is not an octopus -- resolve should be used instead.
+case "$remotes" in
+?*' '?*)
+	;;
+*)
+	exit 2 ;;
+esac
+
+# MRC is the current "merge reference commit"
+# MRT is the current "merge result tree"
+
+if ! git diff-index --quiet --cached HEAD --
+then
+    gettextln "Error: Your local changes to the following files would be overwritten by merge"
+    git diff-index --cached --name-only HEAD -- | sed -e 's/^/    /'
+    exit 2
+fi
+MRC=$(git rev-parse --verify -q $head)
+MRT=$(git write-tree)
+NON_FF_MERGE=0
+OCTOPUS_FAILURE=0
+for SHA1 in $remotes
+do
+	case "$OCTOPUS_FAILURE" in
+	1)
+		# We allow only last one to have a hand-resolvable
+		# conflicts.  Last round failed and we still had
+		# a head to merge.
+		gettextln "Automated merge did not work."
+		gettextln "Should not be doing an octopus."
+		exit 2
+	esac
+
+	eval pretty_name=\${GITHEAD_$SHA1:-$SHA1}
+	if test "$SHA1" = "$pretty_name"
+	then
+		SHA1_UP="$(echo "$SHA1" | tr a-z A-Z)"
+		eval pretty_name=\${GITHEAD_$SHA1_UP:-$pretty_name}
+	fi
+	common=$(git merge-base --all $SHA1 $MRC) ||
+		die "$(eval_gettext "Unable to find common commit with \$pretty_name")"
+
+	case "$LF$common$LF" in
+	*"$LF$SHA1$LF"*)
+		eval_gettextln "Already up to date with \$pretty_name"
+		continue
+		;;
+	esac
+
+	if test "$common,$NON_FF_MERGE" = "$MRC,0"
+	then
+		# The first head being merged was a fast-forward.
+		# Advance MRC to the head being merged, and use that
+		# tree as the intermediate result of the merge.
+		# We still need to count this as part of the parent set.
+
+		eval_gettextln "Fast-forwarding to: \$pretty_name"
+		git read-tree -u -m $head $SHA1 || exit
+		MRC=$SHA1 MRT=$(git write-tree)
+		continue
+	fi
+
+	NON_FF_MERGE=1
+
+	eval_gettextln "Trying simple merge with \$pretty_name"
+	git read-tree -u -m --aggressive  $common $MRT $SHA1 || exit 2
+	next=$(git write-tree 2>/dev/null)
+	if test $? -ne 0
+	then
+		gettextln "Simple merge did not work, trying automatic merge."
+		git merge-index -o git-merge-one-file -a ||
+		OCTOPUS_FAILURE=1
+		next=$(git write-tree 2>/dev/null)
+	fi
+
+	MRC="$MRC $SHA1"
+	MRT=$next
+done
+
+exit "$OCTOPUS_FAILURE"