On Tue, Jan 7, 2025 at 4:30 AM Junio C Hamano <gitster@xxxxxxxxx> wrote: > > Torsten Bögershausen <tboegi@xxxxxx> writes: > > >> changes are fetched from one branch (e.g. 'foo') but are pushed to a > >> different one ('foo_incoming'). Our CI system runs to test the changes > >> and when they pass 'foo_incoming' is merged (fast-forward most of the > >> time) into 'foo'. > >> ... > >> Is there a better way of checking for the existence of a remote branch? > > > > I may have missed something, would that work: > > git fetch -p > > git branch -r > > Or "git ls-remote origin refs/heads/foo-incoming" and see if it > yields anything? git ls-remote --exit-code origin refs/heads/foo_incoming would work for me. And I think it would save me a fetch to get past one bootstrapping issue. > > The "workflow" makes me wonder how it would be bootstrapped, though. > Currently we require the first person to know what they're doing and do the initial push as `HEAD:refs/heads/foo_incoming` the CI tooling we have set up knows to create `foo` if it doesn't already exist. That's probably not too bad because for an unborn branch you'd need to say `HEAD:refs/heads/foo` anyway before subsequent pushes would work without the refspec. Our workflow does require some discipline as that first push should just be either an existing commit (when branching in an existing repo) or a largely empty "Initial commit" for a new repository. That all relies on a "gentlepersons's agreement" that the first push to one of these branches doesn't require review because there's nothing really to enforce that policy. Pushing to the non-incoming branch is restricted to the CI user via a hook on the server for plain git or with access permissions for gerrit. > When you add a new branch, "bar", to be pre-reviewed before getting > merged at the server side, you want people to push to > "bar-incoming". Before the very initial update to "bar-incoming" > that pushes into "bar-incoming" and creates it, there wouldn't be > "bar-incoming" on the remote side, would there? So "see if > foo-incoming exists and change the behaviour on the client end > accordingly" may not be a strategy to pursue. I know git has some tooling for a triangular workflow (branch.<name>.pushRemote) I'm not sure if that can be setup to push to a differently named branch. Some kind of branch.<name>.pushRefSpec might help if it could support *:*_incoming. The main thing I'm scripting on top of is Gerrit's magic refs/for/* so even if git supported our version of a triangular workflow workflow I'd still need something to decide when to use refs/for/foo or refs/for/foo_incoming when dealing with Gerrit. > If we wanted to support the "workflow" natively, the way we would do > so would be to introduce a protocol capability that allows the > server side to advertise: > > If you want to update branch B, you are not allowed to do so > directly. Instead, you are expected to push your changes to > update 'refs/for/B' > > and then "git push" on the client end would notice the capability > and turns "git push origin B" (or, more likely, the user is on local > branch B that is to build on the remote branch B from 'origin', and > "git push" with no arguments would do the right thing) into such an > update. For the most part we're happy with using a pre-receive hook on the server to block updates when required. We're able to put out an error message that tells the user to push to foo_incoming. Having some kind of config that made `git push` do the right thing would be great as it would save the user some typing. I don't know how much advertising from the git server this would really require (we could easily update our reject hook to advertise some `git config` settings). > > I am not suggesting that we jump to the above immediately. But the > reason why I am bringing it up is because The "how would I see if > they have foo-incoming?" smells like seeking a way to implement such > a custom capability advertisement outside Git. > > A few random thoughts. > > - Would it be useful if we introduced the ability to advertise > "custom capabilities" from the receiving end of the connection, > that does not affect how the rest of Git behaves at all? It > would be sort of the reverse of --server-option, which is a > mechanism to let the client to tell the other side out of band > information that the rest of Git is oblivious. > > The other side of course needs a way to inspect what capabilities > are advertised. For "--server-option", I do not think our server > end does anything special, but other implementations can act on > them. This new thing can start the same way. > > - If this is a poor-man's custom capability advertisement, perhaps > the server end can create a ref "refs/capabilities/incoming" > (whose value does not really matter) and your client side can see > if there is such a ref with "ls-remote"? That may be a more > robust thing to do instead, perhaps, as you do not need to worry > about "What about a new branch 'bar'?" bootstrapping issues. >