Git development
 help / color / mirror / Atom feed
* `git push --porcelain` has no effect when deleting a ref which does not exist
@ 2026-08-05  7:19 Xavier Morel
  2026-08-05 16:30 ` Junio C Hamano
  0 siblings, 1 reply; 3+ messages in thread
From: Xavier Morel @ 2026-08-05  7:19 UTC (permalink / raw)
  To: git

Using `push --delete --porcelain` with refs which are extant correctly 
outputs the relevant information in the documented format:

-	:refs/heads/<branch1>	[deleted]
-	:refs/heads/<branch2>	[deleted]

However doing the same with refs which don't exist on the remote (e.g. 
because of a concurrent deletion) has the error written out in 
human-targeted text:

error: unable to delete '<branch1>': remote ref does not exist
error: unable to delete '<branch2>': remote ref does not exist

I would have expected something along the lines of:

!	:refs/heads/<branch>	[remote failure]

which would be machine-readable as documented for the `--porcelain` 
flag. Was that intended or is it just something that fell through the 
cracks of code convolution?

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: `git push --porcelain` has no effect when deleting a ref which does not exist
  2026-08-05  7:19 `git push --porcelain` has no effect when deleting a ref which does not exist Xavier Morel
@ 2026-08-05 16:30 ` Junio C Hamano
  2026-08-07  6:51   ` Xavier Morel
  0 siblings, 1 reply; 3+ messages in thread
From: Junio C Hamano @ 2026-08-05 16:30 UTC (permalink / raw)
  To: Xavier Morel; +Cc: git

Xavier Morel <xmo@odoo.com> writes:

> Using `push --delete --porcelain` with refs which are extant correctly 
> outputs the relevant information in the documented format:
>
> -	:refs/heads/<branch1>	[deleted]
> -	:refs/heads/<branch2>	[deleted]
>
> However doing the same with refs which don't exist on the remote (e.g. 
> because of a concurrent deletion) has the error written out in 
> human-targeted text:
>
> error: unable to delete '<branch1>': remote ref does not exist
> error: unable to delete '<branch2>': remote ref does not exist
>
> I would have expected something along the lines of:
>
> !	:refs/heads/<branch>	[remote failure]
>
> which would be machine-readable as documented for the `--porcelain` 
> flag. Was that intended or is it just something that fell through the 
> cracks of code convolution?

If I have to guess, I would say it is because nobody thought of
covering this usage pattern, which allows you to randomly throw a
deletion request to probe what does and what does not exist on the
other side.

Patches welcome.

Thanks.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: `git push --porcelain` has no effect when deleting a ref which does not exist
  2026-08-05 16:30 ` Junio C Hamano
@ 2026-08-07  6:51   ` Xavier Morel
  0 siblings, 0 replies; 3+ messages in thread
From: Xavier Morel @ 2026-08-07  6:51 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On 05/08/2026 18:30, Junio C Hamano wrote:
> Xavier Morel <xmo@odoo.com> writes:
> 
>> Using `push --delete --porcelain` with refs which are extant correctly
>> outputs the relevant information in the documented format:
>>
>> -	:refs/heads/<branch1>	[deleted]
>> -	:refs/heads/<branch2>	[deleted]
>>
>> However doing the same with refs which don't exist on the remote (e.g.
>> because of a concurrent deletion) has the error written out in
>> human-targeted text:
>>
>> error: unable to delete '<branch1>': remote ref does not exist
>> error: unable to delete '<branch2>': remote ref does not exist
>>
>> I would have expected something along the lines of:
>>
>> !	:refs/heads/<branch>	[remote failure]
>>
>> which would be machine-readable as documented for the `--porcelain`
>> flag. Was that intended or is it just something that fell through the
>> cracks of code convolution?
> 
> If I have to guess, I would say it is because nobody thought of
> covering this usage pattern, which allows you to randomly throw a
> deletion request to probe what does and what does not exist on the
> other side.
> 
> Patches welcome.

Looking at the current code, the abort when requesting the deletion of a 
ref which is not on the remote is pretty early in the process, during 
ref matching, which then causes `push` to bail.

Reading some of the followup the following call 
`set_ref_status_for_push` can already set statuses on remote refs before 
the push, in which case such refs with statuses set will be ignored for 
the actual network operation (and the entire thing would be skipped if 
atomic), and then we get to the reporting and teardown.

So it looks like

- `match_explicit` could create a dummy dest ref and set its status to 
some sort of failure value (either an existing one or a new one) instead 
of aborting
- then `set_ref_status_for_push` should skip over refs which already 
have a status set (so it doesn't overwrite a previous error)
- push_refs_with_push all refs with a rejection status already set
- and then the formatting needs to get adapted for the new mode / case

And then trying to delete a non-existent ref would appear in the report 
normally, and valid pushes would be performed instead of ignored, unless 
`atomic` was set in which case they'd all be aborted, similar to other 
abortions from "pre-push" checks by set_ref_status_for_push.

Does that seem to make sense or did I miss something critical? Do you 
foresee significant issues?

Would you rather a new status code for this case or extending an 
existing case? e.g. I could see REF_STATUS_REJECT_NODELETE on an 
otherwise zeroed deletion ref for missing on remote, and a non-zeroed 
deletion ref would be the existing "remote rejecting the deletion" case 
so less code (and notably not push_refs_with_push) would have to be 
adapted, but it would make the new case a bit more implicit.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-08-07  6:51 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-05  7:19 `git push --porcelain` has no effect when deleting a ref which does not exist Xavier Morel
2026-08-05 16:30 ` Junio C Hamano
2026-08-07  6:51   ` Xavier Morel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox