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:
@ -8,12 +8,14 @@ git-merge - Grand Unified Merge Driver
|
|||||||
|
|
||||||
SYNOPSIS
|
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
|
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.
|
which drives multiple merge strategy scripts.
|
||||||
|
|
||||||
|
|
||||||
@ -27,13 +29,19 @@ include::merge-options.txt[]
|
|||||||
to give a good default for automated `git-merge` invocations.
|
to give a good default for automated `git-merge` invocations.
|
||||||
|
|
||||||
<head>::
|
<head>::
|
||||||
our branch head commit.
|
Our branch head commit. This has to be `HEAD`, so new
|
||||||
|
syntax does not require it
|
||||||
|
|
||||||
<remote>::
|
<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>
|
least one <remote>. Specifying more than one <remote>
|
||||||
obviously means you are trying an Octopus.
|
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[]
|
include::merge-strategies.txt[]
|
||||||
|
|
||||||
|
|
||||||
|
61
git-merge.sh
61
git-merge.sh
@ -3,7 +3,8 @@
|
|||||||
# Copyright (c) 2005 Junio C Hamano
|
# 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
|
. git-sh-setup
|
||||||
|
|
||||||
LF='
|
LF='
|
||||||
@ -92,7 +93,7 @@ finish () {
|
|||||||
|
|
||||||
case "$#" in 0) usage ;; esac
|
case "$#" in 0) usage ;; esac
|
||||||
|
|
||||||
rloga=
|
rloga= have_message=
|
||||||
while case "$#" in 0) break ;; esac
|
while case "$#" in 0) break ;; esac
|
||||||
do
|
do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@ -125,17 +126,63 @@ do
|
|||||||
--reflog-action=*)
|
--reflog-action=*)
|
||||||
rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'`
|
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 ;;
|
-*) usage ;;
|
||||||
*) break ;;
|
*) break ;;
|
||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
merge_msg="$1"
|
# This could be traditional "merge <msg> HEAD <commit>..." and the
|
||||||
shift
|
# way we can tell it is to see if the second token is HEAD, but some
|
||||||
head_arg="$1"
|
# people might have misused the interface and used a committish that
|
||||||
head=$(git-rev-parse --verify "$1"^0) || usage
|
# is the same as HEAD there instead. Traditional format never would
|
||||||
shift
|
# 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
|
# All the rest are remote heads
|
||||||
test "$#" = 0 && usage ;# we need at least one remote head.
|
test "$#" = 0 && usage ;# we need at least one remote head.
|
||||||
|
Reference in New Issue
Block a user