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

[PATCH] git-merge: make it usable as the first class UI

From
Junio C Hamano <junkio@cox.net>
Date
Nov 20, 2006, 10:17 UTC
Message-ID
<7vu00u4e2d.fsf@assigned-by-dhcp.cox.net>
In-Reply-To
<7v8xi67qhq.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> writes:
Show 21 quoted lines
> So if we rename the current "git merge" to "git-merge--record"
> (or any name "git pull" uses internally to record the merge
> commit), and make "git merge" a synonym to "git pull .", and
> give a command line option -m to "git pull" to _affect_ the
> resulting merge message, I would think everybody would become
> quite happy.  It means:
>
>  - People can say "git merge this-branch" (which is internally
>    translated to "git pull . this-branch");
>
>  - People can say "git pull -m 'I am doing this merge for such
>    and such reason' $URL $branch" to _include_ that message in
>    the resulting merge commit;
>
>  - The same can be said about "git merge -m 'comment' $branch".
>
> I said _affect_ and _include_ in the above because I suspect
> that most of the time you do not want to _replace_ the
> autogenerated part ("Merge branch of repo", and if you are
> pulling from your subordinate trees the merge summary message as
> well).

I did a moral equivalent of the above without renaming the command "git merge" and will be pushing the result out in "pu" shortly.

The following is for commenting only -- it depends on an earlier patch in "pu".

-- >8 -- [PATCH] git-merge: make it usable as the first class UI

This teaches the oft-requested syntax
	git merge $commit

to implement merging the named commit to the current branch. This hopefully would make "git merge" usable as the first class UI instead of being a mere backend for "git pull".

Most notably, $commit above can be any committish, so you can say for example:

	git merge js/shortlog~2

to merge early part of a topic branch without merging the rest of it.

A custom merge message can be given with the new --message=<msg> parameter. The message is prepended in front of the usual "Merge ..." message autogenerated with fmt-merge-message.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 Documentation/git-merge.txt |   18 +++++++++---
 git-merge.sh                |   61 ++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 67 insertions(+), 12 deletions(-)
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index bebf30a..e2954aa 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -8,12 +8,14 @@ git-merge - Grand Unified Merge Driver
 
 SYNOPSIS
 --------
-'git-merge' [-n] [--no-commit] [-s <strategy>]... <msg> <head> <remote> <remote>...
-
+[verse]
+'git-merge' [-n] [--no-commit] [--squash] [-s <strategy>]...
+	[--reflog-action=<action>]
+	-m=<msg> <remote> <remote>...
 
 DESCRIPTION
 -----------
-This is the top-level user interface to the merge machinery
+This is the top-level interface to the merge machinery
 which drives multiple merge strategy scripts.
 
 
@@ -27,13 +29,19 @@ include::merge-options.txt[]
 	to give a good default for automated `git-merge` invocations.
 
 <head>::
-	our branch head commit.
+	Our branch head commit.  This has to be `HEAD`, so new
+	syntax does not require it
 
 <remote>::
-	other branch head merged into our branch.  You need at
+	Other branch head merged into our branch.  You need at
 	least one <remote>.  Specifying more than one <remote>
 	obviously means you are trying an Octopus.
 
+--reflog-action=<action>::
+	This is used internally when `git-pull` calls this command
+	to record that the merge was created by `pull` command
+	in the `ref-log` entry that results from the merge.
+
 include::merge-strategies.txt[]
 
 
diff --git a/git-merge.sh b/git-merge.sh
index 84c3acf..25deb1e 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -3,7 +3,8 @@
 # Copyright (c) 2005 Junio C Hamano
 #
 
-USAGE='[-n] [--no-commit] [--squash] [-s <strategy>]... <merge-message> <head> <remote>+'
+USAGE='[-n] [--no-commit] [--squash] [-s <strategy>] [--reflog-action=<action>] [-m=<merge-message>] <commit>+'
+
 . git-sh-setup
 
 LF='
@@ -92,7 +93,7 @@ finish () {
 
 case "$#" in 0) usage ;; esac
 
-rloga=
+rloga= have_message=
 while case "$#" in 0) break ;; esac
 do
 	case "$1" in
@@ -125,17 +126,63 @@ do
 	--reflog-action=*)
 		rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'`
 		;;
+	-m=*|--m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*)
+		merge_msg=`expr "z$1" : 'z-[^=]*=\(.*\)'`
+		have_message=t
+		;;
+	-m|--m|--me|--mes|--mess|--messa|--messag|--message)
+		shift
+		case "$#" in
+		1)	usage ;;
+		esac
+		merge_msg="$1"
+		have_message=t
+		;;
 	-*)	usage ;;
 	*)	break ;;
 	esac
 	shift
 done
 
-merge_msg="$1"
-shift
-head_arg="$1"
-head=$(git-rev-parse --verify "$1"^0) || usage
-shift
+# This could be traditional "merge <msg> HEAD <commit>..."  and the
+# way we can tell it is to see if the second token is HEAD, but some
+# people might have misused the interface and used a committish that
+# is the same as HEAD there instead.  Traditional format never would
+# have "-m" so it is an additional safety measure to check for it.
+
+if test -z "$have_message" &&
+	second_token=$(git-rev-parse --verify "$2^0" 2>/dev/null) &&
+	head_commit=$(git-rev-parse --verify "HEAD" 2>/dev/null) &&
+	test "$second_token" = "$head_commit"
+then
+	merge_msg="$1"
+	shift
+	head_arg="$1"
+	shift
+else
+	# We are invoked directly as the first-class UI.
+	head_arg=HEAD
+
+	# All the rest are the commits being merged; prepare
+	# the standard merge summary message to be appended to
+	# the given message.  If remote is invalid we will die
+	# later in the common codepath so we discard the error
+	# in this loop.
+	merge_name=$(for remote
+		do
+			rh=$(git-rev-parse --verify "$remote"^0 2>/dev/null)
+			if git show-ref -q --verify "refs/heads/$remote"
+			then
+				what=branch
+			else
+				what=commit
+			fi
+			echo "$rh		$what '$remote'"
+		done | git-fmt-merge-msg
+	)
+	merge_msg="${merge_msg:+$merge_msg$LF$LF}$merge_name"
+fi
+head=$(git-rev-parse --verify "$head_arg"^0) || usage
 
 # All the rest are remote heads
 test "$#" = 0 && usage ;# we need at least one remote head.
-- 
1.4.4.gbacc
Previous: Jakub NarebskiNext: Junio C Hamano
Message 6 of 7 in “Feature request: git-pull -e/--edit”
  1. linux@horizon.comNov 19, 2006
  2. Junio C HamanoNov 20, 2006
  3. linux@horizon.comNov 20, 2006
  4. Junio C HamanoNov 20, 2006
  5. Jakub NarebskiNov 20, 2006
  6. git-merge: make it usable as the first class UIJunio C Hamano, Nov 20, 2006
  7. Junio C HamanoNov 22, 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.