* [PATCH 0/6] Forwarding Sverre's "merge --ff=<allow,only,never>" series
@ 2008-05-22 1:16 Junio C Hamano
2008-05-22 1:16 ` [PATCH 1/6] Documentation for joining more than two histories Junio C Hamano
0 siblings, 1 reply; 9+ messages in thread
From: Junio C Hamano @ 2008-05-22 1:16 UTC (permalink / raw)
To: git; +Cc: Sverre Hvammen Johansen
A few weeks ago Sverre's "merge --ff=<allow,only,never>" series was
re-sent to the list but as 6 attachments to a single mail. The format was
unfortunate and nobody seems to have bothered to read nor comment on.
I think the early patches in the series are at least worth keeping and the
overall series deserves some attention from the list, so I am re-injecting
them in format that can hopefully be commented on and tried out as a
public service ;-) I am tempted to apply up to [3/6] after another round
of reading myself.
A few minor nits I already have:
[2/6]
"diff -u" in verify_diff() should be "test_cmp":
@@ -254,7 +254,7 @@
+}
+
+verify_diff() {
-+ if ! diff -u "$1" "$2"
++ if ! test_cmp "$1" "$2"
+ then
+ echo "$3"
+ false
[3/6]
The argument to --ff is optional (log message):
---ff now takes an argument allowing --ff to be written
-as --ff=allow and -no-ff to be written as --ff=never.
-This change allow other fast forward options to be
-introduced later.
-
-See the documentation for a further explanation of these options.
+The --ff flag now takes an optional argument, allowing --ff to be
+written as --ff=allow and -no-ff to be written as --ff=never. This
+allows other fast forward options to be introduced later.
Also, you usually should not say 'see doc for details' in commit log, as
it does not help anybody. Either you convince others that your patch is
worth reading by your commit log message alone, or you don't.
Grammar.
+The first merge of topicA or the only merge of topicB would have
-+resulted in a fast forward without '--ff=never'. Topic A consist of
++resulted in a fast forward without '--ff=never'. Topic A consists of
+those commits that can be reached from master^2 without passing
[4/6]
Grammar.
+# Find reduced parents
-+# The following variables are set as follow:
++# The following variables are set as follows:
+# reduced_parents: The reduced parents of those specified on the
command line.
[6/6]
Commit log:
instead of a real merge. This option can then be used to
avoid an accidental merge.
-See the documentation for further details.
-
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/6] Documentation for joining more than two histories
2008-05-22 1:16 [PATCH 0/6] Forwarding Sverre's "merge --ff=<allow,only,never>" series Junio C Hamano
@ 2008-05-22 1:16 ` Junio C Hamano
2008-05-22 1:16 ` [PATCH 2/6] New merge tests Junio C Hamano
0 siblings, 1 reply; 9+ messages in thread
From: Junio C Hamano @ 2008-05-22 1:16 UTC (permalink / raw)
To: git
From: Sverre Hvammen Johansen <hvammen@gmail.com>
Added some documentation for how git-merge currently
works when more than two histories are joined.
Signed-off-by: Sverre Hvammen Johansen <hvammen@gmail.com>
---
Documentation/git-merge.txt | 36 ++++++++++++++++++++++++++++++++++++
1 files changed, 36 insertions(+), 0 deletions(-)
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index ef1f055..5924c1a 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -151,6 +151,42 @@ After seeing a conflict, you can do two things:
should be, and run `git-commit` to commit the result.
+JOINING MORE THAN TWO HISTORIES
+-------------------------------
+
+More than one remote may be specified on the command line. Those
+remotes are used for selecting the merge startegy and is also used in
+the merge commit message. However, some of these remotes may not be
+independent. Only remotes with independent heads (reduced parents)
+will be recorded in the merge commit object.
+
+The following shows master and two topic branches. topicB is based
+on topicA, topicA is previously branched off from master:
+
+------------
+ o---o---o topicB
+ /
+ o---o---o topicA
+ /
+ o---o---o---o---o---o---o master
+
+------------
+
+Merging topicA and topicB to the master branch will select the merge
+strategy based on all three branches (an Octopus). master and topicB
+are the reduced parents and are therefore the only parents recorded in
+the merge commit object:
+
+------------
+
+ o---o---o topicB
+ / \
+ o---o---o topicA o master
+ / /
+ o---o---o---o---o---o---o
+
+------------
+
SEE ALSO
--------
linkgit:git-fmt-merge-msg[1], linkgit:git-pull[1],
--
1.5.5.1.499.g878b8
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/6] New merge tests
2008-05-22 1:16 ` [PATCH 1/6] Documentation for joining more than two histories Junio C Hamano
@ 2008-05-22 1:16 ` Junio C Hamano
2008-05-22 1:16 ` [PATCH 3/6] Introduce -ff=<fast forward option> Junio C Hamano
0 siblings, 1 reply; 9+ messages in thread
From: Junio C Hamano @ 2008-05-22 1:16 UTC (permalink / raw)
To: git
From: Sverre Hvammen Johansen <hvammen@gmail.com>
Introduce new merge tests for preparation of new features:
--ff=<fast forward option>
Head reduction
--ff=only
Set up the framework (based on t7600) and add some test cases
that should succeed independent of the new features.
Signed-off-by: Sverre Hvammen Johansen <hvammen@gmail.com>
---
t/t7601-merge-ff-options.sh | 477 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 477 insertions(+), 0 deletions(-)
create mode 100755 t/t7601-merge-ff-options.sh
diff --git a/t/t7601-merge-ff-options.sh b/t/t7601-merge-ff-options.sh
new file mode 100755
index 0000000..e499bf5
--- /dev/null
+++ b/t/t7601-merge-ff-options.sh
@@ -0,0 +1,477 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Sverre Hvammen Johansen, based on t7600 by Lars Hjemli
+#
+
+test_description='git-merge
+
+Testing basic merge operations/option parsing.'
+
+. ./test-lib.sh
+
+cat >file <<EOF
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+EOF
+
+cat >file.1 <<EOF
+1 X
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+EOF
+
+cat >file.5 <<EOF
+1
+2
+3
+4
+5 X
+6
+7
+8
+9
+10
+11
+12
+EOF
+
+cat >file.9 <<EOF
+1
+2
+3
+4
+5
+6
+7
+8
+9 X
+10
+11
+12
+EOF
+
+cat >result.0 <<EOF
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+EOF
+
+cat >result.1 <<EOF
+1 X
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+EOF
+
+cat >result.1-5 <<EOF
+1 X
+2
+3
+4
+5 X
+6
+7
+8
+9
+10
+11
+12
+EOF
+
+cat >result.9 <<EOF
+1
+2
+3
+4
+5
+6
+7
+8
+9 X
+10
+11
+12
+EOF
+
+cat >result.1-5-9 <<EOF
+1 X
+2
+3
+4
+5 X
+6
+7
+8
+9 X
+10
+11
+12
+EOF
+
+cat >result.1-5-9-13 <<EOF
+1 X
+2
+3
+4
+5 X
+6
+7
+8
+9 X
+10
+11
+12
+13 x
+EOF
+
+cat >result.1-5-13 <<EOF
+1 X
+2
+3
+4
+5 X
+6
+7
+8
+9
+10
+11
+12
+13 x
+EOF
+
+cat >result.5-13 <<EOF
+1
+2
+3
+4
+5 X
+6
+7
+8
+9
+10
+11
+12
+13 x
+EOF
+
+cat >result.1-13 <<EOF
+1 X
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13 x
+EOF
+
+cat >extend <<EOF
+13 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
+}
+
+verify_diff() {
+ if ! diff -u "$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 ! 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)"
+ then
+ echo "[OOPS] HEAD^$i != $1"
+ return 1
+ 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 | tail -n 1)
+ if test "$1" != "$head"
+ then
+ echo "[OOPS] MERGE_HEAD $i != $1"
+ return 1
+ fi
+ i=$(expr $i + 1)
+ shift
+ done
+}
+
+verify_no_mergehead() {
+ if test -f .git/MERGE_HEAD
+ then
+ echo "[OOPS] MERGE_HEAD exists"
+ false
+ fi
+}
+
+# Setup with the following commits:
+#
+# y3
+# / \
+# / \
+# y1 y2
+# | \ / |
+# | \ / |
+# x1 x0 x2
+# | / \ |
+# | / \ |
+# c1 c2
+# \ /
+# \ /
+# c0---c3
+#
+
+test_expect_success 'setup' '
+ git add file &&
+ test_tick &&
+ git commit -m "commit 0" &&
+ git tag c0 &&
+ c0=$(git rev-parse HEAD) &&
+
+ cp file.1 file &&
+ git add file &&
+ test_tick &&
+ git commit -m "commit 1" &&
+ git tag c1 &&
+ c1=$(git rev-parse HEAD) &&
+ test_tick &&
+
+ git reset --hard "$c0" &&
+ cp file.5 file &&
+ git add file &&
+ git commit -m "commit 2" &&
+ test_tick &&
+ git tag c2 &&
+ c2=$(git rev-parse HEAD) &&
+
+ git reset --hard "$c0" &&
+ cp file.9 file &&
+ git add file &&
+ test_tick &&
+ git commit -m "commit 3" &&
+ git tag c3 &&
+ c3=$(git rev-parse HEAD) &&
+ test_tick &&
+
+ git reset --hard "$c1" &&
+ cat extend >>file &&
+ git add file &&
+ git commit -m "commit 4" &&
+ git tag x1 &&
+ x1=$(git rev-parse HEAD) &&
+ test_tick &&
+
+ git reset --hard "$c1" &&
+ git merge "$c2" &&
+ git tag x0 &&
+ x0=$(git rev-parse HEAD) &&
+ test_tick &&
+
+ git reset --hard "$c2" &&
+ cat extend >>file &&
+ git add file &&
+ git commit -m "commit 5" &&
+ git tag x2 &&
+ x2=$(git rev-parse HEAD) &&
+ test_tick &&
+
+ git reset --hard "$x1" &&
+ git merge "$x0" &&
+ git tag y1 &&
+ y1=$(git rev-parse HEAD) &&
+ test_tick &&
+
+ git reset --hard "$x0" &&
+ git merge "$x2" &&
+ git tag y2 &&
+ y2=$(git rev-parse HEAD) &&
+ test_tick &&
+
+ git reset --hard "$y1" &&
+ git merge "$y2" &&
+ git tag y3 &&
+ y3=$(git rev-parse HEAD) &&
+ test_tick &&
+ git reset --hard "$c0" &&
+ create_merge_msgs &&
+
+ git reset --hard x1 &&
+ git clone .git clone &&
+ git config remote.clone.url clone &&
+ git config remote.clone.fetch "+refs/heads/*:refs/remotes/clone/*" &&
+
+ (mkdir new && cd new && git init && cp ../file.9 file2 && git add file2 && test_tick && git commit -m "commit new") &&
+ git config remote.new.url new &&
+ git config remote.new.fetch "+refs/heads/*:refs/remotes/new/*"
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c0 and c0' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c0 c0 &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c0 with c1 and c2' '
+ git reset --hard c0 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c1 c2 &&
+ verify_merge file result.1-5 &&
+ verify_parents $c1 $c2
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c0, c2, c0, and c1' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c0 c2 c0 c1 &&
+ verify_merge file result.1-5 &&
+ verify_parents $c1 $c2
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge y2 with x0, c3, and c0' '
+ git reset --hard y2 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge x0 c3 c0 &&
+ verify_merge file result.1-5-9-13 &&
+ verify_parents $y2 $c3
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge x0 with y2, c3, and c0' '
+ git reset --hard x0 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge y2 c3 c0 &&
+ verify_merge file result.1-5-9-13 &&
+ verify_parents $y2 $c3
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge c1 with c2 and x1' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c2 x1 &&
+ verify_merge file result.1-5-13 &&
+ verify_parents $c2 $x1
+'
+
+test_debug 'gitk --all'
+
+test_done
--
1.5.5.1.499.g878b8
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/6] Introduce -ff=<fast forward option>
2008-05-22 1:16 ` [PATCH 2/6] New merge tests Junio C Hamano
@ 2008-05-22 1:16 ` Junio C Hamano
2008-05-22 1:16 ` [PATCH 4/6] Restructure git-merge.sh Junio C Hamano
0 siblings, 1 reply; 9+ messages in thread
From: Junio C Hamano @ 2008-05-22 1:16 UTC (permalink / raw)
To: git
From: Sverre Hvammen Johansen <hvammen@gmail.com>
--ff now takes an argument allowing --ff to be written
as --ff=allow and -no-ff to be written as --ff=never.
This change allow other fast forward options to be
introduced later.
See the documentation for a further explanation of these options.
Signed-off-by: Sverre Hvammen Johansen <hvammen@gmail.com>
---
Documentation/fast-forward-options.txt | 44 ++++++++
Documentation/git-merge.txt | 6 +-
Documentation/git-pull.txt | 2 +
Documentation/merge-options.txt | 9 +-
git-merge.sh | 47 +++++---
git-pull.sh | 4 +-
t/t7601-merge-ff-options.sh | 188 ++++++++++++++++++++++++++++++++
7 files changed, 277 insertions(+), 23 deletions(-)
create mode 100644 Documentation/fast-forward-options.txt
diff --git a/Documentation/fast-forward-options.txt b/Documentation/fast-forward-options.txt
new file mode 100644
index 0000000..9374aa9
--- /dev/null
+++ b/Documentation/fast-forward-options.txt
@@ -0,0 +1,44 @@
+FAST FORWARD OPTIONS
+--------------------
+
+allow::
+
+ Do not generate a merge commit if the merge resolves as a
+ fast-forward, only update the branch pointer. This option is
+ equivalent of '--ff' without any argument. This is the
+ default behavior.
+
+never::
+ Generate a merge commit even if the merge resolves as a
+ fast-forward. This option is equivalent of '--no-ff'.
+
+If your workflow is always to branch from the special branch
+("master") when working on a topic and merge that back to "master", if
+you happen to have worked only on a single topic and the "master" was
+never advanced during the time you worked on that topic, merging the
+topic back to "master" will result in a fast-forward. When you look
+back that history, you will not be able to tell where the topic
+started and ended by following the ancestry chain of the "master"
+branch.
+
+Using "never fast forward" policy on such a special branch will be a
+way to make sure that all commits on the first-parent ancestry of that
+special branch will be merges from something else. From the history
+you can determine where the topic started and ended.
+
+The following shows two branches forked off from "master". The branch
+"master" have merged in changes from branch "topicA" twice and
+"topicB" once:
+
+------------
+ o---o---o---o---o topicA
+ / \ \
+ ---*-------*-------*---* master
+ / \ /
+ o---o topicB
+------------
+
+The first merge of topicA or the only merge of topicB would have
+resulted in a fast forward without '--ff=never'. Topic A consist of
+those commits that can be reached from master^2 without passing
+through any of the first-parent ancestries of master.
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 5924c1a..9cf761d 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -9,7 +9,8 @@ git-merge - Join two or more development histories together
SYNOPSIS
--------
[verse]
-'git-merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
+'git-merge' [-n] [--stat] [--no-commit] [--squash]
+ [-s <strategy>]... [--ff[=<fast forward option>]]
[-m <msg>] <remote> <remote>...
'git-merge' <msg> HEAD <remote>...
@@ -37,6 +38,9 @@ include::merge-options.txt[]
least one <remote>. Specifying more than one <remote>
obviously means you are trying an Octopus.
+
+include::fast-forward-options.txt[]
+
include::merge-strategies.txt[]
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index 66304f0..eb816bc 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -52,6 +52,8 @@ include::pull-fetch-param.txt[]
include::urls-remotes.txt[]
+include::fast-forward-options.txt[]
+
include::merge-strategies.txt[]
DEFAULT BEHAVIOUR
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index f37a776..8f87758 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -42,12 +42,11 @@
--no-ff::
Generate a merge commit even if the merge resolved as a
- fast-forward.
+ fast-forward. --no-ff is an alias for --ff=never.
---ff::
- Do not generate a merge commit if the merge resolved as
- a fast-forward, only update the branch pointer. This is
- the default behavior of git-merge.
+--ff[=<fast forward option>]::
+ Select fast forward option. --ff without any argument
+ is an alias for --ff=allow which is the default behavior.
-s <strategy>, \--strategy=<strategy>::
Use the given merge strategy; can be supplied more than
diff --git a/git-merge.sh b/git-merge.sh
index 69b35d8..91fada7 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -16,7 +16,7 @@ log add list of one-line log to merge commit message
no-log don't 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 sucesses (default)
-ff allow fast forward (default)
+ff? fast forward options
s,strategy= merge strategy to use
m,message= message to be used for the merge commit (if any)
"
@@ -39,7 +39,7 @@ no_fast_forward_strategies='subtree ours'
no_trivial_strategies='recursive recur subtree ours'
use_strategies=
-allow_fast_forward=t
+fast_forward=allow
allow_trivial_merge=t
squash= no_commit= log_arg=
@@ -159,8 +159,6 @@ parse_config () {
--log|--no-log)
log_arg=$1 ;;
--squash)
- test "$allow_fast_forward" = t ||
- die "You cannot combine --squash with --no-ff."
squash=t no_commit=t ;;
--no-squash)
squash= no_commit= ;;
@@ -169,11 +167,26 @@ parse_config () {
--no-commit)
no_commit=t ;;
--ff)
- allow_fast_forward=t ;;
+ case "$2" in
+ allow|never)
+ fast_forward=$2; shift ;;
+ -*)
+ fast_forward=allow ;;
+ *)
+ die "Available fast-forward options are: allow and newer" ;;
+ esac
+ ;;
+ --ff=*)
+ fast_forward=${1#--ff=}
+ case "$fast_forward" in
+ allow|never)
+ ;;
+ *)
+ die "Available fast-forward options are: allow and newer" ;;
+ esac
+ ;;
--no-ff)
- test "$squash" != t ||
- die "You cannot combine --squash with --no-ff."
- allow_fast_forward=f ;;
+ fast_forward=never ;;
-s|--strategy)
shift
case " $all_strategies " in
@@ -195,6 +208,8 @@ parse_config () {
esac
shift
done
+ test "$fast_forward" = allow -o "$squash" = "" ||
+ die "You cannot combine --squash with --ff=never"
args_left=$#
}
@@ -315,7 +330,7 @@ do
do
case " $s " in
*" $ss "*)
- allow_fast_forward=f
+ fast_forward=never
break
;;
esac
@@ -341,17 +356,17 @@ case "$#" in
esac
echo "$head" >"$GIT_DIR/ORIG_HEAD"
-case "$allow_fast_forward,$#,$common,$no_commit" in
-?,*,'',*)
+case "$fast_forward,$#,$common,$no_commit" in
+*,*,'',*)
# No common ancestors found. We need a real merge.
;;
-?,1,"$1",*)
+*,1,"$1",*)
# If head can reach all the merge then we are up to date.
# but first the most common case of merging one remote.
finish_up_to_date "Already up-to-date."
exit 0
;;
-t,1,"$head",*)
+allow,1,"$head",*)
# Again the most common case of merging one remote.
echo "Updating $(git rev-parse --short $head)..$(git rev-parse --short $1)"
git update-index --refresh 2>/dev/null
@@ -366,11 +381,11 @@ t,1,"$head",*)
dropsave
exit 0
;;
-?,1,?*"$LF"?*,*)
+*,1,?*"$LF"?*,*)
# We are not doing octopus and not fast forward. Need a
# real merge.
;;
-?,1,*,)
+*,1,*,)
# We are not doing octopus, not fast forward, and have only
# one common.
git update-index --refresh 2>/dev/null
@@ -488,7 +503,7 @@ done
# auto resolved the merge cleanly.
if test '' != "$result_tree"
then
- if test "$allow_fast_forward" = "t"
+ if test $fast_forward = allow
then
parents=$(git show-branch --independent "$head" "$@")
else
diff --git a/git-pull.sh b/git-pull.sh
index bf0c298..9e91e75 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -4,7 +4,7 @@
#
# Fetch one or more remote refs and merge it/them into the current HEAD.
-USAGE='[-n | --no-stat] [--[no-]commit] [--[no-]squash] [--[no-]ff] [-s strategy]... [<fetch-options>] <repo> <head>...'
+USAGE='[-n | --no-stat] [--[no-]commit] [--[no-]squash] [--ff=<ff-strategy>] [-s strategy]... [<fetch-options>] <repo> <head>...'
LONG_USAGE='Fetch one or more remote refs and merge it/them into the current HEAD.'
SUBDIRECTORY_OK=Yes
OPTIONS_SPEC=
@@ -41,6 +41,8 @@ do
no_ff=--ff ;;
--no-ff)
no_ff=--no-ff ;;
+ --ff=allow|--ff=never)
+ no_ff=$1 ;;
-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
--strateg=*|--strategy=*|\
-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
diff --git a/t/t7601-merge-ff-options.sh b/t/t7601-merge-ff-options.sh
index e499bf5..c7c6d14 100755
--- a/t/t7601-merge-ff-options.sh
+++ b/t/t7601-merge-ff-options.sh
@@ -474,4 +474,192 @@ test_expect_success 'merge c1 with c2 and x1' '
test_debug 'gitk --all'
+test_expect_success 'merge x0 with c1 (--squash combined with --ff=allow)' '
+ git reset --hard x0 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c1 --squash --ff=allow &&
+ verify_merge file result.1-5 &&
+ verify_head $x0
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge c1 with c2 (--squash combined with --ff=allow)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c2 --squash --ff=allow &&
+ verify_merge file result.1-5 &&
+ verify_head $c1 &&
+ git commit &&
+ verify_parents $c1
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge c1 with x0 (--no-commit combined with --ff=allow)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge x0 --no-commit --ff=allow &&
+ verify_merge file result.1-5 &&
+ verify_parents $c1
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge x0 with c1 (--no-commit combined with --ff=allow)' '
+ git reset --hard x0 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c1 --no-commit --ff=allow &&
+ verify_merge file result.1-5 &&
+ verify_head $x0
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge c1 with c2 (--no-commit combined with --ff=allow)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c2 --no-commit --ff=allow &&
+ verify_merge file result.1-5 &&
+ verify_head $c1 &&
+ git commit &&
+ verify_parents $c1
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge c1 with x1 (pull --ff=allow)' '
+ git reset --hard c1 &&
+ test_tick &&
+ git pull --ff=allow clone refs/heads/master &&
+ verify_merge file result.1-13 &&
+ verify_head $x1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge x2 with x1 (pull --ff=allow)' '
+ git reset --hard x2 &&
+ test_tick &&
+ git pull --ff=allow clone refs/heads/master &&
+ verify_merge file result.1-5-13 &&
+ verify_parents $x2 $x1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with new repository (pull --ff=allow)' '
+ git reset --hard c1 &&
+ test_tick &&
+ git pull --ff=allow new refs/heads/master &&
+ verify_merge file result.1 &&
+ verify_merge file2 result.9
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge x0 with c1 (--squash combined with --ff=never)' '
+ git reset --hard x0 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ test_must_fail git merge c1 --squash --ff=never &&
+ verify_merge file result.1-5 &&
+ verify_head $x0
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge c1 with c2 (--squash combined with --ff=never)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ test_must_fail git merge c2 --squash --ff=never &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge c1 with x0 (--no-commit combined with --ff=never)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge x0 --no-commit --ff=never &&
+ verify_merge file result.1-5 &&
+ verify_head $c1 &&
+ git commit &&
+ verify_parents $c1
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge x0 with c1 (--no-commit combined with --ff=never)' '
+ git reset --hard x0 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c1 --no-commit --ff=never &&
+ verify_merge file result.1-5 &&
+ verify_head $x0
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge c1 with c2 (--no-commit combined with --ff=never)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c2 --no-commit --ff=never &&
+ verify_merge file result.1-5 &&
+ verify_head $c1 &&
+ git commit &&
+ verify_parents $c1
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge c1 with x1 (pull --ff=never)' '
+ git reset --hard c1 &&
+ test_tick &&
+ git pull --ff=never clone refs/heads/master &&
+ verify_merge file result.1-13 &&
+ verify_parents $c1 $x1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge x2 with x1 (pull --ff=never)' '
+ git reset --hard x2 &&
+ test_tick &&
+ git pull --ff=never clone refs/heads/master &&
+ verify_merge file result.1-5-13 &&
+ verify_parents $x2 $x1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with new repository (pull --ff=never)' '
+ git reset --hard c1 &&
+ test_tick &&
+ git pull --ff=never new refs/heads/master &&
+ verify_merge file result.1 &&
+ verify_merge file2 result.9
+'
+
+test_debug 'gitk --all'
+
test_done
--
1.5.5.1.499.g878b8
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/6] Restructure git-merge.sh
2008-05-22 1:16 ` [PATCH 3/6] Introduce -ff=<fast forward option> Junio C Hamano
@ 2008-05-22 1:16 ` Junio C Hamano
2008-05-22 1:16 ` [PATCH 5/6] Head reduction before selecting merge strategy Junio C Hamano
2008-05-22 10:48 ` [PATCH 4/6] Restructure git-merge.sh Johannes Schindelin
0 siblings, 2 replies; 9+ messages in thread
From: Junio C Hamano @ 2008-05-22 1:16 UTC (permalink / raw)
To: git
From: Sverre Hvammen Johansen <hvammen@gmail.com>
Restructure git-merge.sh for preparation of new feature:
Head reduction before selecting merge strategy
Some aspects of this patch does not make much sense without
the next patch in this series.
Signed-off-by: Sverre Hvammen Johansen <hvammen@gmail.com>
---
git-merge.sh | 186 +++++++++++++++++++++++++++++++++-------------------------
1 files changed, 105 insertions(+), 81 deletions(-)
diff --git a/git-merge.sh b/git-merge.sh
index 91fada7..fc14c4b 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -213,6 +213,47 @@ parse_config () {
args_left=$#
}
+# Find reduced parents
+# The following variables are set as follow:
+# reduced_parents: The reduced parents of those specified on the command line.
+# However, the actual parents are included if we never ff.
+# common: All common ancestors or not_queried
+# ff_head: Head or an reduced parent that may be a candidate for fast forward
+find_reduced_parents () {
+ if test $fast_forward = never
+ then
+ reduced_parents=$(git rev-parse "$@")
+ ff_head=$head
+ common=not_queried
+ else
+ if test $# = 1
+ then
+ common=$(git merge-base --all $head "$1")
+ if test "$common" = $head
+ then
+ reduced_parents=
+ ff_head=$1
+ elif test "$common" = "$1"
+ then
+ reduced_parents=
+ ff_head=$head
+ else
+ reduced_parents=$1
+ ff_head=$head
+
+ fi
+ else
+ reduced_parents=$(git show-branch --independent $head "$@")
+ # Here we may actually lie about which bransh is ff of head.
+ # This will preserve the order the user gave.
+ ff_head=${reduced_parents%%$LF*}
+ reduced_parents=${reduced_parents#$ff_head}
+ reduced_parents=${reduced_parents#$LF}
+ common=not_queried
+ fi
+ fi
+}
+
test $# != 0 || usage
have_message=
@@ -301,24 +342,28 @@ do
done
set x $remoteheads ; shift
+find_reduced_parents "$@"
+
+actual_parents=$(git rev-parse "$@")
+
case "$use_strategies" in
'')
- case "$#" in
- 1)
- var="`git config --get pull.twohead`"
+ case "$actual_parents" in
+ ?*"$LF"?*)
+ var="`git config --get pull.octopus`"
if test -n "$var"
then
use_strategies="$var"
else
- use_strategies="$default_twohead_strategies"
+ use_strategies="$default_octopus_strategies"
fi ;;
*)
- var="`git config --get pull.octopus`"
+ var="`git config --get pull.twohead`"
if test -n "$var"
then
use_strategies="$var"
else
- use_strategies="$default_octopus_strategies"
+ use_strategies="$default_twohead_strategies"
fi ;;
esac
;;
@@ -346,87 +391,66 @@ do
done
done
-case "$#" in
-1)
- common=$(git merge-base --all $head "$@")
- ;;
-*)
- common=$(git show-branch --merge-base $head "$@")
- ;;
-esac
echo "$head" >"$GIT_DIR/ORIG_HEAD"
-case "$fast_forward,$#,$common,$no_commit" in
-*,*,'',*)
- # No common ancestors found. We need a real merge.
- ;;
-*,1,"$1",*)
- # If head can reach all the merge then we are up to date.
- # but first the most common case of merging one remote.
- finish_up_to_date "Already up-to-date."
- exit 0
- ;;
-allow,1,"$head",*)
- # Again the most common case of merging one remote.
- echo "Updating $(git rev-parse --short $head)..$(git rev-parse --short $1)"
- git update-index --refresh 2>/dev/null
- msg="Fast forward"
- if test -n "$have_message"
+if test -z "$reduced_parents"
+then
+ if test $head = $ff_head
then
- msg="$msg (no commit created; -m option ignored)"
- fi
- new_head=$(git rev-parse --verify "$1^0") &&
- git read-tree -v -m -u --exclude-per-directory=.gitignore $head "$new_head" &&
- finish "$new_head" "$msg" || exit
- dropsave
- exit 0
- ;;
-*,1,?*"$LF"?*,*)
- # We are not doing octopus and not fast forward. Need a
- # real merge.
- ;;
-*,1,*,)
- # 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)
- # See if it is really trivial.
- git var GIT_COMMITTER_IDENT >/dev/null || exit
- echo "Trying really trivial in-index merge..."
- if git read-tree --trivial -m -u -v $common $head "$1" &&
- result_tree=$(git write-tree)
- then
- echo "Wonderful."
- result_commit=$(
- printf '%s\n' "$merge_msg" |
- git commit-tree $result_tree -p HEAD -p "$1"
- ) || exit
- finish "$result_commit" "In-index merge"
- dropsave
- exit 0
- fi
- echo "Nope."
- esac
- ;;
-*)
- # An octopus. If we can reach all the remote we are up to date.
- up_to_date=t
- for remote
- do
- common_one=$(git merge-base --all $head $remote)
- if test "$common_one" != "$remote"
+ finish_up_to_date "Already up-to-date."
+ exit 0
+ elif test $fast_forward != never
+ then
+ echo "Updating $(git rev-parse --short $head)..$(git rev-parse --short $ff_head)"
+ git update-index --refresh 2>/dev/null
+ msg="Fast forward"
+ if test -n "$have_message"
then
- up_to_date=f
- break
+ msg="$msg (no commit created; -m option ignored)"
fi
- done
- if test "$up_to_date" = t
- then
- finish_up_to_date "Already up-to-date. Yeeah!"
+ new_head=$(git rev-parse --verify "$ff_head^0") &&
+ git read-tree -v -m -u --exclude-per-directory=.gitignore $head "$new_head" &&
+ finish "$new_head" "$msg" || exit
+ dropsave
exit 0
fi
+fi
+
+case "$actual_parents" in
+?*"$LF"?*)
+ # We have more than one actual parent
+ common=$(git show-branch --merge-base $head $actual_parents)
;;
+*)
+ # We have exactly one actual parent
+ test "$common" != not_queried || common=$(git merge-base --all $head $actual_parents)
+ case "$common" in
+ ?*"$LF"?*)
+ # We are not doing octopus and not fast forward. Need a
+ # real merge.
+ ;;
+ *)
+ git update-index --refresh 2>/dev/null
+ if test "$allow_trivial_merge" = t
+ then
+ # See if it is really trivial.
+ git var GIT_COMMITTER_IDENT >/dev/null || exit
+ echo "Trying really trivial in-index merge..."
+ if git read-tree --trivial -m -u -v $common $head $actual_parents &&
+ result_tree=$(git write-tree)
+ then
+ echo "Wonderful."
+ result_commit=$(
+ printf '%s\n' "$merge_msg" |
+ git commit-tree $result_tree -p HEAD -p $actual_parents
+ ) || exit
+ finish "$result_commit" "In-index merge"
+ dropsave
+ exit 0
+ fi
+ echo "Nope."
+ fi ;;
+ esac ;;
esac
# We are going to make a new commit.
@@ -467,7 +491,7 @@ do
# Remember which strategy left the state in the working tree
wt_strategy=$strategy
- git-merge-$strategy $common -- "$head_arg" "$@"
+ git-merge-$strategy $common -- "$head_arg" $actual_parents
exit=$?
if test "$no_commit" = t && test "$exit" = 0
then
@@ -537,7 +561,7 @@ case "$best_strategy" in
echo "Rewinding the tree to pristine..."
restorestate
echo "Using the $best_strategy to prepare resolving by hand."
- git-merge-$best_strategy $common -- "$head_arg" "$@"
+ git-merge-$best_strategy $common -- "$head_arg" $actual_parents
;;
esac
--
1.5.5.1.499.g878b8
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/6] Head reduction before selecting merge strategy
2008-05-22 1:16 ` [PATCH 4/6] Restructure git-merge.sh Junio C Hamano
@ 2008-05-22 1:16 ` Junio C Hamano
2008-05-22 1:16 ` [PATCH 6/6] Introduce fast forward option only Junio C Hamano
2008-05-22 10:48 ` [PATCH 4/6] Restructure git-merge.sh Johannes Schindelin
1 sibling, 1 reply; 9+ messages in thread
From: Junio C Hamano @ 2008-05-22 1:16 UTC (permalink / raw)
To: git
From: Sverre Hvammen Johansen <hvammen@gmail.com>
This commit uses the reduced parents instead of the actual
parents specified for selecting the merge strategy when doing
a merge. The recorded parents and the commit message stays
the same.
Some cases where we before needed an octopus strategy may now be
done using a two head strategy.
See the documentation for further details.
Signed-off-by: Sverre Hvammen Johansen <hvammen@gmail.com>
---
Documentation/git-merge.txt | 20 +++++++++-------
git-merge.sh | 50 ++++++++++++++++++++++++-------------------
2 files changed, 39 insertions(+), 31 deletions(-)
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 9cf761d..845d0ed 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -36,7 +36,7 @@ include::merge-options.txt[]
<remote>::
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.
+ usually means you are trying an Octopus.
include::fast-forward-options.txt[]
@@ -158,11 +158,12 @@ After seeing a conflict, you can do two things:
JOINING MORE THAN TWO HISTORIES
-------------------------------
-More than one remote may be specified on the command line. Those
-remotes are used for selecting the merge startegy and is also used in
-the merge commit message. However, some of these remotes may not be
-independent. Only remotes with independent heads (reduced parents)
-will be recorded in the merge commit object.
+More than one remote may be specified on the command line. Some of
+these remotes may not have independent heads. Git will only use the
+remotes with independent heads (reduced parents) for selecting the
+merge startegy. The reduced parents are the parents recorded in the
+merge commit object. However, the commit message will reflect the
+remotes specified on the command line.
The following shows master and two topic branches. topicB is based
on topicA, topicA is previously branched off from master:
@@ -177,9 +178,10 @@ on topicA, topicA is previously branched off from master:
------------
Merging topicA and topicB to the master branch will select the merge
-strategy based on all three branches (an Octopus). master and topicB
-are the reduced parents and are therefore the only parents recorded in
-the merge commit object:
+strategy based on the two independent branch heads, tip of the master
+branch and the tip of the topicB branch (a two head strategy). The
+commits are also the reduced parents recorded in the merge commit
+object:
------------
diff --git a/git-merge.sh b/git-merge.sh
index fc14c4b..775dae7 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -344,11 +344,16 @@ set x $remoteheads ; shift
find_reduced_parents "$@"
-actual_parents=$(git rev-parse "$@")
+# ff_head may be included here or later in actual parents
+if test -n "$reduced_parents"
+then
+ test $head = $ff_head ||
+ reduced_parents="$ff_head$LF$reduced_parents"
+fi
case "$use_strategies" in
'')
- case "$actual_parents" in
+ case "$reduced_parents" in
?*"$LF"?*)
var="`git config --get pull.octopus`"
if test -n "$var"
@@ -413,17 +418,23 @@ then
finish "$new_head" "$msg" || exit
dropsave
exit 0
+ else
+ reduced_parents="$ff_head"
+ ff_head=$head
fi
+else
+ test $head != $ff_head -a $fast_forward = never &&
+ reduced_parents="$ff_head$LF$reduced_parents"
fi
-case "$actual_parents" in
+case "$reduced_parents" in
?*"$LF"?*)
- # We have more than one actual parent
- common=$(git show-branch --merge-base $head $actual_parents)
+ # We have more than one reduced parent
+ common=$(git show-branch --merge-base $head $reduced_parents)
;;
*)
- # We have exactly one actual parent
- test "$common" != not_queried || common=$(git merge-base --all $head $actual_parents)
+ # We have exactly one reduced parent
+ test "$common" != not_queried || common=$(git merge-base --all $head $reduced_parents)
case "$common" in
?*"$LF"?*)
# We are not doing octopus and not fast forward. Need a
@@ -436,13 +447,13 @@ case "$actual_parents" in
# See if it is really trivial.
git var GIT_COMMITTER_IDENT >/dev/null || exit
echo "Trying really trivial in-index merge..."
- if git read-tree --trivial -m -u -v $common $head $actual_parents &&
+ if git read-tree --trivial -m -u -v $common $head $reduced_parents &&
result_tree=$(git write-tree)
then
echo "Wonderful."
result_commit=$(
printf '%s\n' "$merge_msg" |
- git commit-tree $result_tree -p HEAD -p $actual_parents
+ git commit-tree $result_tree -p HEAD -p $reduced_parents
) || exit
finish "$result_commit" "In-index merge"
dropsave
@@ -491,7 +502,7 @@ do
# Remember which strategy left the state in the working tree
wt_strategy=$strategy
- git-merge-$strategy $common -- "$head_arg" $actual_parents
+ git-merge-$strategy $common -- "$head_arg" $reduced_parents
exit=$?
if test "$no_commit" = t && test "$exit" = 0
then
@@ -527,17 +538,12 @@ done
# auto resolved the merge cleanly.
if test '' != "$result_tree"
then
- if test $fast_forward = allow
- then
- parents=$(git show-branch --independent "$head" "$@")
- else
- 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
- finish "$result_commit" "Merge made by $wt_strategy."
- dropsave
- exit 0
+ test $head = $ff_head && reduced_parents="$head$LF$reduced_parents"
+ parents=$(echo "$reduced_parents" | sed -e 's/^/-p /')
+ result_commit=$(printf '%s\n' "$merge_msg" | git commit-tree $result_tree $parents) || exit
+ finish "$result_commit" "Merge made by $wt_strategy."
+ dropsave
+ exit 0
fi
# Pick the result from the best strategy and have the user fix it up.
@@ -561,7 +567,7 @@ case "$best_strategy" in
echo "Rewinding the tree to pristine..."
restorestate
echo "Using the $best_strategy to prepare resolving by hand."
- git-merge-$best_strategy $common -- "$head_arg" $actual_parents
+ git-merge-$best_strategy $common -- "$head_arg" $reduced_parents
;;
esac
--
1.5.5.1.499.g878b8
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 6/6] Introduce fast forward option only
2008-05-22 1:16 ` [PATCH 5/6] Head reduction before selecting merge strategy Junio C Hamano
@ 2008-05-22 1:16 ` Junio C Hamano
0 siblings, 0 replies; 9+ messages in thread
From: Junio C Hamano @ 2008-05-22 1:16 UTC (permalink / raw)
To: git
From: Sverre Hvammen Johansen <hvammen@gmail.com>
This commit introduces fast forward option 'only'. With --ff=only
merge succeeds only if it resolves to fast-forward merge.
This feature is useful for cases where a rebase is desired
instead of a real merge. This option can then be used to
avoid an accidental merge.
See the documentation for further details.
Signed-off-by: Sverre Hvammen Johansen <hvammen@gmail.com>
---
Documentation/fast-forward-options.txt | 9 ++
git-merge.sh | 12 +-
git-pull.sh | 2 +-
t/t7601-merge-ff-options.sh | 214 ++++++++++++++++++++++++++++++++
4 files changed, 231 insertions(+), 6 deletions(-)
diff --git a/Documentation/fast-forward-options.txt b/Documentation/fast-forward-options.txt
index 9374aa9..41580ea 100644
--- a/Documentation/fast-forward-options.txt
+++ b/Documentation/fast-forward-options.txt
@@ -12,6 +12,10 @@ never::
Generate a merge commit even if the merge resolves as a
fast-forward. This option is equivalent of '--no-ff'.
+only::
+ Only allow a fast-forward. The merge will fail unless HEAD is
+ up to date or the merge resolves as a fast-forward.
+
If your workflow is always to branch from the special branch
("master") when working on a topic and merge that back to "master", if
you happen to have worked only on a single topic and the "master" was
@@ -42,3 +46,8 @@ The first merge of topicA or the only merge of topicB would have
resulted in a fast forward without '--ff=never'. Topic A consist of
those commits that can be reached from master^2 without passing
through any of the first-parent ancestries of master.
+
+However, if the workflow require that the branch you are merging with
+is based on the current HEAD you can use "only fast forward" policy to
+enforce fast forward or a failure. The last merge of topicA in
+the example above would have failed with '--ff=only'.
diff --git a/git-merge.sh b/git-merge.sh
index 775dae7..b87e125 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -168,21 +168,21 @@ parse_config () {
no_commit=t ;;
--ff)
case "$2" in
- allow|never)
+ allow|never|only)
fast_forward=$2; shift ;;
-*)
fast_forward=allow ;;
*)
- die "Available fast-forward options are: allow and newer" ;;
+ die "Available fast-forward options are: allow, newer, and only" ;;
esac
;;
--ff=*)
fast_forward=${1#--ff=}
case "$fast_forward" in
- allow|never)
+ allow|never|only)
;;
*)
- die "Available fast-forward options are: allow and newer" ;;
+ die "Available fast-forward options are: allow, newer, and only" ;;
esac
;;
--no-ff)
@@ -209,7 +209,7 @@ parse_config () {
shift
done
test "$fast_forward" = allow -o "$squash" = "" ||
- die "You cannot combine --squash with --ff=never"
+ die "You cannot combine --squash with --ff=never or --ff=only."
args_left=$#
}
@@ -347,6 +347,8 @@ find_reduced_parents "$@"
# ff_head may be included here or later in actual parents
if test -n "$reduced_parents"
then
+ test $fast_forward = only &&
+ die "--ff=only can not handle more than one real parent"
test $head = $ff_head ||
reduced_parents="$ff_head$LF$reduced_parents"
fi
diff --git a/git-pull.sh b/git-pull.sh
index 9e91e75..c5fa1ee 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -41,7 +41,7 @@ do
no_ff=--ff ;;
--no-ff)
no_ff=--no-ff ;;
- --ff=allow|--ff=never)
+ --ff=allow|--ff=only|--ff=never)
no_ff=$1 ;;
-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
--strateg=*|--strategy=*|\
diff --git a/t/t7601-merge-ff-options.sh b/t/t7601-merge-ff-options.sh
index c7c6d14..56e8370 100755
--- a/t/t7601-merge-ff-options.sh
+++ b/t/t7601-merge-ff-options.sh
@@ -662,4 +662,218 @@ test_expect_success 'merge c1 with new repository (pull --ff=never)' '
test_debug 'gitk --all'
+test_expect_success 'merge c0 with c1 (--ff=only overrides --no-ff)' '
+ git reset --hard c0 &&
+ git config branch.master.mergeoptions "--no-ff" &&
+ git merge --ff=only c1 &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c0 with c1 (--ff=only in config)' '
+ git reset --hard c0 &&
+ git config branch.master.mergeoptions "--ff=only" &&
+ git merge c1 &&
+ test_tick &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c0 (--ff=only in config)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "--ff=only" &&
+ git merge c0 &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c2 (--ff=only in config)' '
+ git reset --hard c1 &&
+ test_tick &&
+ git config branch.master.mergeoptions "--ff=only" &&
+ test_must_fail git merge c2 &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c0 with c1 (--ff=only)' '
+ git reset --hard c0 &&
+ test_tick &&
+ git merge --ff=only c1 &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c0 (--ff=only)' '
+ git reset --hard c1 &&
+ test_tick &&
+ git merge --ff=only c0 &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c0 with c1 and c2 (--ff=only)' '
+ git reset --hard c0 &&
+ test_must_fail git merge --ff=only c1 c2 &&
+ verify_merge file result.0 &&
+ verify_head $c0
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c0 (--ff=only)' '
+ git reset --hard c1 &&
+ test_tick &&
+ git merge --ff=only c0 &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c2 (--ff=only overrides --no-ff)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "--no-ff" &&
+ test_tick &&
+ test_must_fail git merge c2 --ff=only &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c0 with c1 (--no-ff overrides --ff=only)' '
+ git reset --hard c0 &&
+ git config branch.master.mergeoptions "--ff=only" &&
+ test_tick &&
+ git merge --no-ff c1 &&
+ verify_merge file result.1 &&
+ verify_parents $c0 $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c2 (--ff owerrides --ff=only)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "--ff=only" &&
+ test_tick &&
+ git merge --ff c2 &&
+ verify_merge file result.1-5 &&
+ verify_parents $c1 $c2
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with x0 (--squash combined with --ff=only)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ test_must_fail git merge x0 --squash --ff=only &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge x0 with c1 (--squash combined with --ff=only)' '
+ git reset --hard x0 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ test_must_fail git merge c1 --squash --ff=only &&
+ verify_merge file result.1-5 &&
+ verify_head $x0
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge c1 with c2 (--squash combined with --ff=only)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ test_must_fail git merge c2 --squash --ff=only &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge c1 with x0 (--no-commit combined with --ff=only)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge x0 --no-commit --ff=only &&
+ verify_merge file result.1-5 &&
+ verify_head $x0
+'
+
+test_debug 'gitk --all'
+
+
+test_expect_success 'merge x0 with c1 (--no-commit combined with --ff=only)' '
+ git reset --hard x0 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ git merge c1 --no-commit --ff=only &&
+ verify_merge file result.1-5 &&
+ verify_head $x0
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c2 (--no-commit combined with --ff=only)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "" &&
+ test_tick &&
+ test_must_fail git merge c2 --no-commit --ff=only &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with x1 (pull --ff=only)' '
+ git reset --hard c1 &&
+ test_tick &&
+ git pull --ff=only clone refs/heads/master &&
+ verify_merge file result.1-13 &&
+ verify_head $x1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge x2 with x1 (pull --ff=only)' '
+ git reset --hard x2 &&
+ test_tick &&
+ test_must_fail git pull --ff=only clone refs/heads/master &&
+ verify_merge file result.5-13 &&
+ verify_head $x2
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with new repository (pull --ff=only)' '
+ git reset --hard c1 &&
+ test_tick &&
+ test_must_fail git pull --ff=only new refs/heads/master &&
+ verify_merge file result.1 &&
+ verify_head $c1
+'
+
+test_debug 'gitk --all'
+
test_done
--
1.5.5.1.499.g878b8
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 4/6] Restructure git-merge.sh
2008-05-22 1:16 ` [PATCH 4/6] Restructure git-merge.sh Junio C Hamano
2008-05-22 1:16 ` [PATCH 5/6] Head reduction before selecting merge strategy Junio C Hamano
@ 2008-05-22 10:48 ` Johannes Schindelin
2008-05-22 12:50 ` Johannes Schindelin
1 sibling, 1 reply; 9+ messages in thread
From: Johannes Schindelin @ 2008-05-22 10:48 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
On Wed, 21 May 2008, Junio C Hamano wrote:
> From: Sverre Hvammen Johansen <hvammen@gmail.com>
>
> Restructure git-merge.sh for preparation of new feature:
>
> Head reduction before selecting merge strategy
>
> Some aspects of this patch does not make much sense without
> the next patch in this series.
As my student is pretty busy rewriting git-merge into a C builtin, can I
ask to hold this patch off?
Thanks,
Dscho
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 4/6] Restructure git-merge.sh
2008-05-22 10:48 ` [PATCH 4/6] Restructure git-merge.sh Johannes Schindelin
@ 2008-05-22 12:50 ` Johannes Schindelin
0 siblings, 0 replies; 9+ messages in thread
From: Johannes Schindelin @ 2008-05-22 12:50 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Hi,
On Thu, 22 May 2008, Johannes Schindelin wrote:
> On Wed, 21 May 2008, Junio C Hamano wrote:
>
> > From: Sverre Hvammen Johansen <hvammen@gmail.com>
> >
> > Restructure git-merge.sh for preparation of new feature:
> >
> > Head reduction before selecting merge strategy
> >
> > Some aspects of this patch does not make much sense without
> > the next patch in this series.
>
> As my student is pretty busy rewriting git-merge into a C builtin, can I
> ask to hold this patch off?
Just to keep you updated: Miklos has a version of builtin-merge which
passes all but three test scripts (in total, there are only 6 test cases
that do not pass).
Given that the restructuring of git-merge.sh affects only the octopus case
(IIRC...), I think it is not asked too much to redo the change in the
builtin-merge, which should be easier, too.
Ciao,
Dscho
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2008-05-22 12:51 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-22 1:16 [PATCH 0/6] Forwarding Sverre's "merge --ff=<allow,only,never>" series Junio C Hamano
2008-05-22 1:16 ` [PATCH 1/6] Documentation for joining more than two histories Junio C Hamano
2008-05-22 1:16 ` [PATCH 2/6] New merge tests Junio C Hamano
2008-05-22 1:16 ` [PATCH 3/6] Introduce -ff=<fast forward option> Junio C Hamano
2008-05-22 1:16 ` [PATCH 4/6] Restructure git-merge.sh Junio C Hamano
2008-05-22 1:16 ` [PATCH 5/6] Head reduction before selecting merge strategy Junio C Hamano
2008-05-22 1:16 ` [PATCH 6/6] Introduce fast forward option only Junio C Hamano
2008-05-22 10:48 ` [PATCH 4/6] Restructure git-merge.sh Johannes Schindelin
2008-05-22 12:50 ` Johannes Schindelin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).