Git push fails for tag names containing + with InvalidObjectIdException in pre-receive callback #3055
Service Desk opened 16 hours ago

Follow-up from issue #3054, reported by @sen23.

Adding @sen23, @robin, and @servicedesk to the watch list.

Summary

Pushing a Git tag or ref whose name contains + is rejected by the server-side pre-receive hook (HTTP 500 / pre-receive hook declined).

Example tag: 1.0.10+16

+ is a valid Git ref character. Branch pushes without + work.

Environment

  • Reported on OneDev 15.0.8
  • Still present on current main (16.5.6)

Actual result

Client:

remote: curl: (22) The requested URL returned error: 500
! [remote rejected] 1.0.10+16 -> 1.0.10+16 (pre-receive hook declined)
error: failed to push some refs

Server:

org.eclipse.jgit.errors.InvalidObjectIdException: Invalid id: refs/tags/1.0.10
    at org.eclipse.jgit.lib.ObjectId.fromString(...)
    at io.onedev.server.git.hook.GitPreReceiveCallback.doPost(...)

The pushed ref is refs/tags/1.0.10+16, but parsing sees refs/tags/1.0.10.

Expected result

refs/tags/1.0.10+16 is accepted and the tag is created on the remote.

Root cause

git-receive-hook forwards hook stdin with curl -d @- (form body, not --data-urlencode). Servlet form decoding turns + into a space, so:

<old-oid> <new-oid> refs/tags/1.0.10+16

arrives as:

<old-oid> <new-oid> refs/tags/1.0.10 16

GitPreReceiveCallback then splits on spaces and passes refs/tags/1.0.10 to ObjectId.fromString(...).

The same encoding applies to branch names containing +.

Reproduce

git tag 1.0.10+16
git push origin 1.0.10+16
1/1
Type
Bug
Priority
Normal
Assignee
Affected Versions
<=16.5.6
Labels
No labels
Issue Votes (0)
Watchers (3)
Reference
OD-3055
Please wait...
Connection lost or session expired, reload to recover
Page is in error, reload to recover