[PATCH] git-merge: add option --no-ff

Subsystems: documentation, the rest

DORMANTno replies

20 messages, 6 authors, 2016-06-15 · open the first message on its own page

[PATCH] git-merge: add option --no-ff

From: Lars Hjemli <hidden>
Date: 2016-06-15 22:43:35

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

Although a fast-forward would normally be The Right Thing, it isn't when the
branches to be merged originated in subversion and the merge commit will
be pushed back by means of 'git svn dcommit'. In these cases, a fast-
forward merge simply will not work.

Signed-off-by: Lars Hjemli <redacted>
---
 Documentation/merge-options.txt |    4 ++++
 git-merge.sh                    |   13 +++++++++++--
 t/t6028-merge-up-to-date.sh     |   25 +++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index d64c259..ed28017 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -25,3 +25,7 @@
 	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.
diff --git a/git-merge.sh b/git-merge.sh
index 3a01db0..13b98e6 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,10 @@ do
 		merge_msg="$1"
 		have_message=t
 		;;
+	--no-ff)
+		no_ff=t
+		no_fast_forward_strategies=$all_strategies
+		;;
 	-*)	usage ;;
 	*)	break ;;
 	esac
@@ -444,7 +448,12 @@ done
 # auto resolved the merge cleanly.
 if test '' != "$result_tree"
 then
-    parents=$(git show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
+    if test $no_ff = 't'
+    then
+        parents=$(git rev-parse "$head" "$@" | sed -e 's/^/-p /')
+    else
+        parents=$(git show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
+    fi
     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/t6028-merge-up-to-date.sh b/t/t6028-merge-up-to-date.sh
index f8f3e3f..afd74e2 100755
--- a/t/t6028-merge-up-to-date.sh
+++ b/t/t6028-merge-up-to-date.sh
@@ -10,12 +10,14 @@ test_expect_success setup '
 	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
 '
 
@@ -41,6 +43,16 @@ test_expect_success 'merge -s recursive fast-forward' '
 
 '
 
+test_expect_success 'merge -s recursive --no-ff' '
+
+	git reset --hard c0 &&
+	test_tick &&
+	git merge -s recursive --no-ff c1 &&
+	test $c0 = $(git rev-parse HEAD^1) &&
+	test $c1 = $(git rev-parse HEAD^2)
+
+'
+
 test_expect_success 'merge -s ours up-to-date' '
 
 	git reset --hard c1 &&
@@ -63,6 +75,19 @@ test_expect_success 'merge -s ours fast-forward' '
 
 '
 
+test_expect_success 'merge -s ours --no-ff' '
+
+	git reset --hard c0 &&
+	test_tick &&
+	git merge -s ours --no-ff c1 &&
+	expect=$(git rev-parse c0^{tree}) &&
+	current=$(git rev-parse HEAD^{tree}) &&
+	test "$expect" = "$current" &&
+	test $c0 = $(git rev-parse HEAD^1) &&
+	test $c1 = $(git rev-parse HEAD^2)
+
+'
+
 test_expect_success 'merge -s subtree up-to-date' '
 
 	git reset --hard c1 &&
-- 
1.5.3.1.92.g2f5e

Re: [PATCH] git-merge: add option --no-ff

From: Andreas Ericsson <hidden>
Date: 2016-06-15 22:43:35

Lars Hjemli wrote:
This new option forces all merges to create a "true" merge commit, i.e. a
commit with multiple parents.

Although a fast-forward would normally be The Right Thing, it isn't when the
branches to be merged originated in subversion and the merge commit will
be pushed back by means of 'git svn dcommit'. In these cases, a fast-
forward merge simply will not work.

 	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.
+ Although a fast-forward would normally be The Right Thing, it isn't when the
+ branches to be merged originated in subversion and the merge commit will
+ be pushed back by means of 'git svn dcommit'. In these cases, a fast-
+ forward merge simply will not work.

Otherwise someone will sit down and try to figure out why this is necessary.

I'm having trouble understanding why this is needed, but I'll take your word
for it ;-)

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

Re: [PATCH] git-merge: add option --no-ff

From: Lars Hjemli <hidden>
Date: 2016-06-15 22:43:35

On 9/17/07, Andreas Ericsson [off-list ref] wrote:
Lars Hjemli wrote:
quoted
This new option forces all merges to create a "true" merge commit, i.e. a
commit with multiple parents.

Although a fast-forward would normally be The Right Thing, it isn't when the
branches to be merged originated in subversion and the merge commit will
be pushed back by means of 'git svn dcommit'. In these cases, a fast-
forward merge simply will not work.

      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.
+ Although a fast-forward would normally be The Right Thing, it isn't when the
+ branches to be merged originated in subversion and the merge commit will
+ be pushed back by means of 'git svn dcommit'. In these cases, a fast-
+ forward merge simply will not work.

Otherwise someone will sit down and try to figure out why this is necessary.
True.
I'm having trouble understanding why this is needed, but I'll take your word
for it ;-)
I'll try to explain:

When 'git-svn dcommit' decides which commits it should push back
subversion, it scans the output from 'git-log --first-parent HEAD'
looking for embedded 'git-svn-id' lines. These lines contain the url
of the upstream subversion repository + the subversion revision
number. So the problem with fast-forward merges of subversion branches
is that the output from 'git-log --first-parent HEAD' will show
commits from the wrong subversion branch (the fast-forwarded commits).

This could maybe be fixed in git-svn if it learned a different way of
discovering the upstream subversion branch, but then it would make
git-svn commit n revisions to subversion (again, the fast-forwarded
commits) instead of a single merge-commit. This would look (in
subversion) like a series of n cherry-picks from the merged branch.

Btw: maybe the --no-ff section in merge-options.txt could just link to
git-svn.txt, which in turn could have some lengthy explanation about
merge --no-ff/dcommit behaviour?

--
larsh

Re: [PATCH] git-merge: add option --no-ff

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:43:35

Hi,

On Mon, 17 Sep 2007, Lars Hjemli wrote:
When 'git-svn dcommit' decides which commits it should push back
subversion, it scans the output from 'git-log --first-parent HEAD'
looking for embedded 'git-svn-id' lines. These lines contain the url
of the upstream subversion repository + the subversion revision
number.
So the problem with fast-forward merges of subversion branches is that 
the output from 'git-log --first-parent HEAD' will show commits from the 
wrong subversion branch (the fast-forwarded commits).
Ah, I think I know what you're trying to get at.  But "git svn fetch && 
git rebase git-svn" might be a better approach than "git svn fetch && git 
merge --no-ff git-svn", no?

Ciao,
Dscho

Re: [PATCH] git-merge: add option --no-ff

From: Chris Shoemaker <hidden>
Date: 2016-06-15 22:43:35

On Mon, Sep 17, 2007 at 02:23:38PM +0100, Johannes Schindelin wrote:
Hi,

On Mon, 17 Sep 2007, Lars Hjemli wrote:
quoted
When 'git-svn dcommit' decides which commits it should push back
subversion, it scans the output from 'git-log --first-parent HEAD'
looking for embedded 'git-svn-id' lines. These lines contain the url
of the upstream subversion repository + the subversion revision
number.
quoted
So the problem with fast-forward merges of subversion branches is that 
the output from 'git-log --first-parent HEAD' will show commits from the 
wrong subversion branch (the fast-forwarded commits).
Ah, I think I know what you're trying to get at.  But "git svn fetch && 
git rebase git-svn" might be a better approach [...]
BTW, this is spelled "git svn rebase" these days.

-chris

Re: [PATCH] git-merge: add option --no-ff

From: Lars Hjemli <hidden>
Date: 2016-06-15 22:43:35

[Cc'd Eric since he's the expert on git-svn]

On 9/17/07, Johannes Schindelin [off-list ref] wrote:
Hi,

On Mon, 17 Sep 2007, Lars Hjemli wrote:
quoted
When 'git-svn dcommit' decides which commits it should push back
subversion, it scans the output from 'git-log --first-parent HEAD'
looking for embedded 'git-svn-id' lines. These lines contain the url
of the upstream subversion repository + the subversion revision
number.
quoted
So the problem with fast-forward merges of subversion branches is that
the output from 'git-log --first-parent HEAD' will show commits from the
wrong subversion branch (the fast-forwarded commits).
Ah, I think I know what you're trying to get at.  But "git svn fetch &&
git rebase git-svn" might be a better approach than "git svn fetch && git
merge --no-ff git-svn", no?
If I'm understanding you right: no. After  a rebase, the commits would
be ignored by git-svn when looking for the subversion upstream branch
(since the commit SHA1's would no longer match the ones stored in
git-svn's rev_db), but the subversion history would look like
'cherry-picked n commits from merged branch' after dcommit.

-- 
larsh

Re: [PATCH] git-merge: add option --no-ff

From: Lars Hjemli <hidden>
Date: 2016-06-15 22:43:35

On 9/17/07, Chris Shoemaker [off-list ref] wrote:
On Mon, Sep 17, 2007 at 02:23:38PM +0100, Johannes Schindelin wrote:
quoted
Ah, I think I know what you're trying to get at.  But "git svn fetch &&
git rebase git-svn" might be a better approach [...]
BTW, this is spelled "git svn rebase" these days.
Not in this case, since 'git-svn rebase' would fall in the same trap
as 'git-svn dcommit'.

-- 
larsh

Re: [PATCH] git-merge: add option --no-ff

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:43:35

Hi,

On Mon, 17 Sep 2007, Chris Shoemaker wrote:
On Mon, Sep 17, 2007 at 02:23:38PM +0100, Johannes Schindelin wrote:
quoted
"git svn fetch && git rebase git-svn" might be a better approach [...]
BTW, this is spelled "git svn rebase" these days.
Heh.  Missed that.

Thanks,
Dscho

Re: [PATCH] git-merge: add option --no-ff

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:43:35

Hi,

On Mon, 17 Sep 2007, Lars Hjemli wrote:
[Cc'd Eric since he's the expert on git-svn]

On 9/17/07, Johannes Schindelin [off-list ref] wrote:
quoted
Ah, I think I know what you're trying to get at.  But "git svn fetch 
&& git rebase git-svn" might be a better approach than "git svn fetch 
&& git merge --no-ff git-svn", no?
If I'm understanding you right: no. After a rebase, the commits would be 
ignored by git-svn when looking for the subversion upstream branch 
(since the commit SHA1's would no longer match the ones stored in 
git-svn's rev_db), but the subversion history would look like 
'cherry-picked n commits from merged branch' after dcommit.
I feel that I am not really qualified here, since I am a strict git-svn 
_user_, but AFAICT it worked here all the time, _especially_ with fast 
forwards.  The trick is that all commits that were added after the branch 
point do _not_ contain any svn lines.

But then, I do not use svn branches here, and that might be the problem?

Ciao,
Dscho

Re: [PATCH] git-merge: add option --no-ff

From: Lars Hjemli <hidden>
Date: 2016-06-15 22:43:35

On 9/17/07, Johannes Schindelin [off-list ref] wrote:
But then, I do not use svn branches here, and that might be the problem?
Probably. The case I'm trying to solve is:
  -git-svn branch A is merged into git-svn branch B
  -A is a fast-forward of B

This might look unrealistic, but it happened to me today when I wanted
to merge a feature-branch into a relase-branch. The release-branch had
previously been merged into the feature-branch (to get a few
bugfixes), but the release-branch had not changed since this merge. So
when merging the feature-branch into the release-branch it just
fast-forwarded, leaving me with an 'un-dcomittable' release-branch. I
obviously could have done the merge in subversion (haha!), but doing
it in git preserves the correct history.

Btw: I have redone the merge with --no-ff, and dcommit then worked
like a charm ;-)

-- 
larsh

Re: [PATCH] git-merge: add option --no-ff

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:43:35

Hi,

On Mon, 17 Sep 2007, Lars Hjemli wrote:
On 9/17/07, Johannes Schindelin [off-list ref] wrote:
quoted
But then, I do not use svn branches here, and that might be the problem?
Probably. The case I'm trying to solve is:
  -git-svn branch A is merged into git-svn branch B
  -A is a fast-forward of B

This might look unrealistic, but it happened to me today when I wanted
to merge a feature-branch into a relase-branch. The release-branch had
previously been merged into the feature-branch (to get a few
bugfixes), but the release-branch had not changed since this merge. So
when merging the feature-branch into the release-branch it just
fast-forwarded, leaving me with an 'un-dcomittable' release-branch. I
obviously could have done the merge in subversion (haha!), but doing
it in git preserves the correct history.

Btw: I have redone the merge with --no-ff, and dcommit then worked
like a charm ;-)
Yep, I can see that now.

But maybe there is a better method to detect the latest svn id, by not 
only looking up the svn ids, but making sure that they come from the 
current branch?

(I'm happily unaware of git-svn's internals, so that might not be 
feasible... But I think that it might be worth fixing that for the git-svn 
idiot like me, since I would never guess that I have to specify --no-ff 
when working on branches that come from git-svn...)

Ciao,
Dscho

Re: [PATCH] git-merge: add option --no-ff

From: Lars Hjemli <hidden>
Date: 2016-06-15 22:43:35

On 9/17/07, Johannes Schindelin [off-list ref] wrote:
Hi,

On Mon, 17 Sep 2007, Lars Hjemli wrote:
quoted
On 9/17/07, Johannes Schindelin [off-list ref] wrote:
quoted
But then, I do not use svn branches here, and that might be the problem?
Probably. The case I'm trying to solve is:
  -git-svn branch A is merged into git-svn branch B
  -A is a fast-forward of B

This might look unrealistic, but it happened to me today when I wanted
to merge a feature-branch into a relase-branch. The release-branch had
previously been merged into the feature-branch (to get a few
bugfixes), but the release-branch had not changed since this merge. So
when merging the feature-branch into the release-branch it just
fast-forwarded, leaving me with an 'un-dcomittable' release-branch. I
obviously could have done the merge in subversion (haha!), but doing
it in git preserves the correct history.

Btw: I have redone the merge with --no-ff, and dcommit then worked
like a charm ;-)
Yep, I can see that now.

But maybe there is a better method to detect the latest svn id, by not
only looking up the svn ids, but making sure that they come from the
current branch?
Actually, I looked into this last week (my --upstream rants), and I
guess git-svn could use the --track information in .git/config (if
present) as a sanity check when resolving the upstream. But this would
still make the subversion history look like crap after a fast-forward
merge of the kind I was messing with today. It was logically a merge,
but if dcommit had worked 'correctly' it would have created ~150 new
revisions in the release-branch instead of the single merge commit.
(I'm happily unaware of git-svn's internals, so that might not be
feasible... But I think that it might be worth fixing that for the git-svn
idiot like me, since I would never guess that I have to specify --no-ff
when working on branches that come from git-svn...)
In the normal cases there is no need for --no-ff, only in degenerated
cases like the one I stumbled upon today ;-)

I'll resend the patch with a link from merge-options.txt to
git-svn.txt and try to describe (in git-svn.txt) when to use --no-ff.

-- 
larsh

Re: [PATCH] git-merge: add option --no-ff

From: Chris Shoemaker <hidden>
Date: 2016-06-15 22:43:35

On Mon, Sep 17, 2007 at 04:12:56PM +0200, Lars Hjemli wrote:
On 9/17/07, Johannes Schindelin [off-list ref] wrote:
quoted
But then, I do not use svn branches here, and that might be the problem?
Probably. The case I'm trying to solve is:
  -git-svn branch A is merged into git-svn branch B
  -A is a fast-forward of B
Ah, now I see what you mean.  But, IIUC, if you want to dcommit your
merge, you should treat it the way svn treats it, with git-merge
--squash.  Then, dcommit won't be confused about the branch you're
committing to.

-chris
This might look unrealistic, but it happened to me today when I wanted
to merge a feature-branch into a relase-branch. The release-branch had
previously been merged into the feature-branch (to get a few
bugfixes), but the release-branch had not changed since this merge. So
when merging the feature-branch into the release-branch it just
fast-forwarded, leaving me with an 'un-dcomittable' release-branch. I
obviously could have done the merge in subversion (haha!), but doing
it in git preserves the correct history.

Btw: I have redone the merge with --no-ff, and dcommit then worked
like a charm ;-)

-- 
larsh
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Re: [PATCH] git-merge: add option --no-ff

From: Lars Hjemli <hidden>
Date: 2016-06-15 22:43:35

On 9/17/07, Chris Shoemaker [off-list ref] wrote:
On Mon, Sep 17, 2007 at 04:12:56PM +0200, Lars Hjemli wrote:
quoted
On 9/17/07, Johannes Schindelin [off-list ref] wrote:
quoted
But then, I do not use svn branches here, and that might be the problem?
Probably. The case I'm trying to solve is:
  -git-svn branch A is merged into git-svn branch B
  -A is a fast-forward of B
Ah, now I see what you mean.  But, IIUC, if you want to dcommit your
merge, you should treat it the way svn treats it, with git-merge
--squash.  Then, dcommit won't be confused about the branch you're
committing to.
Yeah, --squash is a viable option (I _almost_ used it ;-) but I wanted
to keep the merge-history on the git side (without modifying the
grafts-file).

-- 
larsh

[PATCH] git-merge: add option --no-ff

From: Lars Hjemli <hidden>
Date: 2016-06-15 22:43:35

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

Although a fast-forward merge would normally be the right thing to do with
git branches, it is suboptimal when operating on git-svn branches since it
makes 'git-svn dcommit' fail to recognize the correct upstream subversion
branch. But performing such a merge with --no-ff specified will both make
git-svn dcommit recognize the correct upstream and create the logically
correct history in subversion (the merge performed in git will be recorded
as a single revision in subversion, not as a series of revisions seemingly
cherry-picked from the merged branch).

Signed-off-by: Lars Hjemli <redacted>
---

When updating git-svn.txt, I noticed that we might want to update the 
section "DESIGN PHILOSOPHY". Eric?


 Documentation/git-svn.txt       |   13 +++++++++++++
 Documentation/merge-options.txt |    5 +++++
 git-merge.sh                    |   13 +++++++++++--
 t/t6028-merge-up-to-date.sh     |   25 +++++++++++++++++++++++++
 4 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index be2e34e..c510c21 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 belive 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..13b98e6 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,10 @@ do
 		merge_msg="$1"
 		have_message=t
 		;;
+	--no-ff)
+		no_ff=t
+		no_fast_forward_strategies=$all_strategies
+		;;
 	-*)	usage ;;
 	*)	break ;;
 	esac
@@ -444,7 +448,12 @@ done
 # auto resolved the merge cleanly.
 if test '' != "$result_tree"
 then
-    parents=$(git show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
+    if test $no_ff = 't'
+    then
+        parents=$(git rev-parse "$head" "$@" | sed -e 's/^/-p /')
+    else
+        parents=$(git show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
+    fi
     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/t6028-merge-up-to-date.sh b/t/t6028-merge-up-to-date.sh
index f8f3e3f..afd74e2 100755
--- a/t/t6028-merge-up-to-date.sh
+++ b/t/t6028-merge-up-to-date.sh
@@ -10,12 +10,14 @@ test_expect_success setup '
 	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
 '
 
@@ -41,6 +43,16 @@ test_expect_success 'merge -s recursive fast-forward' '
 
 '
 
+test_expect_success 'merge -s recursive --no-ff' '
+
+	git reset --hard c0 &&
+	test_tick &&
+	git merge -s recursive --no-ff c1 &&
+	test $c0 = $(git rev-parse HEAD^1) &&
+	test $c1 = $(git rev-parse HEAD^2)
+
+'
+
 test_expect_success 'merge -s ours up-to-date' '
 
 	git reset --hard c1 &&
@@ -63,6 +75,19 @@ test_expect_success 'merge -s ours fast-forward' '
 
 '
 
+test_expect_success 'merge -s ours --no-ff' '
+
+	git reset --hard c0 &&
+	test_tick &&
+	git merge -s ours --no-ff c1 &&
+	expect=$(git rev-parse c0^{tree}) &&
+	current=$(git rev-parse HEAD^{tree}) &&
+	test "$expect" = "$current" &&
+	test $c0 = $(git rev-parse HEAD^1) &&
+	test $c1 = $(git rev-parse HEAD^2)
+
+'
+
 test_expect_success 'merge -s subtree up-to-date' '
 
 	git reset --hard c1 &&
-- 
1.5.3.1.92.g2f5e

Re: [PATCH] git-merge: add option --no-ff

From: Eric Wong <hidden>
Date: 2016-06-15 22:43:35

Lars Hjemli [off-list ref] wrote:
This option forces fast-forward merges to create a "true" merge commit,
i.e. a commit with multiple parents.

Although a fast-forward merge would normally be the right thing to do with
git branches, it is suboptimal when operating on git-svn branches since it
makes 'git-svn dcommit' fail to recognize the correct upstream subversion
branch. But performing such a merge with --no-ff specified will both make
git-svn dcommit recognize the correct upstream and create the logically
correct history in subversion (the merge performed in git will be recorded
as a single revision in subversion, not as a series of revisions seemingly
cherry-picked from the merged branch).

Signed-off-by: Lars Hjemli <redacted>
Would automatically enabling --no-ff when it detects merging of two (or
more) SVN branches be a good thing?  We can add scripting support to
git-svn for detecting if any given commit is really from SVN or not.
Then we could do something like this in git-merge

---------------------------- 8< --------------------------------
if git-svn test-svn-commits "$@"
then
	no_ff=t
	no_fast_forward_strategies=$all_strategies
fi
---------------------------- 8< --------------------------------

It'd probably prevent a lot of users from shooting themselves in the
foot if they forget to read or learn about the --no-ff option.
---

When updating git-svn.txt, I noticed that we might want to update the 
section "DESIGN PHILOSOPHY". Eric?
Yeah.  That's very much out of date.  I'll update it in a bit.

-- 
Eric Wong

Re: [PATCH] git-merge: add option --no-ff

From: Lars Hjemli <hidden>
Date: 2016-06-15 22:43:35

On 9/18/07, Eric Wong [off-list ref] wrote:
Would automatically enabling --no-ff when it detects merging of two (or
more) SVN branches be a good thing?
I'd say 'git-svn merge' as a wrapper for 'git merge --no-ff' would be cleaner.

--
larsh

Re: [PATCH] git-merge: add option --no-ff

From: Eric Wong <hidden>
Date: 2016-06-15 22:43:35

Lars Hjemli [off-list ref] wrote:
On 9/18/07, Eric Wong [off-list ref] wrote:
quoted
Would automatically enabling --no-ff when it detects merging of two (or
more) SVN branches be a good thing?
I'd say 'git-svn merge' as a wrapper for 'git merge --no-ff' would be cleaner.
That still involves having to get the user to use something new to avoid
shooting themselves in the foot.  Perhaps putting a
"test -d $GIT_DIR/svn" condition in front of the git-svn call I proposed
in git-merge would be alright.

If anybody else is thinking about 'git-svn rebase', this is completely
different.  Using git-rebase alone doesn't allow git-svn users to shoot
themselves in the foot like git-merge does.  'git-svn rebase' only
serves to minimize typing and brain power needed to operate git-svn.

-- 
Eric Wong

Re: [PATCH] git-merge: add option --no-ff

From: Peter Baumann <hidden>
Date: 2016-06-15 22:43:35

On Mon, Sep 17, 2007 at 06:23:04PM +0200, Lars Hjemli wrote:
quoted hunk
This option forces fast-forward merges to create a "true" merge commit,
i.e. a commit with multiple parents.

Although a fast-forward merge would normally be the right thing to do with
git branches, it is suboptimal when operating on git-svn branches since it
makes 'git-svn dcommit' fail to recognize the correct upstream subversion
branch. But performing such a merge with --no-ff specified will both make
git-svn dcommit recognize the correct upstream and create the logically
correct history in subversion (the merge performed in git will be recorded
as a single revision in subversion, not as a series of revisions seemingly
cherry-picked from the merged branch).

Signed-off-by: Lars Hjemli <redacted>
---

When updating git-svn.txt, I noticed that we might want to update the 
section "DESIGN PHILOSOPHY". Eric?


 Documentation/git-svn.txt       |   13 +++++++++++++
 Documentation/merge-options.txt |    5 +++++
 git-merge.sh                    |   13 +++++++++++--
 t/t6028-merge-up-to-date.sh     |   25 +++++++++++++++++++++++++
 4 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index be2e34e..c510c21 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 belive 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..13b98e6 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,10 @@ do
 		merge_msg="$1"
 		have_message=t
 		;;
+	--no-ff)
+		no_ff=t
+		no_fast_forward_strategies=$all_strategies
+		;;
 	-*)	usage ;;
 	*)	break ;;
 	esac
@@ -444,7 +448,12 @@ done
 # auto resolved the merge cleanly.
 if test '' != "$result_tree"
 then
-    parents=$(git show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
+    if test $no_ff = 't'
This should be quoted, e.g.
  +    if test "$no_ff" = 't'

Otherwise I get an error like the following:

  xp:/tmp/va (a)$ git merge b
  Renamed msg.cc->common/msg.cc
  Auto-merged common/msg.cc
  Renamed msg.h->common/msg.h
  Auto-merged common/msg.h
  Renamed sampler/ConcurrentQueue.h->common/ConcurrentQueue.h
  Auto-merged common/ConcurrentQueue.h
  Renamed sampler/TimeoutSemaphore.h->common/TimeoutSemaphore.h
  Auto-merged common/TimeoutSemaphore.h
  /home/peter/usr/bin/git-merge: line 451: test: =: unary operator expected
  Merge made by recursive.

+    then
+        parents=$(git rev-parse "$head" "$@" | sed -e 's/^/-p /')
+    else
+        parents=$(git show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
+    fi
     result_commit=$(printf '%s\n' "$merge_msg" | git commit-tree $result_tree $parents) || exit
     finish "$result_commit" "Merge made by $wt_strategy."
     dropsave
-Peter

Re: [PATCH] git-merge: add option --no-ff

From: Lars Hjemli <hidden>
Date: 2016-06-15 22:43:35

On 9/19/07, Peter Baumann [off-list ref] wrote:
This should be quoted, e.g.
  +    if test "$no_ff" = 't'
Ouch, sorry about that. I can send an updated patch late tonight (it's
now early morning here), but I'm not sure Junio wants/needs it. Junio?

--
larsh
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help