Today I learned that git push will silently try to recreate a remote
funny ref if you push to it.

"Hypothetically" ... lets say I have a reimplementation of Git called JGit.
Lets say its on a server somewhere on the network.
Lets say its a bit more liberal in what it accepts...

$ git push origin HEAD^:refs/wtf
Counting objects: 3, done.
Writing objects: 100% (3/3), 206 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ...blahblah.../wtf
 * [new branch]      HEAD^ -> refs/wtf

Okaaaay. We are the proud new owners of

$ git ls-remote origin
4da022e5c7e2c33025374ddd1c3aeeb082d7b394        refs/wtf

Yea. Great.

Here is the WTF. git push will silently send a creation command
instead of an update.

$ GIT_TRACE_PACKET=1 git push origin HEAD:refs/wtf
22:48:09.277446 pkt-line.c:46           packet:         push<
4da022e5c7e2c33025374ddd1c3aeeb082d7b394 refs/wtf\0 side-band-64k
delete-refs report-status quiet ofs-delta agent=JGit/4-...
22:48:09.277522 pkt-line.c:46           packet:         push< 0000
22:48:09.277595 pkt-line.c:46           packet:         push>
0000000000000000000000000000000000000000
f721fb36771dc587d45e8a95ef9f7edcc3849236 refs/wtf\0 report-status
side-band-64k agent=git/2.4.3.573.g4eafbef
22:48:09.277605 pkt-line.c:46           packet:         push> 0000
Counting objects: 6, done.
Delta compression using up to 12 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 409 bytes | 0 bytes/s, done.
Total 6 (delta 0), reused 0 (delta 0)
22:48:09.419038 pkt-line.c:46           packet:         push<
\1000eunpack ok001fng refs/wtf already exists0000
22:48:09.419066 pkt-line.c:46           packet:         push< 0000
22:48:09.419073 pkt-line.c:46           packet:         push< unpack ok
22:48:09.419082 pkt-line.c:46           packet:         push< ng
refs/wtf already exists
22:48:09.419092 pkt-line.c:46           packet:         push< 0000
To rpc://user/sop/wtf
 ! [remote rejected] HEAD -> refs/wtf (already exists)
error: failed to push some refs to '...blahblah.../wtf'


I think the cause is get_remote_heads() gets passed REF_NORMAL during
send-pack, which filters out that refs/wtf advertisement from the
server. Once its filtered out send-pack thinks the ref is new and
happily sends along the command to create it.

In git-core this rejection of the funny ref is done at the server.
This JGit server was fine with the funny ref. It didn't care earlier
when git push created it.

Now git push isn't so happy with that funny ref on the RHS, because it
always forgets it in the advertisement. This makes it hard to update
the ref. Or delete it remotely.

If we don't want that ref in the advertisement, push should refuse it
in the RHS.
If we want to let the remote decide, send-pack should honor the advertisement.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to