mbox series

[0/2] advise about force-pushing as an alternative to reconciliation

Message ID 20230702200818.1038494-1-alexhenrie24@gmail.com (mailing list archive)
Headers show
Series advise about force-pushing as an alternative to reconciliation | expand

Message

Alex Henrie July 2, 2023, 8:08 p.m. UTC
Many times now, I have seen novices do the following:

1. Start work on their own personal topic branch
2. Push the branch to origin
3. Rebase the branch onto origin/master
4. Try to push again, but Git says they need to pull
5. Pull and make a mess trying to reconcile the older topic branch with
   the rebased topic branch

Help avoid this mistake by giving advice that mentions force-pushing,
rather than assuming that the user always wants to do reconciliation.

Alex Henrie (2):
  remote: advise about force-pushing as an alternative to reconciliation
  push: advise about force-pushing as an alternative to reconciliation

 builtin/push.c | 22 +++++++++++++---------
 remote.c       |  3 ++-
 2 files changed, 15 insertions(+), 10 deletions(-)

Comments

Phillip Wood July 3, 2023, 3:33 p.m. UTC | #1
Hi Alex

On 02/07/2023 21:08, Alex Henrie wrote:
> Many times now, I have seen novices do the following:
> 
> 1. Start work on their own personal topic branch
> 2. Push the branch to origin
> 3. Rebase the branch onto origin/master
> 4. Try to push again, but Git says they need to pull
> 5. Pull and make a mess trying to reconcile the older topic branch with
>     the rebased topic branch
> 
> Help avoid this mistake by giving advice that mentions force-pushing,
> rather than assuming that the user always wants to do reconciliation.

I don't think we want to be advising users to force push. For the case 
you mention above I think it would be much safer to advise them to use

	git push --force-if-includes

In the absence of background fetches even

	git push --force-with-lease

is still safer than

	git push --force

Best Wishes

Phillip

> Alex Henrie (2):
>    remote: advise about force-pushing as an alternative to reconciliation
>    push: advise about force-pushing as an alternative to reconciliation
> 
>   builtin/push.c | 22 +++++++++++++---------
>   remote.c       |  3 ++-
>   2 files changed, 15 insertions(+), 10 deletions(-)
>
Alex Henrie July 3, 2023, 4:26 p.m. UTC | #2
On Mon, Jul 3, 2023 at 9:33 AM Phillip Wood <phillip.wood123@gmail.com> wrote:

> On 02/07/2023 21:08, Alex Henrie wrote:
> > Many times now, I have seen novices do the following:
> >
> > 1. Start work on their own personal topic branch
> > 2. Push the branch to origin
> > 3. Rebase the branch onto origin/master
> > 4. Try to push again, but Git says they need to pull
> > 5. Pull and make a mess trying to reconcile the older topic branch with
> >     the rebased topic branch
> >
> > Help avoid this mistake by giving advice that mentions force-pushing,
> > rather than assuming that the user always wants to do reconciliation.
>
> I don't think we want to be advising users to force push. For the case
> you mention above I think it would be much safer to advise them to use
>
>         git push --force-if-includes
>
> In the absence of background fetches even
>
>         git push --force-with-lease
>
> is still safer than
>
>         git push --force

Hi Phillip, thanks for the feedback. --force-with-lease would be fine.
I'll make that change in v2.

Regarding your other suggestion, --force-if-includes doesn't do
anything unless --force-with-lease is also specified, and I think
recommending that users always type --force-with-lease
--force-if-includes is a bit much to ask of them. It also could lead
to confusion if the user has decided to delete the local branch and
start over, and is now trying to push the new local branch over the
old one on the remote.

-Alex
Junio C Hamano July 4, 2023, 9:44 p.m. UTC | #3
Phillip Wood <phillip.wood123@gmail.com> writes:

> Hi Alex
>
> On 02/07/2023 21:08, Alex Henrie wrote:
>> Many times now, I have seen novices do the following:
>> 1. Start work on their own personal topic branch
>> 2. Push the branch to origin

And did this succeed, or did this fail?  I'd assume that it failed,
because othrewise you would not be rebasing your work done in #1 on
top of what the central repository has.  Also ...

>> 3. Rebase the branch onto origin/master

... the user's better have done "git fetch" to update origin/master
before this step.  And that means this can just be done with "git
pull --rebase" (or you may already have configured pull to do so).

In any case, assuming that this was indeed the intention of the
user, i.e. the user never wanted to discard the changes made in the
central repository (presumably by others)...

>> 4. Try to push again, but Git says they need to pull

... if this happened, it is because somebody else pushed in the
meantime, right?  Then ...

>> 5. Pull and make a mess trying to reconcile the older topic branch with
>>     the rebased topic branch

... this means that somebody else's work was something that
overlapped with what you did in #1, and then you do want to clean up
the mess carefully, so that you do not lose the work by that
somebody else.  So ...

>> Help avoid this mistake by giving advice that mentions
>> force-pushing,

... why would it possibly be a good idea to suggest force pushing,
which discards other's work?  I do not quite understand.

> I don't think we want to be advising users to force push. For the case
> you mention above I think it would be much safer to advise them to use
>
> 	git push --force-if-includes
>
> In the absence of background fetches even
>
> 	git push --force-with-lease
>
> is still safer than
>
> 	git push --force

Absolutely.  git push --force-with-lease=$(git merge-base HEAD origin/master)
or something, perhaps, would be even better.

Thanks.
Alex Henrie July 4, 2023, 10:24 p.m. UTC | #4
On Tue, Jul 4, 2023 at 3:44 PM Junio C Hamano <gitster@pobox.com> wrote:

> > On 02/07/2023 21:08, Alex Henrie wrote:
> >> Many times now, I have seen novices do the following:
> >> 1. Start work on their own personal topic branch
> >> 2. Push the branch to origin
>
> And did this succeed, or did this fail?  I'd assume that it failed,
> because othrewise you would not be rebasing your work done in #1 on
> top of what the central repository has.  Also ...

It succeeded; the new branch was created on origin.

> >> 3. Rebase the branch onto origin/master
>
> ... the user's better have done "git fetch" to update origin/master
> before this step.  And that means this can just be done with "git
> pull --rebase" (or you may already have configured pull to do so).

Yes, the rebase was performed with `git pull -r origin master`. Other
work had been done on master while the topic branch was being worked
on.

> In any case, assuming that this was indeed the intention of the
> user, i.e. the user never wanted to discard the changes made in the
> central repository (presumably by others)...

The user did not want to discard anything from master, but they
absolutely did want to discard the obsolete version of their own
branch, which they made themself.

> >> 4. Try to push again, but Git says they need to pull
>
> ... if this happened, it is because somebody else pushed in the
> meantime, right?  Then ...

No one pushed between steps 3 and 4.

> >> 5. Pull and make a mess trying to reconcile the older topic branch with
> >>     the rebased topic branch
>
> ... this means that somebody else's work was something that
> overlapped with what you did in #1, and then you do want to clean up
> the mess carefully, so that you do not lose the work by that
> somebody else.  So ...

The conflicts came from trying to reconcile an older version of the
user's work with a rebased version of the user's work. The user
doesn't want to end up with a history that has two commits from the
same author with the same message.

> >> Help avoid this mistake by giving advice that mentions
> >> force-pushing,
>
> ... why would it possibly be a good idea to suggest force pushing,
> which discards other's work?  I do not quite understand.

The user was only trying to overwrite the old version of their own
branch, which no one cares about. This scenario comes up commonly when
using a single shared remote repository, or when using a forked remote
repository and running `git pull -r upstream master` to incorporate
changes from the upstream remote repository.

I hope that's more clear now. Please let me know if it's not.

-Alex
Junio C Hamano July 5, 2023, 5:30 a.m. UTC | #5
Alex Henrie <alexhenrie24@gmail.com> writes:

> I hope that's more clear now. Please let me know if it's not.

I think the description in the cover was prone to be misunderstood,
but I think I got it now.  Where you are pushing from your topic
branch is your "publishing" branch that only you would push into,
and the primary way you update it is by rebasing your local copy of
it on the updated 'master' branch to keep up with others' work
integrated into the shared 'master'.

In such a workflow, the way to update your "publishing" branch will
normally be to force push to overwrite.  And in this very narrow use
case, where nobody else is pushing into your "publishing" branch,
your remote-tracking branch would be always up-to-date with the
remote repository and use of --force-with-lease that does not say
which commit you expect there to be is safe.  In fact, you do not
even have to use --force-with-lease in such a use case, because its
additional safety (relative to --force) relies on the assumption
that you would be the only one who is pushing into the remote
repository to update that branch---and at that point, --force
without lease is just as good.

Thanks.
Alex Henrie July 6, 2023, 2:32 a.m. UTC | #6
On Tue, Jul 4, 2023 at 11:30 PM Junio C Hamano <gitster@pobox.com> wrote:

> I think the description in the cover was prone to be misunderstood,
> but I think I got it now.  Where you are pushing from your topic
> branch is your "publishing" branch that only you would push into,
> and the primary way you update it is by rebasing your local copy of
> it on the updated 'master' branch to keep up with others' work
> integrated into the shared 'master'.

Right. It's a narrow case, but it's quite common. For example, GitHub
and GitLab keep permanent references to every version of a branch that
was pushed while a pull request was open for that branch. On those
platforms, force-pushing is analogous to emailing a new version of a
patchset.

> In such a workflow, the way to update your "publishing" branch will
> normally be to force push to overwrite.  And in this very narrow use
> case, where nobody else is pushing into your "publishing" branch,
> your remote-tracking branch would be always up-to-date with the
> remote repository and use of --force-with-lease that does not say
> which commit you expect there to be is safe.  In fact, you do not
> even have to use --force-with-lease in such a use case, because its
> additional safety (relative to --force) relies on the assumption
> that you would be the only one who is pushing into the remote
> repository to update that branch---and at that point, --force
> without lease is just as good.

OK, I'll switch back to --force in v3. Thanks for the feedback!

-Alex