git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Lars Hjemli <hjemli@gmail.com>
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org
Subject: [PATCH 1/2] git-merge: add option --no-ff
Date: Thu, 20 Sep 2007 14:53:08 +0200	[thread overview]
Message-ID: <1190292789-16203-2-git-send-email-hjemli@gmail.com> (raw)
In-Reply-To: <1190292789-16203-1-git-send-email-hjemli@gmail.com>

This option forces all merges to create a "true" merge commit, i.e. a commit
with multiple parents.

A fast-forward merge will often be considered The Right Thing when working
in a distributed environment, but it doesn't work well when the branches to
be merged originated in subversion and the merge commit will be pushed back
with 'git svn dcommit'. In this case, a fast-forward merge will make git-svn
mistakenly think that the current branch is tracking the merged upstream
branch. But if the merge is created with --no-ff, 'git svn dcommit' will work
as expected (and the history in subversion and git will be equal).

There are also a use-case for --no-ff in 'native git' when integrating topic
branches: if the merge of a topic-branch results in a fast-forward operation,
there will be no way to detect that the topic-branch ever existed. This might
be good or bad dependent on project policy, but both options (ff/no-ff) are
technically sane.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 Documentation/git-svn.txt       |   13 +++++++++++
 Documentation/merge-options.txt |    5 ++++
 git-merge.sh                    |   13 +++++++++-
 t/t6029-merge-integration.sh    |   46 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 75 insertions(+), 2 deletions(-)
 create mode 100755 t/t6029-merge-integration.sh

diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index e157c6a..619023d 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -475,6 +475,19 @@ use 'git-svn rebase' to update your work branch instead of 'git pull' or
 when committing into SVN, which can lead to merge commits reversing
 previous commits in SVN.
 
+If you use 'git-svn dcommit' to commit your local work to the upstream
+subversion branch, merge commits are usually handled correctly, i.e.
+git-svn will only follow the first parent of each merge commit and create
+a single subversion revision for each of them. An exception is when two
+subversion branches has been merged locally and the merge ended up as a
+fast-forward operation. This will make git-svn believe that there are no
+local changes to dcommit. To work around this issue, one can redo the
+merge using the --no-ff option:
+
+       $ git reset --hard HEAD@{1}   ## undo the fast-forward merge
+       $ git merge --no-ff <branch>
+
+
 DESIGN PHILOSOPHY
 -----------------
 Merge tracking in Subversion is lacking and doing branched development
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index d64c259..b34b888 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -25,3 +25,8 @@
 	If there is no `-s` option, a built-in list of strategies
 	is used instead (`git-merge-recursive` when merging a single
 	head, `git-merge-octopus` otherwise).
+
+--no-ff::
+	Force the creation of a merge commit even when the merge would
+	have resolved as a fast-forward operation. See gitlink:git-svn[1]
+	for a use-case for this option.
diff --git a/git-merge.sh b/git-merge.sh
index 3a01db0..70ca5ff 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2005 Junio C Hamano
 #
 
-USAGE='[-n] [--summary] [--no-commit] [--squash] [-s <strategy>] [-m=<merge-message>] <commit>+'
+USAGE='[-n] [--summary] [--no-commit] [--no-ff] [--squash] [-s <strategy>] [-m=<merge-message>] <commit>+'
 
 SUBDIRECTORY_OK=Yes
 . git-sh-setup
@@ -165,6 +165,9 @@ do
 		merge_msg="$1"
 		have_message=t
 		;;
+	--no-ff)
+		allow_fast_forward=f
+		;;
 	-*)	usage ;;
 	*)	break ;;
 	esac
@@ -444,7 +447,13 @@ done
 # auto resolved the merge cleanly.
 if test '' != "$result_tree"
 then
-    parents=$(git show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
+    if test "$allow_fast_forward" = "f"
+    then
+        parents=$(git rev-parse "$head" "$@")
+    else
+        parents=$(git show-branch --independent "$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
diff --git a/t/t6029-merge-integration.sh b/t/t6029-merge-integration.sh
new file mode 100755
index 0000000..6ba7dd9
--- /dev/null
+++ b/t/t6029-merge-integration.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+test_description='merge --no-ff'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	>file &&
+	git add file &&
+	test_tick &&
+	git commit -m initial &&
+	git tag c0 &&
+	c0=$(git rev-parse c0)
+
+	echo second >file &&
+	git add file &&
+	test_tick &&
+	git commit -m second &&
+	git tag c1 &&
+	c1=$(git rev-parse c1)
+	git branch test
+'
+
+test_expect_success 'merge c1' '
+
+	git reset --hard c0 &&
+	test_tick &&
+	git merge c1 &&
+	test $c0 = $(git rev-parse HEAD^) &&
+	test $c1 = $(git rev-parse HEAD)
+
+'
+
+test_expect_success 'merge --no-ff c1' '
+
+	git reset --hard c0 &&
+	test_tick &&
+	git merge --no-ff c1 &&
+	test $c0 = $(git rev-parse HEAD^1) &&
+	test $c1 = $(git rev-parse HEAD^2)
+
+'
+
+test_debug 'gitk &'
+
+test_done
-- 
1.5.3.2.82.g75c8d

  reply	other threads:[~2007-09-20 12:52 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-20 12:53 [PATCH 0/2] add support for per branch merge policy Lars Hjemli
2007-09-20 12:53 ` Lars Hjemli [this message]
2007-09-20 12:53   ` [PATCH 2/2] add support for branch.<name>.integrationonly Lars Hjemli
2007-09-20 13:14     ` Johannes Schindelin
2007-09-20 13:36       ` Matthieu Moy
2007-09-20 13:07 ` [PATCH 0/2] add support for per branch merge policy Lars Hjemli
2007-09-20 13:24   ` Johannes Schindelin
2007-09-20 13:38     ` Lars Hjemli

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1190292789-16203-2-git-send-email-hjemli@gmail.com \
    --to=hjemli@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).