Skip to content

Commit 8ea8281

Browse files
Unique-Usmangitster
authored andcommitted
push: support pushing to a remote group
`git fetch` accepts a remote group name (configured via `remotes.<name>` in config) and fetches from each member remote. `git push` has no equivalent — it only accepts a single remote name. Teach `git push` to resolve its repository argument through `add_remote_or_group()`, which was made public in the previous patch, so that a user can push to all remotes in a group with: git push <group> When the argument resolves to a single remote, the behaviour is identical to before. When it resolves to a group, each member remote is pushed in sequence. The group push path rebuilds the refspec list (`rs`) from scratch for each member remote so that per-remote push mappings configured via `remote.<name>.push` are resolved correctly against each specific remote. Without this, refspec entries would accumulate across iterations and each subsequent remote would receive a growing list of duplicated entries. Mirror detection (`remote->mirror`) is also evaluated per remote using a copy of the flags, so that a mirror remote in the group cannot set TRANSPORT_PUSH_FORCE on subsequent non-mirror remotes in the same group. Suggested-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 3e7b9dc commit 8ea8281

4 files changed

Lines changed: 451 additions & 41 deletions

File tree

Documentation/git-push.adoc

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,28 @@ git push [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n
1818

1919
DESCRIPTION
2020
-----------
21-
22-
Updates one or more branches, tags, or other references in a remote
23-
repository from your local repository, and sends all necessary data
24-
that isn't already on the remote.
21+
Updates one or more branches, tags, or other references in one or more
22+
remote repositories from your local repository, and sends all necessary
23+
data that isn't already on the remote.
2524

2625
The simplest way to push is `git push <remote> <branch>`.
2726
`git push origin main` will push the local `main` branch to the `main`
2827
branch on the remote named `origin`.
2928

30-
The `<repository>` argument defaults to the upstream for the current branch,
31-
or `origin` if there's no configured upstream.
29+
You can also push to multiple remotes at once by using a remote group.
30+
A remote group is a named list of remotes configured via `remotes.<name>`
31+
in your git config:
32+
33+
$ git config remotes.all-remotes "origin gitlab backup"
34+
35+
Then `git push all-remotes` will push to `origin`, `gitlab`, and
36+
`backup` in turn, as if you had run `git push` against each one
37+
individually. Each remote is pushed independently using its own
38+
push mapping configuration. There is a `remotes.<group>` entry in
39+
the configuration file. (See linkgit:git-config[1]).
40+
41+
The `<repository>` argument defaults to the upstream for the current
42+
branch, or `origin` if there's no configured upstream.
3243

3344
To decide which branches, tags, or other refs to push, Git uses
3445
(in order of precedence):
@@ -55,8 +66,10 @@ OPTIONS
5566
_<repository>_::
5667
The "remote" repository that is the destination of a push
5768
operation. This parameter can be either a URL
58-
(see the section <<URLS,GIT URLS>> below) or the name
59-
of a remote (see the section <<REMOTES,REMOTES>> below).
69+
(see the section <<URLS,GIT URLS>> below), the name
70+
of a remote (see the section <<REMOTES,REMOTES>> below),
71+
or the name of a remote group
72+
(see the section <<REMOTE-GROUPS,REMOTE GROUPS>> below).
6073
6174
`<refspec>...`::
6275
Specify what destination ref to update with what source object.
@@ -430,6 +443,57 @@ further recursion will occur. In this case, `only` is treated as `on-demand`.
430443
431444
include::urls-remotes.adoc[]
432445
446+
[[REMOTE-GROUPS]]
447+
REMOTE GROUPS
448+
-------------
449+
450+
A remote group is a named list of remotes configured via `remotes.<name>`
451+
in your git config:
452+
453+
$ git config remotes.all-remotes "r1 r2 r3"
454+
455+
When a group name is given as the `<repository>` argument, the push is
456+
performed to each member remote in turn. The defining principle is:
457+
458+
git push <options> all-remotes <args>
459+
460+
is exactly equivalent to:
461+
462+
git push <options> r1 <args>
463+
git push <options> r2 <args>
464+
...
465+
git push <options> rN <args>
466+
467+
where r1, r2, ..., rN are the members of `all-remotes`. No special
468+
behaviour is added or removed — the group is purely a shorthand for
469+
running the same push command against each member remote individually.
470+
471+
When pushing to a group of more than one remote, Git spawns a separate
472+
`git push` subprocess for each member remote in sequence. Each subprocess
473+
receives the same flags and refspecs as the original invocation. This
474+
means that per-remote push mappings configured via `remote.<name>.push`
475+
and mirror mode (`remote.<name>.mirror`) are evaluated independently for
476+
each remote, and a mirror remote in the group cannot affect the push
477+
behaviour of other non-mirror remotes in the same group.
478+
479+
The `--atomic` option is not supported for group pushes, because atomicity
480+
can only be guaranteed within a single transport connection to a single
481+
remote. Git will refuse the invocation with an error if `--atomic` is
482+
combined with a group name.
483+
484+
If any member remote fails whether due to a push rejection (e.g. a
485+
non-fast-forward update, a server-side hook refusing a ref) or a connection
486+
error (e.g. the repository does not exist, authentication fails, or the
487+
network is unreachable), Git reports the error and continues pushing to
488+
the remaining remotes in the group. The overall exit code is non-zero if
489+
any member push fails.
490+
491+
This means the user is responsible for ensuring that the sequence of
492+
individual pushes makes sense. If `git push r1`` would fail for a given
493+
set of options and arguments, then `git push all-remotes` will fail in
494+
the same way when it reaches r1. The group push does not do anything
495+
special to make a failing individual push succeed.
496+
433497
OUTPUT
434498
------
435499

0 commit comments

Comments
 (0)