Merge branch 'jn/update-contrib-example-merge'

* jn/update-contrib-example-merge: (24 commits)
  merge script: learn --[no-]rerere-autoupdate
  merge script: notice @{-1} shorthand
  merge script: handle --no-ff --no-commit correctly
  merge script: --ff-only to disallow true merge
  merge script: handle many-way octopus
  merge script: handle -m --log correctly
  merge script: forbid merge -s index
  merge script: allow custom strategies
  merge script: merge -X<option>
  merge script: improve log message subject
  merge script: refuse to merge during merge
  merge script: tweak unmerged files message to match builtin
  merge script: --squash, --ff from unborn branch are errors
  fmt-merge-msg -m to override merge title
  merge-base --independent to print reduced parent list in a merge
  merge-base --octopus to mimic show-branch --merge-base
  Documentation: add a SEE ALSO section for merge-base
  t6200 (fmt-merge-msg): style nitpicks
  t6010 (merge-base): modernize style
  t7600 (merge): test merge from branch yet to be born
  ...
This commit is contained in:
Junio C Hamano 2010-09-03 09:43:42 -07:00
commit 2b916ffa18
9 changed files with 687 additions and 548 deletions

View file

@ -9,8 +9,8 @@ git-fmt-merge-msg - Produce a merge commit message
SYNOPSIS
--------
[verse]
'git fmt-merge-msg' [--log | --no-log] <$GIT_DIR/FETCH_HEAD
'git fmt-merge-msg' [--log | --no-log] -F <file>
'git fmt-merge-msg' [-m <message>] [--log | --no-log] <$GIT_DIR/FETCH_HEAD
'git fmt-merge-msg' [-m <message>] [--log | --no-log] -F <file>
DESCRIPTION
-----------
@ -38,6 +38,11 @@ OPTIONS
Synonyms to --log and --no-log; these are deprecated and will be
removed in the future.
-m <message>::
--message <message>::
Use <message> instead of the branch names for the first line
of the log message. For use with `--log`.
-F <file>::
--file <file>::
Take the list of merged objects from <file> instead of

View file

@ -8,7 +8,9 @@ git-merge-base - Find as good common ancestors as possible for a merge
SYNOPSIS
--------
'git merge-base' [-a|--all] <commit> <commit>...
[verse]
'git merge-base' [-a|--all] [--octopus] <commit> <commit>...
'git merge-base' --independent <commit>...
DESCRIPTION
-----------
@ -20,12 +22,12 @@ that does not have any better common ancestor is a 'best common
ancestor', i.e. a 'merge base'. Note that there can be more than one
merge base for a pair of commits.
Among the two commits to compute the merge base from, one is specified by
the first commit argument on the command line; the other commit is a
(possibly hypothetical) commit that is a merge across all the remaining
commits on the command line. As the most common special case, specifying only
two commits on the command line means computing the merge base between
the given two commits.
Unless `--octopus` is given, among the two commits to compute the merge
base from, one is specified by the first commit argument on the command
line; the other commit is a (possibly hypothetical) commit that is a merge
across all the remaining commits on the command line. As the most common
special case, specifying only two commits on the command line means
computing the merge base between the given two commits.
As a consequence, the 'merge base' is not necessarily contained in each of the
commit arguments if more than two commits are specified. This is different
@ -37,6 +39,18 @@ OPTIONS
--all::
Output all merge bases for the commits, instead of just one.
--octopus::
Compute the best common ancestors of all supplied commits,
in preparation for an n-way merge. This mimics the behavior
of 'git show-branch --merge-base'.
--independent::
Instead of printing merge bases, print a minimal subset of
the supplied commits with the same ancestors. In other words,
among the commits given, list those which cannot be reached
from any other. This mimics the behavior of 'git show-branch
--independent'.
DISCUSSION
----------
@ -96,6 +110,12 @@ Documentation
--------------
Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
See also
--------
linkgit:git-rev-list[1],
linkgit:git-show-branch[1],
linkgit:git-merge[1]
GIT
---
Part of the linkgit:git[1] suite

View file

@ -7,7 +7,7 @@
#include "string-list.h"
static const char * const fmt_merge_msg_usage[] = {
"git fmt-merge-msg [--log|--no-log] [--file <file>]",
"git fmt-merge-msg [-m <message>] [--log|--no-log] [--file <file>]",
NULL
};
@ -319,11 +319,14 @@ int fmt_merge_msg_shortlog(struct strbuf *in, struct strbuf *out) {
int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
{
const char *inpath = NULL;
const char *message = NULL;
struct option options[] = {
OPT_BOOLEAN(0, "log", &merge_summary, "populate log with the shortlog"),
{ OPTION_BOOLEAN, 0, "summary", &merge_summary, NULL,
"alias for --log (deprecated)",
PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
OPT_STRING('m', "message", &message, "text",
"use <text> as start of message"),
OPT_FILENAME('F', "file", &inpath, "file to read from"),
OPT_END()
};
@ -337,6 +340,12 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
0);
if (argc > 0)
usage_with_options(fmt_merge_msg_usage, options);
if (message && !merge_summary) {
char nl = '\n';
write_in_full(STDOUT_FILENO, message, strlen(message));
write_in_full(STDOUT_FILENO, &nl, 1);
return 0;
}
if (inpath && strcmp(inpath, "-")) {
in = fopen(inpath, "r");
@ -346,7 +355,12 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
if (strbuf_read(&input, fileno(in), 0) < 0)
die_errno("could not read input file");
ret = fmt_merge_msg(merge_summary, &input, &output);
if (message) {
strbuf_addstr(&output, message);
ret = fmt_merge_msg_shortlog(&input, &output);
} else {
ret = fmt_merge_msg(merge_summary, &input, &output);
}
if (ret)
return ret;
write_in_full(STDOUT_FILENO, output.buf, output.len);

View file

@ -23,7 +23,8 @@ static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
}
static const char * const merge_base_usage[] = {
"git merge-base [-a|--all] <commit> <commit>...",
"git merge-base [-a|--all] [--octopus] <commit> <commit>...",
"git merge-base --independent <commit>...",
NULL
};
@ -41,21 +42,58 @@ static struct commit *get_commit_reference(const char *arg)
return r;
}
static int handle_octopus(int count, const char **args, int reduce, int show_all)
{
struct commit_list *revs = NULL;
struct commit_list *result;
int i;
if (reduce)
show_all = 1;
for (i = count - 1; i >= 0; i--)
commit_list_insert(get_commit_reference(args[i]), &revs);
result = reduce ? reduce_heads(revs) : get_octopus_merge_bases(revs);
if (!result)
return 1;
while (result) {
printf("%s\n", sha1_to_hex(result->item->object.sha1));
if (!show_all)
return 0;
result = result->next;
}
return 0;
}
int cmd_merge_base(int argc, const char **argv, const char *prefix)
{
struct commit **rev;
int rev_nr = 0;
int show_all = 0;
int octopus = 0;
int reduce = 0;
struct option options[] = {
OPT_BOOLEAN('a', "all", &show_all, "outputs all common ancestors"),
OPT_BOOLEAN('a', "all", &show_all, "output all common ancestors"),
OPT_BOOLEAN(0, "octopus", &octopus, "find ancestors for a single n-way merge"),
OPT_BOOLEAN(0, "independent", &reduce, "list revs not reachable from others"),
OPT_END()
};
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
if (argc < 2)
if (!octopus && !reduce && argc < 2)
usage_with_options(merge_base_usage, options);
if (reduce && (show_all || octopus))
die("--independent cannot be used with other options");
if (octopus || reduce)
return handle_octopus(argc, argv, reduce, show_all);
rev = xmalloc(argc * sizeof(*rev));
while (argc-- > 0)
rev[rev_nr++] = get_commit_reference(*argv++);

View file

@ -438,7 +438,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
strbuf_addstr(&truname, "refs/heads/");
strbuf_addstr(&truname, remote);
strbuf_setlen(&truname, truname.len - len);
if (resolve_ref(truname.buf, buf_sha, 0, NULL)) {
if (resolve_ref(truname.buf, buf_sha, 1, NULL)) {
strbuf_addf(msg,
"%s\t\tbranch '%s'%s of .\n",
sha1_to_hex(remote_head->sha1),

View file

@ -15,7 +15,10 @@ log add list of one-line log to merge commit message
squash create a single commit instead of doing a merge
commit perform a commit if the merge succeeds (default)
ff allow fast-forward (default)
ff-only abort if fast-forward is not possible
rerere-autoupdate update index with any reused conflict resolution
s,strategy= merge strategy to use
X= option for selected merge strategy
m,message= message to be used for the merge commit (if any)
"
@ -25,26 +28,32 @@ require_work_tree
cd_to_toplevel
test -z "$(git ls-files -u)" ||
die "You are in the middle of a conflicted merge."
die "Merge is not possible because you have unmerged files."
! test -e "$GIT_DIR/MERGE_HEAD" ||
die 'You have not concluded your merge (MERGE_HEAD exists).'
LF='
'
all_strategies='recur recursive octopus resolve stupid ours subtree'
all_strategies="$all_strategies recursive-ours recursive-theirs"
not_strategies='base file index tree'
default_twohead_strategies='recursive'
default_octopus_strategies='octopus'
no_fast_forward_strategies='subtree ours'
no_trivial_strategies='recursive recur subtree ours recursive-ours recursive-theirs'
use_strategies=
xopt=
allow_fast_forward=t
fast_forward_only=
allow_trivial_merge=t
squash= no_commit= log_arg=
squash= no_commit= log_arg= rr_arg=
dropsave() {
rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" \
"$GIT_DIR/MERGE_STASH" || exit 1
"$GIT_DIR/MERGE_STASH" "$GIT_DIR/MERGE_MODE" || exit 1
}
savestate() {
@ -131,21 +140,34 @@ finish () {
merge_name () {
remote="$1"
rh=$(git rev-parse --verify "$remote^0" 2>/dev/null) || return
bh=$(git show-ref -s --verify "refs/heads/$remote" 2>/dev/null)
if test "$rh" = "$bh"
then
echo "$rh branch '$remote' of ."
elif truname=$(expr "$remote" : '\(.*\)~[1-9][0-9]*$') &&
if truname=$(expr "$remote" : '\(.*\)~[0-9]*$') &&
git show-ref -q --verify "refs/heads/$truname" 2>/dev/null
then
echo "$rh branch '$truname' (early part) of ."
elif test "$remote" = "FETCH_HEAD" -a -r "$GIT_DIR/FETCH_HEAD"
return
fi
if found_ref=$(git rev-parse --symbolic-full-name --verify \
"$remote" 2>/dev/null)
then
expanded=$(git check-ref-format --branch "$remote") ||
exit
if test "${found_ref#refs/heads/}" != "$found_ref"
then
echo "$rh branch '$expanded' of ."
return
elif test "${found_ref#refs/remotes/}" != "$found_ref"
then
echo "$rh remote branch '$expanded' of ."
return
fi
fi
if test "$remote" = "FETCH_HEAD" -a -r "$GIT_DIR/FETCH_HEAD"
then
sed -e 's/ not-for-merge / /' -e 1q \
"$GIT_DIR/FETCH_HEAD"
else
echo "$rh commit '$remote'"
return
fi
echo "$rh commit '$remote'"
}
parse_config () {
@ -172,16 +194,36 @@ parse_config () {
--no-ff)
test "$squash" != t ||
die "You cannot combine --squash with --no-ff."
test "$fast_forward_only" != t ||
die "You cannot combine --ff-only with --no-ff."
allow_fast_forward=f ;;
--ff-only)
test "$allow_fast_forward" != f ||
die "You cannot combine --ff-only with --no-ff."
fast_forward_only=t ;;
--rerere-autoupdate|--no-rerere-autoupdate)
rr_arg=$1 ;;
-s|--strategy)
shift
case " $all_strategies " in
*" $1 "*)
use_strategies="$use_strategies$1 " ;;
use_strategies="$use_strategies$1 "
;;
*)
die "available strategies are: $all_strategies" ;;
case " $not_strategies " in
*" $1 "*)
false
esac &&
type "git-merge-$1" >/dev/null 2>&1 ||
die "available strategies are: $all_strategies"
use_strategies="$use_strategies$1 "
;;
esac
;;
-X)
shift
xopt="${xopt:+$xopt }$(git rev-parse --sq-quote "--$1")"
;;
-m|--message)
shift
merge_msg="$1"
@ -245,6 +287,10 @@ then
exit 1
fi
test "$squash" != t ||
die "Squash commit into empty head not supported yet"
test "$allow_fast_forward" = t ||
die "Non-fast-forward into an empty head does not make sense"
rh=$(git rev-parse --verify "$1^0") ||
die "$1 - not something we can merge"
@ -261,12 +307,18 @@ else
# 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
merge_msg="$(
for remote
do
merge_name "$remote"
done | git fmt-merge-msg $log_arg
)
merge_msg="${merge_msg:+$merge_msg$LF$LF}$merge_name"
done |
if test "$have_message" = t
then
git fmt-merge-msg -m "$merge_msg" $log_arg
else
git fmt-merge-msg $log_arg
fi
)"
fi
head=$(git rev-parse --verify "$head_arg"^0) || usage
@ -335,7 +387,7 @@ case "$#" in
common=$(git merge-base --all $head "$@")
;;
*)
common=$(git show-branch --merge-base $head "$@")
common=$(git merge-base --all --octopus $head "$@")
;;
esac
echo "$head" >"$GIT_DIR/ORIG_HEAD"
@ -373,8 +425,8 @@ t,1,"$head",*)
# We are not doing octopus, not fast-forward, and have only
# one common.
git update-index --refresh 2>/dev/null
case "$allow_trivial_merge" in
t)
case "$allow_trivial_merge,$fast_forward_only" in
t,)
# See if it is really trivial.
git var GIT_COMMITTER_IDENT >/dev/null || exit
echo "Trying really trivial in-index merge..."
@ -413,6 +465,11 @@ t,1,"$head",*)
;;
esac
if test "$fast_forward_only" = t
then
die "Not possible to fast-forward, aborting."
fi
# We are going to make a new commit.
git var GIT_COMMITTER_IDENT >/dev/null || exit
@ -451,7 +508,7 @@ do
# Remember which strategy left the state in the working tree
wt_strategy=$strategy
git-merge-$strategy $common -- "$head_arg" "$@"
eval 'git-merge-$strategy '"$xopt"' $common -- "$head_arg" "$@"'
exit=$?
if test "$no_commit" = t && test "$exit" = 0
then
@ -489,9 +546,9 @@ if test '' != "$result_tree"
then
if test "$allow_fast_forward" = "t"
then
parents=$(git show-branch --independent "$head" "$@")
parents=$(git merge-base --independent "$head" "$@")
else
parents=$(git rev-parse "$head" "$@")
parents=$(git rev-parse "$head" "$@")
fi
parents=$(echo "$parents" | sed -e 's/^/-p /')
result_commit=$(printf '%s\n' "$merge_msg" | git commit-tree $result_tree $parents) || exit
@ -533,7 +590,15 @@ else
do
echo $remote
done >"$GIT_DIR/MERGE_HEAD"
printf '%s\n' "$merge_msg" >"$GIT_DIR/MERGE_MSG"
printf '%s\n' "$merge_msg" >"$GIT_DIR/MERGE_MSG" ||
die "Could not write to $GIT_DIR/MERGE_MSG"
if test "$allow_fast_forward" != t
then
printf "%s" no-ff
else
:
fi >"$GIT_DIR/MERGE_MODE" ||
die "Could not write to $GIT_DIR/MERGE_MODE"
fi
if test "$merge_was_ok" = t
@ -550,6 +615,6 @@ Conflicts:
sed -e 's/^[^ ]* / /' |
uniq
} >>"$GIT_DIR/MERGE_MSG"
git rerere
git rerere $rr_arg
die "Automatic merge failed; fix conflicts and then commit the result."
fi

View file

@ -3,175 +3,231 @@
# Copyright (c) 2005 Junio C Hamano
#
test_description='Merge base computation.
test_description='Merge base and parent list computation.
'
. ./test-lib.sh
T=$(git write-tree)
test_expect_success 'setup' '
T=$(git write-tree) &&
M=1130000000
Z=+0000
M=1130000000 &&
Z=+0000 &&
GIT_COMMITTER_EMAIL=git@comm.iter.xz
GIT_COMMITTER_NAME='C O Mmiter'
GIT_AUTHOR_NAME='A U Thor'
GIT_AUTHOR_EMAIL=git@au.thor.xz
export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
GIT_COMMITTER_EMAIL=git@comm.iter.xz &&
GIT_COMMITTER_NAME="C O Mmiter" &&
GIT_AUTHOR_NAME="A U Thor" &&
GIT_AUTHOR_EMAIL=git@au.thor.xz &&
export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL &&
doit() {
OFFSET=$1; shift
NAME=$1; shift
PARENTS=
for P
do
PARENTS="${PARENTS}-p $P "
done
GIT_COMMITTER_DATE="$(($M + $OFFSET)) $Z"
GIT_AUTHOR_DATE=$GIT_COMMITTER_DATE
export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
commit=$(echo $NAME | git commit-tree $T $PARENTS)
echo $commit >.git/refs/tags/$NAME
echo $commit
}
doit() {
OFFSET=$1 &&
NAME=$2 &&
shift 2 &&
# E---D---C---B---A
# \'-_ \ \
# \ `---------G \
# \ \
# F----------------H
PARENTS= &&
for P
do
PARENTS="${PARENTS}-p $P "
done &&
# Setup...
E=$(doit 5 E)
D=$(doit 4 D $E)
F=$(doit 6 F $E)
C=$(doit 3 C $D)
B=$(doit 2 B $C)
A=$(doit 1 A $B)
G=$(doit 7 G $B $E)
H=$(doit 8 H $A $F)
GIT_COMMITTER_DATE="$(($M + $OFFSET)) $Z" &&
GIT_AUTHOR_DATE=$GIT_COMMITTER_DATE &&
export GIT_COMMITTER_DATE GIT_AUTHOR_DATE &&
test_expect_success 'compute merge-base (single)' \
'MB=$(git merge-base G H) &&
expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/B"'
commit=$(echo $NAME | git commit-tree $T $PARENTS) &&
test_expect_success 'compute merge-base (all)' \
'MB=$(git merge-base --all G H) &&
expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/B"'
echo $commit >.git/refs/tags/$NAME &&
echo $commit
}
'
test_expect_success 'compute merge-base with show-branch' \
'MB=$(git show-branch --merge-base G H) &&
expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/B"'
test_expect_success 'set up G and H' '
# E---D---C---B---A
# \"-_ \ \
# \ `---------G \
# \ \
# F----------------H
E=$(doit 5 E) &&
D=$(doit 4 D $E) &&
F=$(doit 6 F $E) &&
C=$(doit 3 C $D) &&
B=$(doit 2 B $C) &&
A=$(doit 1 A $B) &&
G=$(doit 7 G $B $E) &&
H=$(doit 8 H $A $F)
'
# Setup for second test to demonstrate that relying on timestamps in a
# distributed SCM to provide a _consistent_ partial ordering of commits
# leads to insanity.
#
# Relative
# Structure timestamps
#
# PL PR +4 +4
# / \/ \ / \/ \
# L2 C2 R2 +3 -1 +3
# | | | | | |
# L1 C1 R1 +2 -2 +2
# | | | | | |
# L0 C0 R0 +1 -3 +1
# \ | / \ | /
# S 0
#
# The left and right chains of commits can be of any length and complexity as
# long as all of the timestamps are greater than that of S.
test_expect_success 'merge-base G H' '
git name-rev $B >expected &&
S=$(doit 0 S)
MB=$(git merge-base G H) &&
git name-rev "$MB" >actual.single &&
C0=$(doit -3 C0 $S)
C1=$(doit -2 C1 $C0)
C2=$(doit -1 C2 $C1)
MB=$(git merge-base --all G H) &&
git name-rev "$MB" >actual.all &&
L0=$(doit 1 L0 $S)
L1=$(doit 2 L1 $L0)
L2=$(doit 3 L2 $L1)
MB=$(git show-branch --merge-base G H) &&
git name-rev "$MB" >actual.sb &&
R0=$(doit 1 R0 $S)
R1=$(doit 2 R1 $R0)
R2=$(doit 3 R2 $R1)
test_cmp expected actual.single &&
test_cmp expected actual.all &&
test_cmp expected actual.sb
'
PL=$(doit 4 PL $L2 $C2)
PR=$(doit 4 PR $C2 $R2)
test_expect_success 'merge-base/show-branch --independent' '
git name-rev "$H" >expected1 &&
git name-rev "$H" "$G" >expected2 &&
test_expect_success 'compute merge-base (single)' \
'MB=$(git merge-base PL PR) &&
expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/C2"'
parents=$(git merge-base --independent H) &&
git name-rev $parents >actual1.mb &&
parents=$(git merge-base --independent A H G) &&
git name-rev $parents >actual2.mb &&
test_expect_success 'compute merge-base (all)' \
'MB=$(git merge-base --all PL PR) &&
expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/C2"'
parents=$(git show-branch --independent H) &&
git name-rev $parents >actual1.sb &&
parents=$(git show-branch --independent A H G) &&
git name-rev $parents >actual2.sb &&
# Another set to demonstrate base between one commit and a merge
# in the documentation.
#
# * C (MMC) * B (MMB) * A (MMA)
# * o * o * o
# * o * o * o
# * o * o * o
# * o | _______/
# | |/
# | * 1 (MM1)
# | _______/
# |/
# * root (MMR)
test_cmp expected1 actual1.mb &&
test_cmp expected2 actual2.mb &&
test_cmp expected1 actual1.sb &&
test_cmp expected2 actual2.sb
'
test_expect_success 'unsynchronized clocks' '
# This test is to demonstrate that relying on timestamps in a distributed
# SCM to provide a _consistent_ partial ordering of commits leads to
# insanity.
#
# Relative
# Structure timestamps
#
# PL PR +4 +4
# / \/ \ / \/ \
# L2 C2 R2 +3 -1 +3
# | | | | | |
# L1 C1 R1 +2 -2 +2
# | | | | | |
# L0 C0 R0 +1 -3 +1
# \ | / \ | /
# S 0
#
# The left and right chains of commits can be of any length and complexity as
# long as all of the timestamps are greater than that of S.
S=$(doit 0 S) &&
C0=$(doit -3 C0 $S) &&
C1=$(doit -2 C1 $C0) &&
C2=$(doit -1 C2 $C1) &&
L0=$(doit 1 L0 $S) &&
L1=$(doit 2 L1 $L0) &&
L2=$(doit 3 L2 $L1) &&
R0=$(doit 1 R0 $S) &&
R1=$(doit 2 R1 $R0) &&
R2=$(doit 3 R2 $R1) &&
PL=$(doit 4 PL $L2 $C2) &&
PR=$(doit 4 PR $C2 $R2)
git name-rev $C2 >expected &&
MB=$(git merge-base PL PR) &&
git name-rev "$MB" >actual.single &&
MB=$(git merge-base --all PL PR) &&
git name-rev "$MB" >actual.all &&
test_cmp expected actual.single &&
test_cmp expected actual.all
'
test_expect_success '--independent with unsynchronized clocks' '
IB=$(doit 0 IB) &&
I1=$(doit -10 I1 $IB) &&
I2=$(doit -9 I2 $I1) &&
I3=$(doit -8 I3 $I2) &&
I4=$(doit -7 I4 $I3) &&
I5=$(doit -6 I5 $I4) &&
I6=$(doit -5 I6 $I5) &&
I7=$(doit -4 I7 $I6) &&
I8=$(doit -3 I8 $I7) &&
IH=$(doit -2 IH $I8) &&
echo $IH >expected &&
git merge-base --independent IB IH >actual &&
test_cmp expected actual
'
test_expect_success 'merge-base for octopus-step (setup)' '
test_tick && git commit --allow-empty -m root && git tag MMR &&
test_tick && git commit --allow-empty -m 1 && git tag MM1 &&
test_tick && git commit --allow-empty -m o &&
test_tick && git commit --allow-empty -m o &&
test_tick && git commit --allow-empty -m o &&
test_tick && git commit --allow-empty -m A && git tag MMA &&
# Another set to demonstrate base between one commit and a merge
# in the documentation.
#
# * C (MMC) * B (MMB) * A (MMA)
# * o * o * o
# * o * o * o
# * o * o * o
# * o | _______/
# | |/
# | * 1 (MM1)
# | _______/
# |/
# * root (MMR)
test_commit MMR &&
test_commit MM1 &&
test_commit MM-o &&
test_commit MM-p &&
test_commit MM-q &&
test_commit MMA &&
git checkout MM1 &&
test_tick && git commit --allow-empty -m o &&
test_tick && git commit --allow-empty -m o &&
test_tick && git commit --allow-empty -m o &&
test_tick && git commit --allow-empty -m B && git tag MMB &&
test_commit MM-r &&
test_commit MM-s &&
test_commit MM-t &&
test_commit MMB &&
git checkout MMR &&
test_tick && git commit --allow-empty -m o &&
test_tick && git commit --allow-empty -m o &&
test_tick && git commit --allow-empty -m o &&
test_tick && git commit --allow-empty -m o &&
test_tick && git commit --allow-empty -m C && git tag MMC
test_commit MM-u &&
test_commit MM-v &&
test_commit MM-w &&
test_commit MM-x &&
test_commit MMC
'
test_expect_success 'merge-base A B C' '
MB=$(git merge-base --all MMA MMB MMC) &&
MM1=$(git rev-parse --verify MM1) &&
test "$MM1" = "$MB"
git rev-parse --verify MM1 >expected &&
git rev-parse --verify MMR >expected.sb &&
git merge-base --all MMA MMB MMC >actual &&
git merge-base --all --octopus MMA MMB MMC >actual.common &&
git show-branch --merge-base MMA MMB MMC >actual.sb &&
test_cmp expected actual &&
test_cmp expected.sb actual.common &&
test_cmp expected.sb actual.sb
'
test_expect_success 'merge-base A B C using show-branch' '
MB=$(git show-branch --merge-base MMA MMB MMC) &&
MMR=$(git rev-parse --verify MMR) &&
test "$MMR" = "$MB"
'
test_expect_success 'criss-cross merge-base for octopus-step (setup)' '
test_expect_success 'criss-cross merge-base for octopus-step' '
git reset --hard MMR &&
test_tick && git commit --allow-empty -m 1 && git tag CC1 &&
test_commit CC1 &&
git reset --hard E &&
test_tick && git commit --allow-empty -m 2 && git tag CC2 &&
test_tick && git merge -s ours CC1 &&
test_tick && git commit --allow-empty -m o &&
test_tick && git commit --allow-empty -m B && git tag CCB &&
test_commit CC2 &&
test_tick &&
git merge -s ours CC1 &&
test_commit CC-o &&
test_commit CCB &&
git reset --hard CC1 &&
test_tick && git merge -s ours CC2 &&
test_tick && git commit --allow-empty -m A && git tag CCA
'
git merge -s ours CC2 &&
test_commit CCA &&
test_expect_success 'merge-base B A^^ A^^2' '
MB0=$(git merge-base --all CCB CCA^^ CCA^^2 | sort) &&
MB1=$(git rev-parse CC1 CC2 | sort) &&
test "$MB0" = "$MB1"
git rev-parse CC1 CC2 >expected &&
git merge-base --all CCB CCA^^ CCA^^2 >actual &&
sort expected >expected.sorted &&
sort actual >actual.sorted &&
test_cmp expected.sorted actual.sorted
'
test_done

View file

@ -70,14 +70,13 @@ test_expect_success setup '
i=$(($i+1))
done &&
git show-branch
git show-branch &&
apos="'\''"
'
cat >expected <<\EOF
Merge branch 'left'
EOF
test_expect_success 'merge-msg test #1' '
test_expect_success 'message for merging local branch' '
echo "Merge branch ${apos}left${apos}" >expected &&
git checkout master &&
git fetch . left &&
@ -86,11 +85,8 @@ test_expect_success 'merge-msg test #1' '
test_cmp expected actual
'
cat >expected <<EOF
Merge branch 'left' of $(pwd)
EOF
test_expect_success 'merge-msg test #2' '
test_expect_success 'message for merging external branch' '
echo "Merge branch ${apos}left${apos} of $(pwd)" >expected &&
git checkout master &&
git fetch "$(pwd)" left &&
@ -99,139 +95,140 @@ test_expect_success 'merge-msg test #2' '
test_cmp expected actual
'
cat >expected <<\EOF
Merge branch 'left'
test_expect_success '[merge] summary/log configuration' '
cat >expected <<-EOF &&
Merge branch ${apos}left${apos}
* left:
Left #5
Left #4
Left #3
Common #2
Common #1
EOF
* left:
Left #5
Left #4
Left #3
Common #2
Common #1
EOF
test_expect_success 'merge-msg test #3-1' '
git config --unset-all merge.log
git config --unset-all merge.summary
git config merge.log true &&
test_might_fail git config --unset-all merge.summary &&
git checkout master &&
test_tick &&
git fetch . left &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
test_cmp expected actual
'
git fmt-merge-msg <.git/FETCH_HEAD >actual1 &&
test_expect_success 'merge-msg test #3-2' '
git config --unset-all merge.log
git config --unset-all merge.summary
test_might_fail git config --unset-all merge.log &&
git config merge.summary true &&
git checkout master &&
test_tick &&
git fetch . left &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
test_cmp expected actual
git fmt-merge-msg <.git/FETCH_HEAD >actual2 &&
test_cmp expected actual1 &&
test_cmp expected actual2
'
cat >expected <<\EOF
Merge branches 'left' and 'right'
test_expect_success 'fmt-merge-msg -m' '
echo "Sync with left" >expected &&
cat >expected.log <<-EOF &&
Sync with left
* left:
Left #5
Left #4
Left #3
Common #2
Common #1
* ${apos}left${apos} of $(pwd):
Left #5
Left #4
Left #3
Common #2
Common #1
EOF
* right:
Right #5
Right #4
Right #3
Common #2
Common #1
EOF
test_expect_success 'merge-msg test #4-1' '
git config --unset-all merge.log
git config --unset-all merge.summary
test_might_fail git config --unset merge.log &&
test_might_fail git config --unset merge.summary &&
git checkout master &&
git fetch "$(pwd)" left &&
git fmt-merge-msg -m "Sync with left" <.git/FETCH_HEAD >actual &&
git fmt-merge-msg --log -m "Sync with left" \
<.git/FETCH_HEAD >actual.log &&
git config merge.log true &&
git fmt-merge-msg -m "Sync with left" \
<.git/FETCH_HEAD >actual.log-config &&
git fmt-merge-msg --no-log -m "Sync with left" \
<.git/FETCH_HEAD >actual.nolog &&
test_cmp expected actual &&
test_cmp expected.log actual.log &&
test_cmp expected.log actual.log-config &&
test_cmp expected actual.nolog
'
test_expect_success 'setup: expected shortlog for two branches' '
cat >expected <<-EOF
Merge branches ${apos}left${apos} and ${apos}right${apos}
* left:
Left #5
Left #4
Left #3
Common #2
Common #1
* right:
Right #5
Right #4
Right #3
Common #2
Common #1
EOF
'
test_expect_success 'shortlog for two branches' '
git config merge.log true &&
test_might_fail git config --unset-all merge.summary &&
git checkout master &&
test_tick &&
git fetch . left right &&
git fmt-merge-msg <.git/FETCH_HEAD >actual1 &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
test_cmp expected actual
'
test_expect_success 'merge-msg test #4-2' '
git config --unset-all merge.log
git config --unset-all merge.summary
test_might_fail git config --unset-all merge.log &&
git config merge.summary true &&
git checkout master &&
test_tick &&
git fetch . left right &&
git fmt-merge-msg <.git/FETCH_HEAD >actual2 &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
test_cmp expected actual
'
test_expect_success 'merge-msg test #5-1' '
git config --unset-all merge.log
git config --unset-all merge.summary
git config merge.log yes &&
test_might_fail git config --unset-all merge.summary &&
git checkout master &&
test_tick &&
git fetch . left right &&
git fmt-merge-msg <.git/FETCH_HEAD >actual3 &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
test_cmp expected actual
'
test_expect_success 'merge-msg test #5-2' '
git config --unset-all merge.log
git config --unset-all merge.summary
test_might_fail git config --unset-all merge.log &&
git config merge.summary yes &&
git checkout master &&
test_tick &&
git fetch . left right &&
git fmt-merge-msg <.git/FETCH_HEAD >actual4 &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
test_cmp expected actual
test_cmp expected actual1 &&
test_cmp expected actual2 &&
test_cmp expected actual3 &&
test_cmp expected actual4
'
test_expect_success 'merge-msg -F' '
git config --unset-all merge.log
git config --unset-all merge.summary
test_might_fail git config --unset-all merge.log &&
git config merge.summary yes &&
git checkout master &&
test_tick &&
git fetch . left right &&
git fmt-merge-msg -F .git/FETCH_HEAD >actual &&
test_cmp expected actual
'
test_expect_success 'merge-msg -F in subdirectory' '
git config --unset-all merge.log
git config --unset-all merge.summary
test_might_fail git config --unset-all merge.log &&
git config merge.summary yes &&
git checkout master &&
test_tick &&
git fetch . left right &&
@ -245,11 +242,11 @@ test_expect_success 'merge-msg -F in subdirectory' '
'
test_expect_success 'merge-msg with nothing to merge' '
git config --unset-all merge.log
git config --unset-all merge.summary
test_might_fail git config --unset-all merge.log &&
git config merge.summary yes &&
>empty &&
(
cd remote &&
git checkout -b unrelated &&
@ -258,22 +255,20 @@ test_expect_success 'merge-msg with nothing to merge' '
git fmt-merge-msg <.git/FETCH_HEAD >../actual
) &&
test_cmp /dev/null actual
test_cmp empty actual
'
cat >expected <<\EOF
Merge tag 'tag-r3'
* tag 'tag-r3':
Right #3
Common #2
Common #1
EOF
test_expect_success 'merge-msg tag' '
cat >expected <<-EOF &&
Merge tag ${apos}tag-r3${apos}
git config --unset-all merge.log
git config --unset-all merge.summary
* tag ${apos}tag-r3${apos}:
Right #3
Common #2
Common #1
EOF
test_might_fail git config --unset-all merge.log &&
git config merge.summary yes &&
git checkout master &&
@ -284,26 +279,24 @@ test_expect_success 'merge-msg tag' '
test_cmp expected actual
'
cat >expected <<\EOF
Merge tags 'tag-r3' and 'tag-l5'
* tag 'tag-r3':
Right #3
Common #2
Common #1
* tag 'tag-l5':
Left #5
Left #4
Left #3
Common #2
Common #1
EOF
test_expect_success 'merge-msg two tags' '
cat >expected <<-EOF &&
Merge tags ${apos}tag-r3${apos} and ${apos}tag-l5${apos}
git config --unset-all merge.log
git config --unset-all merge.summary
* tag ${apos}tag-r3${apos}:
Right #3
Common #2
Common #1
* tag ${apos}tag-l5${apos}:
Left #5
Left #4
Left #3
Common #2
Common #1
EOF
test_might_fail git config --unset-all merge.log &&
git config merge.summary yes &&
git checkout master &&
@ -314,26 +307,24 @@ test_expect_success 'merge-msg two tags' '
test_cmp expected actual
'
cat >expected <<\EOF
Merge branch 'left', tag 'tag-r3'
* tag 'tag-r3':
Right #3
Common #2
Common #1
* left:
Left #5
Left #4
Left #3
Common #2
Common #1
EOF
test_expect_success 'merge-msg tag and branch' '
cat >expected <<-EOF &&
Merge branch ${apos}left${apos}, tag ${apos}tag-r3${apos}
git config --unset-all merge.log
git config --unset-all merge.summary
* tag ${apos}tag-r3${apos}:
Right #3
Common #2
Common #1
* left:
Left #5
Left #4
Left #3
Common #2
Common #1
EOF
test_might_fail git config --unset-all merge.log &&
git config merge.summary yes &&
git checkout master &&
@ -344,26 +335,27 @@ test_expect_success 'merge-msg tag and branch' '
test_cmp expected actual
'
cat >expected <<\EOF
Merge branch 'long'
* long: (35 commits)
EOF
test_expect_success 'merge-msg lots of commits' '
{
cat <<-EOF &&
Merge branch ${apos}long${apos}
* long: (35 commits)
EOF
i=29 &&
while test $i -gt 9
do
echo " $i" &&
i=$(($i-1))
done &&
echo " ..."
} >expected &&
git checkout master &&
test_tick &&
git fetch . long &&
i=29 &&
while test $i -gt 9
do
echo " $i" &&
i=$(($i-1))
done >>expected &&
echo " ..." >>expected
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
test_cmp expected actual
'

View file

@ -5,189 +5,103 @@
test_description='git merge
Testing basic merge operations/option parsing.'
Testing basic merge operations/option parsing.
! [c0] commit 0
! [c1] commit 1
! [c2] commit 2
! [c3] commit 3
! [c4] c4
! [c5] c5
! [c6] c6
* [master] Merge commit 'c1'
--------
- [master] Merge commit 'c1'
+ * [c1] commit 1
+ [c6] c6
+ [c5] c5
++ [c4] c4
++++ [c3] commit 3
+ [c2] commit 2
+++++++* [c0] commit 0
'
. ./test-lib.sh
cat >file <<EOF
1
2
3
4
5
6
7
8
9
EOF
test_expect_success 'set up test data and helpers' '
printf "%s\n" 1 2 3 4 5 6 7 8 9 >file &&
printf "%s\n" "1 X" 2 3 4 5 6 7 8 9 >file.1 &&
printf "%s\n" 1 2 3 4 "5 X" 6 7 8 9 >file.5 &&
printf "%s\n" 1 2 3 4 5 6 7 8 "9 X" >file.9 &&
printf "%s\n" "1 X" 2 3 4 5 6 7 8 9 >result.1 &&
printf "%s\n" "1 X" 2 3 4 "5 X" 6 7 8 9 >result.1-5 &&
printf "%s\n" "1 X" 2 3 4 "5 X" 6 7 8 "9 X" >result.1-5-9 &&
cat >file.1 <<EOF
1 X
2
3
4
5
6
7
8
9
EOF
create_merge_msgs() {
echo "Merge commit '\''c2'\''" >msg.1-5 &&
echo "Merge commit '\''c2'\''; commit '\''c3'\''" >msg.1-5-9 &&
{
echo "Squashed commit of the following:" &&
echo &&
git log --no-merges ^HEAD c1
} >squash.1 &&
{
echo "Squashed commit of the following:" &&
echo &&
git log --no-merges ^HEAD c2
} >squash.1-5 &&
{
echo "Squashed commit of the following:" &&
echo &&
git log --no-merges ^HEAD c2 c3
} >squash.1-5-9 &&
echo >msg.nolog &&
{
echo "* commit '\''c3'\'':" &&
echo " commit 3" &&
echo
} >msg.log
} &&
cat >file.5 <<EOF
1
2
3
4
5 X
6
7
8
9
EOF
cat >file.9 <<EOF
1
2
3
4
5
6
7
8
9 X
EOF
cat >result.1 <<EOF
1 X
2
3
4
5
6
7
8
9
EOF
cat >result.1-5 <<EOF
1 X
2
3
4
5 X
6
7
8
9
EOF
cat >result.1-5-9 <<EOF
1 X
2
3
4
5 X
6
7
8
9 X
EOF
create_merge_msgs() {
echo "Merge commit 'c2'" >msg.1-5 &&
echo "Merge commit 'c2'; commit 'c3'" >msg.1-5-9 &&
echo "Squashed commit of the following:" >squash.1 &&
echo >>squash.1 &&
git log --no-merges ^HEAD c1 >>squash.1 &&
echo "Squashed commit of the following:" >squash.1-5 &&
echo >>squash.1-5 &&
git log --no-merges ^HEAD c2 >>squash.1-5 &&
echo "Squashed commit of the following:" >squash.1-5-9 &&
echo >>squash.1-5-9 &&
git log --no-merges ^HEAD c2 c3 >>squash.1-5-9 &&
echo > msg.nolog &&
echo "* commit 'c3':" >msg.log &&
echo " commit 3" >>msg.log &&
echo >>msg.log
}
verify_diff() {
if ! test_cmp "$1" "$2"
then
echo "$3"
false
fi
}
verify_merge() {
verify_diff "$2" "$1" "[OOPS] bad merge result" &&
if test $(git ls-files -u | wc -l) -gt 0
then
echo "[OOPS] unmerged files"
false
fi &&
if test_must_fail git diff --exit-code
then
echo "[OOPS] working tree != index"
false
fi &&
if test -n "$3"
then
git show -s --pretty=format:%s HEAD >msg.act &&
verify_diff "$3" msg.act "[OOPS] bad merge message"
fi
}
verify_head() {
if test "$1" != "$(git rev-parse HEAD)"
then
echo "[OOPS] HEAD != $1"
false
fi
}
verify_parents() {
i=1
while test $# -gt 0
do
if test "$1" != "$(git rev-parse HEAD^$i)"
verify_merge() {
test_cmp "$2" "$1" &&
git update-index --refresh &&
git diff --exit-code &&
if test -n "$3"
then
echo "[OOPS] HEAD^$i != $1"
return 1
git show -s --pretty=format:%s HEAD >msg.act &&
test_cmp "$3" msg.act
fi
i=$(expr $i + 1)
shift
done
}
} &&
verify_mergeheads() {
i=1
if ! test -f .git/MERGE_HEAD
then
echo "[OOPS] MERGE_HEAD is missing"
false
fi &&
while test $# -gt 0
do
head=$(head -n $i .git/MERGE_HEAD | sed -ne \$p)
if test "$1" != "$head"
then
echo "[OOPS] MERGE_HEAD $i != $1"
verify_head() {
echo "$1" >head.expected &&
git rev-parse HEAD >head.actual &&
test_cmp head.expected head.actual
} &&
verify_parents() {
printf "%s\n" "$@" >parents.expected &&
>parents.actual &&
i=1 &&
while test $i -le $#
do
git rev-parse HEAD^$i >>parents.actual &&
i=$(expr $i + 1) ||
return 1
fi
i=$(expr $i + 1)
shift
done
}
done &&
test_cmp parents.expected parents.actual
} &&
verify_no_mergehead() {
if test -f .git/MERGE_HEAD
then
echo "[OOPS] MERGE_HEAD exists"
false
fi
}
verify_mergeheads() {
printf "%s\n" "$@" >mergehead.expected &&
test_cmp mergehead.expected .git/MERGE_HEAD
} &&
verify_no_mergehead() {
! test -e .git/MERGE_HEAD
}
'
test_expect_success 'setup' '
git add file &&
@ -219,7 +133,7 @@ test_expect_success 'setup' '
create_merge_msgs
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'test option parsing' '
test_must_fail git merge -$ c1 &&
@ -235,13 +149,19 @@ test_expect_success 'reject non-strategy with a git-merge-foo name' '
'
test_expect_success 'merge c0 with c1' '
echo "OBJID HEAD@{0}: merge c1: Fast-forward" >reflog.expected &&
git reset --hard c0 &&
git merge c1 &&
verify_merge file result.1 &&
verify_head "$c1"
verify_head "$c1" &&
git reflog -1 >reflog.actual &&
sed "s/$_x05[0-9a-f]*/OBJID/g" reflog.actual >reflog.fuzzy &&
test_cmp reflog.expected reflog.fuzzy
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c0 with c1 with --ff-only' '
git reset --hard c0 &&
@ -251,7 +171,28 @@ test_expect_success 'merge c0 with c1 with --ff-only' '
verify_head "$c1"
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge from unborn branch' '
git checkout -f master &&
test_might_fail git branch -D kid &&
echo "OBJID HEAD@{0}: initial pull" >reflog.expected &&
git checkout --orphan kid &&
test_when_finished "git checkout -f master" &&
git rm -fr . &&
test_tick &&
git merge --ff-only c1 &&
verify_merge file result.1 &&
verify_head "$c1" &&
git reflog -1 >reflog.actual &&
sed "s/$_x05[0-9a-f][0-9a-f]/OBJID/g" reflog.actual >reflog.fuzzy &&
test_cmp reflog.expected reflog.fuzzy
'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c2' '
git reset --hard c1 &&
@ -261,7 +202,7 @@ test_expect_success 'merge c1 with c2' '
verify_parents $c1 $c2
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c2 and c3' '
git reset --hard c1 &&
@ -271,7 +212,7 @@ test_expect_success 'merge c1 with c2 and c3' '
verify_parents $c1 $c2 $c3
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'failing merges with --ff-only' '
git reset --hard c1 &&
@ -288,7 +229,7 @@ test_expect_success 'merge c0 with c1 (no-commit)' '
verify_head $c1
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c2 (no-commit)' '
git reset --hard c1 &&
@ -298,7 +239,7 @@ test_expect_success 'merge c1 with c2 (no-commit)' '
verify_mergeheads $c2
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c2 and c3 (no-commit)' '
git reset --hard c1 &&
@ -308,7 +249,7 @@ test_expect_success 'merge c1 with c2 and c3 (no-commit)' '
verify_mergeheads $c2 $c3
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c0 with c1 (squash)' '
git reset --hard c0 &&
@ -316,10 +257,10 @@ test_expect_success 'merge c0 with c1 (squash)' '
verify_merge file result.1 &&
verify_head $c0 &&
verify_no_mergehead &&
verify_diff squash.1 .git/SQUASH_MSG "[OOPS] bad squash message"
test_cmp squash.1 .git/SQUASH_MSG
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c0 with c1 (squash, ff-only)' '
git reset --hard c0 &&
@ -327,10 +268,10 @@ test_expect_success 'merge c0 with c1 (squash, ff-only)' '
verify_merge file result.1 &&
verify_head $c0 &&
verify_no_mergehead &&
verify_diff squash.1 .git/SQUASH_MSG "[OOPS] bad squash message"
test_cmp squash.1 .git/SQUASH_MSG
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c2 (squash)' '
git reset --hard c1 &&
@ -338,17 +279,17 @@ test_expect_success 'merge c1 with c2 (squash)' '
verify_merge file result.1-5 &&
verify_head $c1 &&
verify_no_mergehead &&
verify_diff squash.1-5 .git/SQUASH_MSG "[OOPS] bad squash message"
test_cmp squash.1-5 .git/SQUASH_MSG
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'unsuccesful merge of c1 with c2 (squash, ff-only)' '
git reset --hard c1 &&
test_must_fail git merge --squash --ff-only c2
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c2 and c3 (squash)' '
git reset --hard c1 &&
@ -356,10 +297,10 @@ test_expect_success 'merge c1 with c2 and c3 (squash)' '
verify_merge file result.1-5-9 &&
verify_head $c1 &&
verify_no_mergehead &&
verify_diff squash.1-5-9 .git/SQUASH_MSG "[OOPS] bad squash message"
test_cmp squash.1-5-9 .git/SQUASH_MSG
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c2 (no-commit in config)' '
git reset --hard c1 &&
@ -370,7 +311,7 @@ test_expect_success 'merge c1 with c2 (no-commit in config)' '
verify_mergeheads $c2
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c2 (squash in config)' '
git reset --hard c1 &&
@ -379,10 +320,10 @@ test_expect_success 'merge c1 with c2 (squash in config)' '
verify_merge file result.1-5 &&
verify_head $c1 &&
verify_no_mergehead &&
verify_diff squash.1-5 .git/SQUASH_MSG "[OOPS] bad squash message"
test_cmp squash.1-5 .git/SQUASH_MSG
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'override config option -n with --summary' '
git reset --hard c1 &&
@ -412,7 +353,7 @@ test_expect_success 'override config option -n with --stat' '
fi
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'override config option --stat' '
git reset --hard c1 &&
@ -428,7 +369,7 @@ test_expect_success 'override config option --stat' '
fi
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c2 (override --no-commit)' '
git reset --hard c1 &&
@ -439,7 +380,7 @@ test_expect_success 'merge c1 with c2 (override --no-commit)' '
verify_parents $c1 $c2
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c2 (override --squash)' '
git reset --hard c1 &&
@ -450,7 +391,7 @@ test_expect_success 'merge c1 with c2 (override --squash)' '
verify_parents $c1 $c2
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c0 with c1 (no-ff)' '
git reset --hard c0 &&
@ -461,7 +402,7 @@ test_expect_success 'merge c0 with c1 (no-ff)' '
verify_parents $c0 $c1
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'combining --squash and --no-ff is refused' '
test_must_fail git merge --squash --no-ff c1 &&
@ -485,20 +426,20 @@ test_expect_success 'merge log message' '
git reset --hard c0 &&
git merge --no-log c2 &&
git show -s --pretty=format:%b HEAD >msg.act &&
verify_diff msg.nolog msg.act "[OOPS] bad merge log message" &&
test_cmp msg.nolog msg.act &&
git merge --log c3 &&
git show -s --pretty=format:%b HEAD >msg.act &&
verify_diff msg.log msg.act "[OOPS] bad merge log message" &&
test_cmp msg.log msg.act &&
git reset --hard HEAD^ &&
git config merge.log yes &&
git merge c3 &&
git show -s --pretty=format:%b HEAD >msg.act &&
verify_diff msg.log msg.act "[OOPS] bad merge log message"
test_cmp msg.log msg.act
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c0, c2, c0, and c1' '
git reset --hard c1 &&
@ -509,7 +450,7 @@ test_expect_success 'merge c1 with c0, c2, c0, and c1' '
verify_parents $c1 $c2
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c0, c2, c0, and c1' '
git reset --hard c1 &&
@ -520,7 +461,7 @@ test_expect_success 'merge c1 with c0, c2, c0, and c1' '
verify_parents $c1 $c2
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge c1 with c1 and c2' '
git reset --hard c1 &&
@ -531,7 +472,7 @@ test_expect_success 'merge c1 with c1 and c2' '
verify_parents $c1 $c2
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge fast-forward in a dirty tree' '
git reset --hard c0 &&
@ -541,16 +482,16 @@ test_expect_success 'merge fast-forward in a dirty tree' '
git merge c2
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'in-index merge' '
git reset --hard c0 &&
git merge --no-ff -s resolve c1 > out &&
git merge --no-ff -s resolve c1 >out &&
grep "Wonderful." out &&
verify_parents $c0 $c1
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'refresh the index before merging' '
git reset --hard c1 &&
@ -558,31 +499,39 @@ test_expect_success 'refresh the index before merging' '
git merge c3
'
cat >expected <<EOF
Merge branch 'c5' (early part)
cat >expected.branch <<\EOF
Merge branch 'c5-branch' (early part)
EOF
cat >expected.tag <<\EOF
Merge commit 'c5~1'
EOF
test_expect_success 'merge early part of c2' '
git reset --hard c3 &&
echo c4 > c4.c &&
echo c4 >c4.c &&
git add c4.c &&
git commit -m c4 &&
git tag c4 &&
echo c5 > c5.c &&
echo c5 >c5.c &&
git add c5.c &&
git commit -m c5 &&
git tag c5 &&
git reset --hard c3 &&
echo c6 > c6.c &&
echo c6 >c6.c &&
git add c6.c &&
git commit -m c6 &&
git tag c6 &&
git branch -f c5-branch c5 &&
git merge c5-branch~1 &&
git show -s --pretty=format:%s HEAD >actual.branch &&
git reset --keep HEAD^ &&
git merge c5~1 &&
git show -s --pretty=format:%s HEAD > actual &&
test_cmp actual expected
git show -s --pretty=format:%s HEAD >actual.tag &&
test_cmp expected.branch actual.branch &&
test_cmp expected.tag actual.tag
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge --no-ff --no-commit && commit' '
git reset --hard c0 &&
@ -591,13 +540,13 @@ test_expect_success 'merge --no-ff --no-commit && commit' '
verify_parents $c0 $c1
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'amending no-ff merge commit' '
EDITOR=: git commit --amend &&
verify_parents $c0 $c1
'
test_debug 'gitk --all'
test_debug 'git log --graph --decorate --oneline --all'
test_done