Page MenuHomePhabricator

Can't delete weird ref using git in Gerrit
Closed, ResolvedPublic

Description

There's a weird ref for the AutoCreateCategoryPages extension https://gerrit.wikimedia.org/g/mediawiki/extensions/AutoCreateCategoryPages/+/refs/master that's almost certainly a mistake

Pushing with --delete or pushing an empty ref with --force both fail:

problem
badgit (main #)
(•́‸•̀)❥ git push origin --delete refs/master
2021-02-26 17:29:58,763 sshecret SSH_AUTH_SOCK=/run/user/1000/194f906110c5681bc2ac8c5c340ca5dd.sock
Host key fingerprint is SHA256:j7HQoQ6fIuEgDHjONjI2CZ+2Iwxqgo2Ur5LbPqBgxOU
+---[RSA 1024]----+
|                 |
|.  .             |
|= +     .        |
|+BoE   o .       |
|BBX . o S        |
|@@o+ + o =       |
|X=*.. + o .      |
|*ooo .           |
|o+o.             |
+----[SHA256]-----+
remote: Processing changes: done
remote: error: internal error
To ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/AutoCreateCategoryPages
 ! [remote rejected] refs/master (internal error)
error: failed to push some refs to 'ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/AutoCreateCategoryPages'

Stack trace complains about noops:

stacktrace
[2021-02-27T00:34:47.343+0000] [SSH git-receive-pack /mediawiki/extensions/AutoCreateCategoryPages (thcipriani)] WARN  com.google.gerrit.server.git.MultiProgressMonitor : MultiProgressMonitor worker did not call end() before returning
[2021-02-27T00:34:47.344+0000] [SSH git-receive-pack /mediawiki/extensions/AutoCreateCategoryPages (thcipriani)] ERROR com.google.gerrit.server.git.receive.AsyncReceiveCommits : error while processing push
java.util.concurrent.ExecutionException: com.google.gerrit.exceptions.StorageException: com.google.gerrit.server.update.UpdateException: java.lang.IllegalArgumentException: ref update is a no-op: DELETE: 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 refs/master
        at java.util.concurrent.FutureTask.report(FutureTask.java:122)
        at java.util.concurrent.FutureTask.get(FutureTask.java:192)
        at com.google.gerrit.server.git.receive.AsyncReceiveCommits.preReceive(AsyncReceiveCommits.java:387)
        at com.google.gerrit.server.git.receive.AsyncReceiveCommits.lambda$asHook$1(AsyncReceiveCommits.java:332)
        at org.eclipse.jgit.transport.ReceivePack.service(ReceivePack.java:2206)
        at org.eclipse.jgit.transport.ReceivePack.receive(ReceivePack.java:2120)
        at com.google.gerrit.sshd.commands.Receive.runImpl(Receive.java:98)
        at com.google.gerrit.sshd.AbstractGitCommand.service(AbstractGitCommand.java:108)
        at com.google.gerrit.sshd.AbstractGitCommand.access$000(AbstractGitCommand.java:32)
        at com.google.gerrit.sshd.AbstractGitCommand$1.run(AbstractGitCommand.java:73)
        at com.google.gerrit.sshd.BaseCommand$TaskThunk.run(BaseCommand.java:488)
        at com.google.gerrit.server.logging.LoggingContextAwareRunnable.run(LoggingContextAwareRunnable.java:110)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
        at com.google.gerrit.server.git.WorkQueue$Task.run(WorkQueue.java:610)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: com.google.gerrit.exceptions.StorageException: com.google.gerrit.server.update.UpdateException: java.lang.IllegalArgumentException: ref update is a no-op: DELETE: 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 refs/master
        at com.google.gerrit.server.git.receive.ReceiveCommits.handleRegularCommands(ReceiveCommits.java:734)
        at com.google.gerrit.server.git.receive.ReceiveCommits.processCommandsUnsafe(ReceiveCommits.java:647)
        at com.google.gerrit.server.git.receive.ReceiveCommits.processCommands(ReceiveCommits.java:598)
        at com.google.gerrit.server.git.receive.AsyncReceiveCommits.lambda$preReceive$3(AsyncReceiveCommits.java:370)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at com.google.gerrit.server.util.RequestScopePropagator.lambda$cleanup$1(RequestScopePropagator.java:182)
        at com.google.gerrit.server.util.RequestScopePropagator.lambda$context$0(RequestScopePropagator.java:170)
        at com.google.gerrit.server.util.ThreadLocalRequestScopePropagator.lambda$wrapImpl$0(ThreadLocalRequestScopePropagator.java:45)
        at com.google.gerrit.server.util.RequestScopePropagator$1.call(RequestScopePropagator.java:85)
        at com.google.gerrit.server.util.RequestScopePropagator$2.run(RequestScopePropagator.java:116)
        ... 9 more
Caused by: com.google.gerrit.server.update.UpdateException: java.lang.IllegalArgumentException: ref update is a no-op: DELETE: 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 refs/master
        at com.google.gerrit.server.update.BatchUpdate.executeUpdateRepo(BatchUpdate.java:515)
        at com.google.gerrit.server.update.BatchUpdate.execute(BatchUpdate.java:138)
        at com.google.gerrit.server.update.BatchUpdate.execute(BatchUpdate.java:386)
        at com.google.gerrit.server.update.BatchUpdate.execute(BatchUpdate.java:390)
        at com.google.gerrit.server.git.receive.ReceiveCommits.handleRegularCommands(ReceiveCommits.java:732)
        ... 19 more
Caused by: java.lang.IllegalArgumentException: ref update is a no-op: DELETE: 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 refs/master
        at com.google.common.base.Preconditions.checkArgument(Preconditions.java:217)
        at com.google.gerrit.server.update.ChainedReceiveCommands.add(ChainedReceiveCommands.java:66)
        at com.google.gerrit.server.update.BatchUpdate$RepoContextImpl.addRefUpdate(BatchUpdate.java:257)
        at com.google.gerrit.server.git.receive.ReceiveCommits$UpdateOneRefOp.updateRepo(ReceiveCommits.java:3071)
        at com.google.gerrit.server.update.BatchUpdate.executeUpdateRepo(BatchUpdate.java:502)
        ... 23 more

The message seems to be saying: this ref doesn't exist, but that's not the case on disk:

gerrit2@gerrit1001:/srv/gerrit/git/mediawiki/extensions/AutoCreateCategoryPages.git$ git for-each-ref | grep refs/master
2a5f5e7ce5292d9d6d033311a025a8be3f52b069 commit refs/master

I can delete the ref on disk, but probably worth filing an upstream task for this, too (this is a note for myself to do this after this weekend)

Details

Event Timeline

$ GIT_TRACE_PACKET=1 GIT_TRACE=1 git push origin :refs/master
10:56:41.242428 git.c:444               trace: built-in: git push origin :refs/master
10:56:41.243020 run-command.c:663       trace: run_command: unset GIT_DIR GIT_PREFIX; ssh -p 29418 hashar@gerrit.wikimedia.org 'git-receive-pack '\''/mediawiki/extensions/AutoCreateCategoryPages.git'\'''
10:56:44.019233 pkt-line.c:80           packet:         push< 7ae6dd31e1fdb993f9eebdcb8d8626f7f60e4d79 refs/heads/REL1_21\0 side-band-64k delete-refs report-status quiet ofs-delta push-options agent=JGit/unknown
....
10:56:44.021113 pkt-line.c:80           packet:         push< e4ab701feb4d0cb24e3eb905caa3dbfb0b23816e .have
10:56:44.021133 pkt-line.c:80           packet:         push< 0000
10:56:44.021347 pkt-line.c:80           packet:         push> 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 refs/master\0 report-status side-band-64k agent=git/2.29.2
10:56:44.021382 pkt-line.c:80           packet:         push> 0000

That is with git 2.29.2 (from Debian). Same issue with protocol.version 1 or 2.

The details about the protocol are in git://git.kernel.org/pub/scm/git/git.git Documentation/technical/pack-protocol.txt:

Reference Update Request and Packfile Transfer
----------------------------------------------
...
  command           =  create / delete / update
  create            =  zero-id SP new-id  SP name
  delete            =  old-id  SP zero-id SP name
  update            =  old-id  SP new-id  SP name

0000000000000000000000000000000000000000 is zero-id and is a special sha1 used there to differentiate between reference creation, deletion or update. Gerrit picked it up as a delete command because of jgit:

/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java
  public ReceiveCommand(final ObjectId oldId, final ObjectId newId, final String name) {
...

    type = Type.UPDATE;
    if (ObjectId.zeroId().equals(oldId)) {
      type = Type.CREATE;
    }
    if (ObjectId.zeroId().equals(newId)) {
      type = Type.DELETE;
    }

Essentially if a packet is send with the second arg being zero-id, jgit always consider it a delete and that requires the first parameter to be a sha1 not a zero-id. That is thanksfully caught later.

The issue lies in cgit, it would tries to resolve the refname refs/master using prefixes such as refs/, refs/tags/, refs/remotes/ but ends up with a zero-id somehow. What at least that is what I am imagining ;)

Short of heading into cgit advanced documentation and code to find out why it resolves refs/master to a zero-id or how one can specify the reference to delete properly (ie without magic resolving), I am entitled to ignore that issue and delete the reference directly from disk.

^^ That was my Saturday breakfast :-]

I am entitled to ignore that issue and delete the reference directly from disk.

This sounds reasonable to me.

We should also adjust the ACL to make sure it's not possible for someone to accidentally push to this poorly named ref again.

With plain cgit, here is a script that prepares an upstream repository and a work one. Creates a refs/master reference in upstream then attempt to delete it from the work repository:

#!/bin/bash

set -eu

echo "Creating upstream and work repos"
for repo in upstream work; do
    rm -fr $repo
    mkdir -p $repo
    git -C $repo init -q
    git -C $repo commit --allow-empty -m "First commit for $repo"
done

git -C upstream update-ref refs/master HEAD

git -C work remote add origin ../upstream
git -C work remote update
git -C work ls-remote origin

echo "Pushing delete of \`refs/master\` from work to upstream"
GIT_TRACE_PACKET=1 GIT_TRACE=1 \
    git -C work push origin :refs/master 2>&1 |grep push|grep -v '0000$'

Output:

Creating upstream and work repos
[master (root-commit) dca180f] First commit for upstream
[master (root-commit) 82d312a] First commit for work
Fetching origin
remote: Enumerating objects: 2, done.
remote: Counting objects: 100% (2/2), done.
remote: Total 2 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (2/2), 152 bytes | 152.00 KiB/s, done.
From ../upstream
 * [new branch]      master     -> origin/master
dca180f7bddb524c652425b46988a0022e116f48	HEAD
dca180f7bddb524c652425b46988a0022e116f48	refs/heads/master
dca180f7bddb524c652425b46988a0022e116f48	refs/master

So we get commits dca180f in the upstream repo.

Pushing delete of `refs/master` from work to upstream
17:22:25.546512 git.c:444               trace: built-in: git push origin :refs/master
17:22:25.547170 run-command.c:663       trace: run_command: unset GIT_PREFIX; 'git-receive-pack '\''../upstream'\'''
17:22:25.550513 git.c:444               trace: built-in: git receive-pack ../upstream
17:22:25.551110 pkt-line.c:80           packet: receive-pack> dca180f7bddb524c652425b46988a0022e116f48 refs/heads/master\0report-status report-status-v2 delete-refs side-band-64k quiet atomic ofs-delta object-format=sha1 agent=git/2.29.2
17:22:25.551152 pkt-line.c:80           packet: receive-pack> dca180f7bddb524c652425b46988a0022e116f48 refs/master
17:22:25.551180 pkt-line.c:80           packet: receive-pack> 0000
17:22:25.551229 pkt-line.c:80           packet:         push< dca180f7bddb524c652425b46988a0022e116f48 refs/heads/master\0report-status report-status-v2 delete-refs side-band-64k quiet atomic ofs-delta object-format=sha1 agent=git/2.29.2
17:22:25.551265 pkt-line.c:80           packet:         push< dca180f7bddb524c652425b46988a0022e116f48 refs/master
17:22:25.551275 pkt-line.c:80           packet:         push< 0000

Somehow the upstream repo receives dca180f from the work repo?

The pushes resolves to zero-id zero-id:

17:22:25.551357 pkt-line.c:80           packet:         push> 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 refs/master\0 report-status-v2 side-band-64k object-format=sha1 agent=git/2.29.2
17:22:25.551381 pkt-line.c:80           packet:         push> 0000
17:22:25.551438 pkt-line.c:80           packet: receive-pack< 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 refs/master\0 report-status-v2 side-band-64k object-format=sha1 agent=git/2.29.2
17:22:25.551486 pkt-line.c:80           packet: receive-pack< 0000
17:22:25.551942 pkt-line.c:80           packet: receive-pack> unpack ok
17:22:25.551959 pkt-line.c:80           packet: receive-pack> ng refs/master funny refname
17:22:25.551972 pkt-line.c:80           packet: receive-pack> 0000
17:22:25.552020 run-command.c:663       trace: run_command: git gc --auto --quiet
17:22:25.552073 pkt-line.c:80           packet:     sideband< \2error: refusing to create funny ref 'refs/master' remotely
remote: error: refusing to create funny ref 'refs/master' remotely
17:22:25.552135 pkt-line.c:80           packet:     sideband< \1000eunpack ok0021ng refs/master funny refname0000
17:22:25.552218 pkt-line.c:80           packet:         push< unpack ok
17:22:25.552244 pkt-line.c:80           packet:         push< ng refs/master funny refname
17:22:25.552255 pkt-line.c:80           packet:         push< 0000
17:22:25.554698 pkt-line.c:80           packet:     sideband< \217:22:25.554489 git.c:444               trace: built-in: git gc --auto --quiet
remote: 17:22:25.554489 git.c:444               trace: built-in: git gc --auto --quiet
17:22:25.555134 pkt-line.c:80           packet: receive-pack> 0000
17:22:25.555236 pkt-line.c:80           packet:     sideband< 0000
To ../upstream
 ! [remote rejected] refs/master (funny refname)
error: failed to push some refs to '../upstream'

And that fails with:

error: refusing to create funny ref 'refs/master' remotely

 ! [remote rejected] refs/master (funny refname)

The related code in cgit:

builtin/receive-pack.c
static const char *update(struct command *cmd, struct shallow_info *si)
{
...
        /* only refs/... are allowed */
        if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) {
                rp_error("refusing to create funny ref '%s' remotely", name);
                return "funny refname";
        }

refs/master would match starts_with(name, "refs/") so it then evaluates check_refname_format(name + 5, 0) which leads to:

refs.c
static int check_or_sanitize_refname(const char *refname, int flags,
                                     struct strbuf *sanitized)
{
...
        if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
                return -1; /* Refname has only one component. */
        return 0;

And:

refs.h
#define REFNAME_ALLOW_ONELEVEL 1
#define REFNAME_REFSPEC_PATTERN 2

/*
 * Return 0 iff refname has the correct format for a refname according
 * to the rules described in Documentation/git-check-ref-format.txt.
 * If REFNAME_ALLOW_ONELEVEL is set in flags, then accept one-level
 * reference names.  If REFNAME_REFSPEC_PATTERN is set in flags, then
 * allow a single "*" wildcard character in the refspec. No leading or
 * repeated slashes are accepted.
 */
int check_refname_format(const char *refname, int flags);

So I guess some code path set that REFNAME_ALLOW_ONELEVEL flag and lets the reference be created, but later it is not possible to delete it cause it is considered invalid. Sounds like bug for cgit and jgit maybe.

hashar triaged this task as Low priority.Mar 2 2021, 4:34 PM

Noting here that I deleted this ref -- hopefully this unblocks folks:

gerrit2@gerrit1001:/srv/gerrit/git/mediawiki/extensions/AutoCreateCategoryPages.git$ git for-each-ref | grep master
28db01ebf85c5f94aad8bdb2aa66c8cad2461745 commit refs/heads/master
2a5f5e7ce5292d9d6d033311a025a8be3f52b069 commit refs/master
gerrit2@gerrit1001:/srv/gerrit/git/mediawiki/extensions/AutoCreateCategoryPages.git$ git update-ref -d refs/master
gerrit2@gerrit1001:/srv/gerrit/git/mediawiki/extensions/AutoCreateCategoryPages.git$ git for-each-ref | grep master
28db01ebf85c5f94aad8bdb2aa66c8cad2461745 commit refs/heads/master

Removing myself as assignee.

Based on this task I *think* this might be a problem for jgit. Since cgit's receive-pack protects against one component refs but jgit (it seems) doesn't.

Noting here that I deleted this ref -- hopefully this unblocks folks:

Looks like it is, thanks!

hashar claimed this task.

Solved by deleting the refs/master reference. There is some oddity causes jgit does accept such a reference to be pushed while cgit is later unable to resolve it. Surely that could be pushed to each upstream for a proper fix, which would require a good day of investigation to craft useful report + all the time to follow up for upstream. I am willing to entirely ignore the issue since well .. It is broken in the first place, for 99,999999% purposes refs are created under refs/heads/ or refs/tags, others are really edge cases.

Legoktm added a subscriber: Umherirrender.

@hashar, @thcipriani can the ref be deleted from gerrit-replica as well?

km@cashew ~/tmp> git clone https://gerrit-replica.wikimedia.org/r/mediawiki/extensions/AutoCreateCategoryPages replica
Cloning into 'replica'...
remote: Total 996 (delta 0), reused 996 (delta 0)
Receiving objects: 100% (996/996), 209.04 KiB | 972.00 KiB/s, done.
Resolving deltas: 100% (650/650), done.
km@cashew ~/tmp> cd replica/
km@cashew ~/t/replica> git ls-remote | grep master
From https://gerrit-replica.wikimedia.org/r/mediawiki/extensions/AutoCreateCategoryPages
944be12a5e9d27482478d11af51be71684b1a927	refs/heads/master
2a5f5e7ce5292d9d6d033311a025a8be3f52b069	refs/master

(noticed by @Umherirrender at T275292#6987695)

@hashar, @thcipriani can the ref be deleted from gerrit-replica as well?

km@cashew ~/tmp> git clone https://gerrit-replica.wikimedia.org/r/mediawiki/extensions/AutoCreateCategoryPages replica
Cloning into 'replica'...
remote: Total 996 (delta 0), reused 996 (delta 0)
Receiving objects: 100% (996/996), 209.04 KiB | 972.00 KiB/s, done.
Resolving deltas: 100% (650/650), done.
km@cashew ~/tmp> cd replica/
km@cashew ~/t/replica> git ls-remote | grep master
From https://gerrit-replica.wikimedia.org/r/mediawiki/extensions/AutoCreateCategoryPages
944be12a5e9d27482478d11af51be71684b1a927	refs/heads/master
2a5f5e7ce5292d9d6d033311a025a8be3f52b069	refs/master

(noticed by @Umherirrender at T275292#6987695)

The question is why replica isn't automatically replicated when something gets changed on "the main installation"?

We deleted the faulty refs/master directly on disk and that was not noticed by Gerrit. The fix is to request a full replication:

ssh -p 29418 gerrit.wikimedia.org replication start --now mediawiki/extensions/AutoCreateCategoryPages
[2021-04-14 13:52:32,451] Push to gerrit2@gerrit2001.wikimedia.org:/srv/gerrit/git/mediawiki/extensions/AutoCreateCategoryPages.git references: RemoteRefUpdate{refSpec=null:refs/master, status=NOT_ATTEMPTED, id=(null)..AnyObjectId[0000000000000000000000000000000000000000], force=yes, delete=yes, ffwd=no} [CONTEXT pushOneId="d13e2b31" ]
[2021-04-14 13:52:32,559] Failed replicate of refs/master to gerrit2@gerrit2001.wikimedia.org:/srv/gerrit/git/mediawiki/extensions/AutoCreateCategoryPages.git, reason: funny refname [CONTEXT pushOneId="d13e2b31" ]

Which is rejected by the replica for the same reason it was rejected by Gerrit / jgit and thus it is still there:

git ls-remote https://gerrit-replica.wikimedia.org/r/mediawiki/extensions/AutoCreateCategoryPages refs/master
2a5f5e7ce5292d9d6d033311a025a8be3f52b069	refs/master

I went to delete it manually on the replica:

gerrit2001
sudo -u gerrit2 git -C /srv/gerrit/git/mediawiki/extensions/AutoCreateCategoryPages.git update-ref -d refs/master

I then triggered a full replication of the repository and this time it worked:

[2021-04-14 14:00:36,646] scheduled mediawiki/extensions/AutoCreateCategoryPages:..all.. => [8e699818] push gerrit2@gerrit2001.wikimedia.org:/srv/gerrit/git/mediawiki/extensions/AutoCreateCategoryPages.git to run after 5s
[2021-04-14 14:00:36,647] Replication to gerrit2@gerrit2001.wikimedia.org:/srv/gerrit/git/mediawiki/extensions/AutoCreateCategoryPages.git started... [CONTEXT pushOneId="8e699818" ]
[2021-04-14 14:00:36,876] Replication to git@github.com:wikimedia/mediawiki-extensions-AutoCreateCategoryPages completed in 231ms, 1ms delay, 0 retries [CONTEXT pushOneId="0e7608f6" ]

And it is now gone:

$ git ls-remote https://gerrit-replica.wikimedia.org/r/mediawiki/extensions/AutoCreateCategoryPages refs/master
$

To the best I can tell, Gerrit JGit accepts receiving refs/master but the replication is done with cgit and it refuses refs having only one level. Follow up in T337508.

Mentioned in SAL (#wikimedia-releng) [2025-10-07T09:04:02Z] <hashar> gerrit: deleted invalid ref refs/master (funny refname) from mediawiki/services/ores/deploy | T275946

Mentioned in SAL (#wikimedia-releng) [2025-10-07T09:19:08Z] <hashar> gerrit: deleted invalid refs refs/for2.4.4 and refs/for3.0-beta-9 (funny refname) from mediawiki/skins/Metrolook | T275946

Mentioned in SAL (#wikimedia-releng) [2025-10-07T09:47:03Z] <hashar> gerrit: deleted invalid ref refs/master cb852fd9c6522d94127177a88f59da52bc2b93eb (funny refname) from wikidata/browsertests | T275946

Mentioned in SAL (#wikimedia-releng) [2025-10-07T09:55:21Z] <hashar> gerrit: deleted invalid ref refs/master (funny refname) from operations/debs/kubeyaml | T275946

Mentioned in SAL (#wikimedia-releng) [2025-10-07T09:56:26Z] <hashar> gerrit: deleted invalid ref refs/master (funny refname) from labs/private | T275946

Change #1194149 had a related patch set uploaded (by Hashar; author: Hashar):

[All-Users@refs/meta/config] Prevent pushing to funny refname refs/master

https://gerrit.wikimedia.org/r/1194149

Change #1194149 merged by Hashar:

[All-Users@refs/meta/config] Prevent pushing to funny refname refs/master

https://gerrit.wikimedia.org/r/1194149

Change #1201603 had a related patch set uploaded (by Hashar; author: Hashar):

[All-Projects@refs/meta/config] Prevent pushing to funny refname refs/master

https://gerrit.wikimedia.org/r/1201603

Change #1201603 merged by Hashar:

[All-Projects@refs/meta/config] Prevent pushing to funny refname refs/master

https://gerrit.wikimedia.org/r/1201603

Mentioned in SAL (#wikimedia-releng) [2025-11-04T13:18:56Z] <hashar> gerrit: blocked pushes to refs/[^/]+ , first level references are considered invalid by cgit (funny refname) # T275946 T337508