Patrick Steinhardt <ps@xxxxxx> writes: >> > I might have missed it while scanning through this thread, but why >> > exactly is the zero OID not a good enough placeholder here to say that >> > the ref must not exist? A symref cannot point to a ref named after the >> > zero OID anyway. > >> > In my opinion, "update-symref" with an old-value must be able to accept >> > both object IDs and symrefs as old value. Like this it would be possible >> > to update a proper ref to a symref in a race-free way. So you can say: >> > >> > git update-ref SYMREF refs/heads/main 19981daefd7c147444462739375462b49412ce33 > >> > To update "SYRMEF" to "refs/heads/main", but only in case it currently >> > is a proper ref that points to 19981daefd7c147444462739375462b49412ce33. >> > Similarly... >> > >> > git update-ref SYMREF refs/heads/main refs/heads/master > >> > would update "SYMREF" to "refs/heads/main", but only if it currently >> > points to the symref "refs/heads/master". I think that would work well. We need to explicitly forbid a file $GIT_DIR/[0-9a-f]{40} to be used as a pseudoref, which I think that is an improvement. I do not know how the transition to move to a world with a stricter rule would look like, though. >> > And by extension I think that >> > the zero OID should retain its established meaning of "This ref must not >> > exist": >> > >> > git update-ref SYMREF refs/heads/main 0000000000000000000000000000000000000000 >> > >> > This would only update "SYMREF" to "refs/heads/main" if it does not yet >> > exist. We express "SYMREF must currently be a symref" by naming an old-ref, and we say "SYMREF can currently be either a ref or symref, but it must point at this object" by naming an old-oid. The looseness of the latter (i.e. we cannot express "Before making HEAD point at ref X, ensure that it is detached at OID") looks a bit disturbing, but otherwise looks good. I offhand do not know how expressive we would want the "old" requirement to be. >> On a side-note: This would also mean that we should somehow support >> moving from symrefs to a regular ref via a transaction, so that means we >> should allow >> >> update SP <ref> SP <new-oid> [SP (<old-oid> | <old-rev>)] LF >> >> too, but I'm not going to tackle that in my patches. > > Yes, I think that would be a sensible idea, even though we have to be > careful with backwards compatibility here. In any case, I think it makes > sense to not extend the scope of your patch series and leave this for > the future. Likewise, we may want to be able to express "Before making HEAD detached at commit X, ensure that HEAD points at ref Y that points at commit Z". IOW, the "old" part might have to be not [SP (<old-oid> | <old-ref>)] but [SP <old-oid> SP <old-ref>] to specify both, perhaps?