{"thread":{"id":"39792","subject":"send-pack silently tries to recreate funny remote refs","startedAt":"2015-07-07T05:56:57Z","lastAt":"2015-07-07T05:56:57Z","messageCount":1,"participants":["Shawn Pearce"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"265644","messageId":"CAJo=hJuWAh8ctKp=BOR_0cMg3Y=rk6Lq++qXQpj+2jsZkfSUhg@mail.gmail.com","threadId":"39792","inReplyTo":null,"subject":"send-pack silently tries to recreate funny remote refs","fromName":"Shawn Pearce","fromEmail":"spearce@spearce.org","sentAt":"2015-07-07T05:56:57Z","receivedAt":"2015-07-07T05:56:57Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Today I learned that git push will silently try to recreate a remote\nfunny ref if you push to it.\n\n\"Hypothetically\" ... lets say I have a reimplementation of Git called JGit.\nLets say its on a server somewhere on the network.\nLets say its a bit more liberal in what it accepts...\n\n$ git push origin HEAD^:refs/wtf\nCounting objects: 3, done.\nWriting objects: 100% (3/3), 206 bytes | 0 bytes/s, done.\nTotal 3 (delta 0), reused 0 (delta 0)\nTo ...blahblah.../wtf\n * [new branch]      HEAD^ -> refs/wtf\n\nOkaaaay. We are the proud new owners of\n\n$ git ls-remote origin\n4da022e5c7e2c33025374ddd1c3aeeb082d7b394        refs/wtf\n\nYea. Great.\n\nHere is the WTF. git push will silently send a creation command\ninstead of an update.\n\n$ GIT_TRACE_PACKET=1 git push origin HEAD:refs/wtf\n22:48:09.277446 pkt-line.c:46           packet:         push<\n4da022e5c7e2c33025374ddd1c3aeeb082d7b394 refs/wtf\\0 side-band-64k\ndelete-refs report-status quiet ofs-delta agent=JGit/4-...\n22:48:09.277522 pkt-line.c:46           packet:         push< 0000\n22:48:09.277595 pkt-line.c:46           packet:         push>\n0000000000000000000000000000000000000000\nf721fb36771dc587d45e8a95ef9f7edcc3849236 refs/wtf\\0 report-status\nside-band-64k agent=git/2.4.3.573.g4eafbef\n22:48:09.277605 pkt-line.c:46           packet:         push> 0000\nCounting objects: 6, done.\nDelta compression using up to 12 threads.\nCompressing objects: 100% (2/2), done.\nWriting objects: 100% (6/6), 409 bytes | 0 bytes/s, done.\nTotal 6 (delta 0), reused 0 (delta 0)\n22:48:09.419038 pkt-line.c:46           packet:         push<\n\\1000eunpack ok001fng refs/wtf already exists0000\n22:48:09.419066 pkt-line.c:46           packet:         push< 0000\n22:48:09.419073 pkt-line.c:46           packet:         push< unpack ok\n22:48:09.419082 pkt-line.c:46           packet:         push< ng\nrefs/wtf already exists\n22:48:09.419092 pkt-line.c:46           packet:         push< 0000\nTo rpc://user/sop/wtf\n ! [remote rejected] HEAD -> refs/wtf (already exists)\nerror: failed to push some refs to '...blahblah.../wtf'\n\n\nI think the cause is get_remote_heads() gets passed REF_NORMAL during\nsend-pack, which filters out that refs/wtf advertisement from the\nserver. Once its filtered out send-pack thinks the ref is new and\nhappily sends along the command to create it.\n\nIn git-core this rejection of the funny ref is done at the server.\nThis JGit server was fine with the funny ref. It didn't care earlier\nwhen git push created it.\n\nNow git push isn't so happy with that funny ref on the RHS, because it\nalways forgets it in the advertisement. This makes it hard to update\nthe ref. Or delete it remotely.\n\nIf we don't want that ref in the advertisement, push should refuse it\nin the RHS.\nIf we want to let the remote decide, send-pack should honor the advertisement.\n"}]}