- Package:
- git-remote-gcrypt
- Source:
- git-remote-gcrypt
- Submitter:
- John Goerzen
- Date:
- 2024-05-09 17:45:03 UTC
- Severity:
- important
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.
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.
Hi Sean, I tested it with both the rsync and the git:// backends and observed the same behavior with both. - John
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.
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
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.
Hello, Many thanks for this. Hopefully someone will be interested in implementing it at some point.
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.