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>
This commit is contained in:
Junio C Hamano 2006-11-20 01:06:09 -08:00
parent 7cdbff14d4
commit 17bcdad3b7
2 changed files with 67 additions and 12 deletions

View file

@ -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[]

View file

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