#877464 git-remote-gcrypt: git push always behaves as if --force is given

#877464#5
Date:
2017-10-02 01:58:30 UTC
From:
To:
Here's a secnario -

I have repo A and repo B.  Both have the same git-remote-gcrypt
repository named origin, and both begin with the same HEAD.

Now, make a commit on repo A and push it.  Make a different commit
on repo B and run git push.

The expected result here is an error, and the usual way to handle
it would be to do a git pull followed by another push attempt.

Unfortunately, with git-remote-gcrypt, the push from repo B
silently clobbers the most recent commit made on repo A.  A
subsequent pull from repo B will not pull down the changes
from repo A.

All is not *completely* lost; on repo A, a subsequent pull will
offer to merge the changes from repo B.

This is rather unfortunate for both collaboration with a workgroup
or even sharing files between multiple devices of one's own.

#877464#10
Date:
2017-10-02 16:47:10 UTC
From:
To:
Dear John,

Could you say which backend you were using when you saw this, please?
Possibly it affects all backends, but which were you able to test?

Thanks.

#877464#15
Date:
2017-10-02 18:31:50 UTC
From:
To:
Hi Sean,

I tested it with both the rsync and the git:// backends and observed the
same behavior with both.

- John

#877464#20
Date:
2017-10-22 19:23:24 UTC
From:
To:
control: outlook -1 git-remote-gcrypt needs a test suite before this kind of bug can be fixed

Hello John,

Thank you again for testing.

Fixing this bug is going to require substantial refactoring.  I am
loathe to do that until git-remote-gcrypt has a test suite, so that I
can be sure existing functionality does not break.

I hope to be able to sit down and write such a test suite at some point
during the next year.

#877464#27
Date:
2020-04-03 17:41:34 UTC
From:
To:
Hi,

A solution could be the use of --force-with-lease instead of --force. It
would prevent the behavior observed by the OP.

BR
--- montag451
#877464#32
Date:
2024-04-26 19:52:12 UTC
From:
To:
I was implementing another gitremote-helper today and ran into what I
think is the same problem. Since I've worked around the problem in my
gitremote-helper successfully, I wanted to share what I've learned in
case it can help git-remote-gcrypt.

When git push is run, for a non-forced push, it asks the
gitremote-helper program for "list for-push". It then sends a "push" to
it. And only after that does it go compare the list of refs it got with
the list of refs it has asked to be pushed, and notice if the push would
overwrite a ref. At that point, git pull will complain that refs were
not able to be pushed. But actually nothing stopped the gitremote-helper
from doing a push that overwrote a ref, effectively a force push.

I think this is a bug in git. I can't imagine why it behaves this way.
It requires that every gitremote-helper program effectively replicate
git's own detection of a disallowed push, in order to reject the
"push" with "error $ref"

It is certainly possible for a gitremote-helper program to do that
though. What I did is, when git runs "list for-push", I remember the
refs that are on the remote. Then when git runs "push $src:$dst",
(but not when it's a "+$src" forced push), I compare the sha of $src
with the old ref I saw on the remote. If the shas are different, I
check `git log --oneline $old..$src` -- if this outputs nothing, then
history is not advancing and it refuses to push that ref, and
reports the error to git.

#877464#37
Date:
2024-04-27 09:10:09 UTC
From:
To:
Hello,

Many thanks for this.  Hopefully someone will be interested in
implementing it at some point.

#877464#42
Date:
2024-05-09 17:41:45 UTC
From:
To:
Joey Hess wrote:

That's not quite right, because git log outputs commits when the two
refs are diverged but share a common ancestor.

I think the best way to detect it is
git merge-base --ancestor $old $src
which will exit nonzero on a non-fast-forward.