git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Git multiple remotes push stop at first failed connection

From
John Siu <john.sd.siu@gmail.com>
Date
Jun 2, 2020, 01:32 UTC
Message-ID
<CAGKX4vH42x7nhCgtJ80fiNeaj1ROVxc-R8gO6xV21-6D3GbQSg@mail.gmail.com>
In-Reply-To
<20200601214003.GA3309882@coredump.intra.peff.net>
Thank Jeff for replying.

Yes, one route we are looking into is use fetch -all, push -all and wrap push tag with a loop, or may do what you suggest and wrap all 3 in a loop for consistency.

On Mon, Jun 1, 2020 at 5:40 PM Jeff King <peff@peff.net> wrote:
Show 72 quoted lines
>
> On Sun, May 31, 2020 at 08:28:38PM -0400, John Siu wrote:
>
> > Let say my project has following remotes:
> >
> > $ git remote -v
> > git.all "server A git url" (fetch)
> > git.all "server A git url" (push)
> > git.all "server B git url" (push)
> > git.all "server C git ur" (push)
> >
> > When all serverA/B/C are online, "git push" works.
>
> A slight nomenclature nit, but that's _one_ remote that has several
> push urls.
>
> > However "git push" will stop at the first server it failed to connect.
> > So if git cannot connect to server A, it will not continue with server
> > B/C.
> >
> > In the past I have server C turn off from time to time, so failing the
> > last push is expected. However recently server A went offline
> > completely and we notice git is not pushing to the remaining 2
> > remotes.
> >
> > Not sure if this is intended behavior or can be improved.
>
> I don't think we've ever documented the error-handling semantics.
> Looking at the relevant code in builtin/push.c:do_push():
>
>           url_nr = push_url_of_remote(remote, &url);
>           if (url_nr) {
>                   for (i = 0; i < url_nr; i++) {
>                           struct transport *transport =
>                                   transport_get(remote, url[i]);
>                           if (flags & TRANSPORT_PUSH_OPTIONS)
>                                   transport->push_options = push_options;
>                           if (push_with_options(transport, push_refspec, flags))
>                                   errs++;
>                   }
>           } else {
>                   struct transport *transport =
>                           transport_get(remote, NULL);
>                   if (flags & TRANSPORT_PUSH_OPTIONS)
>                           transport->push_options = push_options;
>                   if (push_with_options(transport, push_refspec, flags))
>                           errs++;
>           }
>           return !!errs;
>
> it does seem to try each one and collect the errors. But the underlying
> transport code is so ready to die() on errors, taking down the whole
> process, that I suspect it rarely manages to do so. You're probably much
> better off defining a separate remote for each push destination, then
> running your own shell loop:
>
>   err=0
>   for dst in serverA serverB serverC; do
>     git push $dst || err=1
>   done
>   exit $err
>
> There's really no benefit to doing it all in a single Git process, as
> we'd connect to each independently, run a separate independent
> pack-objects for each, etc.
>
> I'd even suggest that Git implement such a loop itself, as we did for
> "git fetch --all", but sadly "push --all" is already taken for a
> different meaning (but it might still be worth doing under a different
> option name).
>
> -Peff
Previous: Jeff KingNext: Junio C Hamano
Message 3 of 5 in “Git multiple remotes push stop at first failed connection”
  1. John SiuJun 1, 2020
  2. Jeff KingJun 1, 2020
  3. John SiuJun 2, 2020
  4. Junio C HamanoJun 2, 2020
  5. John SiuJun 2, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.