diff mbox series

[5/9] pull: ensure --rebase overrides ability to ff

Message ID 3d9ff69198e5a604b124bf861df4d6ecf6eb661e.1626536508.git.gitgitgadget@gmail.com (mailing list archive)
State New, archived
Headers show
Series Handle pull option precedence | expand

Commit Message

Elijah Newren July 17, 2021, 3:41 p.m. UTC
From: Elijah Newren <newren@gmail.com>

Now that the handling of fast-forward-only in combination with rebases
has been moved before the merge-vs-rebase logic, we have an unnecessary
special fast-forward case left within the rebase logic.  Actually, more
than unnecessary, it's actually a violation of the rules.  As per
https://lore.kernel.org/git/xmqqwnpqot4m.fsf@gitster.g/, --rebase is
supposed to override all ff flags other than an explicit --ff-only.
Ensure that it does so by removing the fast-forward special case that
exists within the rebase logic.

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 builtin/pull.c  | 8 +-------
 t/t5520-pull.sh | 6 +++---
 2 files changed, 4 insertions(+), 10 deletions(-)

Comments

Felipe Contreras July 17, 2021, 6:25 p.m. UTC | #1
Elijah Newren via GitGitGadget wrote:
> From: Elijah Newren <newren@gmail.com>
> 
> Now that the handling of fast-forward-only in combination with rebases
> has been moved before the merge-vs-rebase logic, we have an unnecessary
> special fast-forward case left within the rebase logic.  Actually, more
> than unnecessary, it's actually a violation of the rules.  As per
> https://lore.kernel.org/git/xmqqwnpqot4m.fsf@gitster.g/, --rebase is
> supposed to override all ff flags other than an explicit --ff-only.
> Ensure that it does so by removing the fast-forward special case that
> exists within the rebase logic.

What Junio said in one mail are not the rules.

This goes against what is described in the documentation.
Junio C Hamano July 20, 2021, 11:35 p.m. UTC | #2
"Elijah Newren via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Elijah Newren <newren@gmail.com>
>
> Now that the handling of fast-forward-only in combination with rebases
> has been moved before the merge-vs-rebase logic, we have an unnecessary
> special fast-forward case left within the rebase logic.

It is correct to say that we could call run_rebase() and it will do
the right thing, even when can_ff is true, in this codepath.

But I am not sure if you want to do this as a part of this series.

The code in question comes from 33b842a1 (pull: fast-forward "pull
--rebase=true", 2016-06-29).  It was meant as a mere optimization
to avoid calling run_rebase() when we know we have nothing to replay
on top of their head after we fast-forward, and doing a pure
fast-forward is easier by calling run_merge().

In other words, the code this patch touches should not have anything
to do with the rebase-vs-fast-forward logic.

Now, if a benchmarking tells us that there is no difference between
calling an empty run_rebase() and run_merge(), I'd be perfectly fine
with this change, with the justification that we are "discarding an
earlier optimization that has become irrelevant".  But that would be
totally outside the theme of this topic, I would think.

Thanks.

> @@ -1070,13 +1070,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
>  		    submodule_touches_in_range(the_repository, &upstream, &curr_head))
>  			die(_("cannot rebase with locally recorded submodule modifications"));
>  
> -		if (can_ff) {
> -			/* we can fast-forward this without invoking rebase */
> -			opt_ff = "--ff-only";
> -			ret = run_merge();
> -		} else {
> -			ret = run_rebase(&newbase, &upstream);
> -		}
> +		ret = run_rebase(&newbase, &upstream);
>  
>  		if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON ||
>  			     recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
> diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
> index e2c0c510222..4b50488141f 100755
> --- a/t/t5520-pull.sh
> +++ b/t/t5520-pull.sh
> @@ -295,7 +295,7 @@ test_expect_success '--rebase (merge) fast forward' '
>  	# The above only validates the result.  Did we actually bypass rebase?
>  	git reflog -1 >reflog.actual &&
>  	sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy &&
> -	echo "OBJID HEAD@{0}: pull --rebase . ff: Fast-forward" >reflog.expected &&
> +	echo "OBJID HEAD@{0}: pull --rebase . ff (finish): returning to refs/heads/to-rebase" >reflog.expected &&
>  	test_cmp reflog.expected reflog.fuzzy
>  '
>  
> @@ -307,8 +307,8 @@ test_expect_success '--rebase (am) fast forward' '
>  
>  	# The above only validates the result.  Did we actually bypass rebase?
>  	git reflog -1 >reflog.actual &&
> -	sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy &&
> -	echo "OBJID HEAD@{0}: pull --rebase . ff: Fast-forward" >reflog.expected &&
> +	sed -e "s/^[0-9a-f][0-9a-f]*/OBJID/" -e "s/[0-9a-f][0-9a-f]*$/OBJID/" reflog.actual >reflog.fuzzy &&
> +	echo "OBJID HEAD@{0}: rebase finished: refs/heads/to-rebase onto OBJID" >reflog.expected &&
>  	test_cmp reflog.expected reflog.fuzzy
>  '
Elijah Newren July 21, 2021, 12:14 a.m. UTC | #3
On Tue, Jul 20, 2021 at 4:35 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> "Elijah Newren via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > From: Elijah Newren <newren@gmail.com>
> >
> > Now that the handling of fast-forward-only in combination with rebases
> > has been moved before the merge-vs-rebase logic, we have an unnecessary
> > special fast-forward case left within the rebase logic.
>
> It is correct to say that we could call run_rebase() and it will do
> the right thing, even when can_ff is true, in this codepath.
>
> But I am not sure if you want to do this as a part of this series.

It turns out my commit message was wrong, and so was the patch.  My
changes did have a functional change, substituting one form of
submodule breakage with another.

I'll replace this with a patch that fixes the submodule issue.  (When
--ff-only is specified, we should not rebase submodules.  We should
fast-forward both the parent module and the submodules.)
diff mbox series

Patch

diff --git a/builtin/pull.c b/builtin/pull.c
index 5c9cbea37c9..5ba376a7487 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -1070,13 +1070,7 @@  int cmd_pull(int argc, const char **argv, const char *prefix)
 		    submodule_touches_in_range(the_repository, &upstream, &curr_head))
 			die(_("cannot rebase with locally recorded submodule modifications"));
 
-		if (can_ff) {
-			/* we can fast-forward this without invoking rebase */
-			opt_ff = "--ff-only";
-			ret = run_merge();
-		} else {
-			ret = run_rebase(&newbase, &upstream);
-		}
+		ret = run_rebase(&newbase, &upstream);
 
 		if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON ||
 			     recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index e2c0c510222..4b50488141f 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -295,7 +295,7 @@  test_expect_success '--rebase (merge) fast forward' '
 	# The above only validates the result.  Did we actually bypass rebase?
 	git reflog -1 >reflog.actual &&
 	sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy &&
-	echo "OBJID HEAD@{0}: pull --rebase . ff: Fast-forward" >reflog.expected &&
+	echo "OBJID HEAD@{0}: pull --rebase . ff (finish): returning to refs/heads/to-rebase" >reflog.expected &&
 	test_cmp reflog.expected reflog.fuzzy
 '
 
@@ -307,8 +307,8 @@  test_expect_success '--rebase (am) fast forward' '
 
 	# The above only validates the result.  Did we actually bypass rebase?
 	git reflog -1 >reflog.actual &&
-	sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy &&
-	echo "OBJID HEAD@{0}: pull --rebase . ff: Fast-forward" >reflog.expected &&
+	sed -e "s/^[0-9a-f][0-9a-f]*/OBJID/" -e "s/[0-9a-f][0-9a-f]*$/OBJID/" reflog.actual >reflog.fuzzy &&
+	echo "OBJID HEAD@{0}: rebase finished: refs/heads/to-rebase onto OBJID" >reflog.expected &&
 	test_cmp reflog.expected reflog.fuzzy
 '