Git push --all vs --mirror
With Git 2.24 (Q4 2019), you won't be able to use git push --all
with --mirror
.
And the problem is: --all
is sometime implied, when you are pushing from a local repository you just cloned with --mirror
.
Filippo Valsorda made the unfortunate experience recently:
Ok, git, WTF. This is not in the man pages.
So, fix an earlier regression to "git push --all
" which should have been forbidden when the target remote repository is set to be a mirror.
See commit 8e4c8af (02 Sep 2019) by Thomas Gummerer (tgummerer
).
(Merged by Junio C Hamano -- gitster
-- in commit fe048e4, 30 Sep 2019)
push
: disallow--all
and refspecs whenremote.<name>.mirror
is set
Pushes with
--all
, or refspecs are disallowed when--mirror
is given to 'git push', or when 'remote.<name>.mirror
' is set in the config of the repository, because they can have surprising effects.
800a4ab ("push
: check for errors earlier", 2018-05-16, Git v2.18.0-rc0) refactored this code to do that check earlier, so we can explicitly check for the presence of flags, instead of their side-effects.However when '
remote.<name>.mirror
' is set in the config, theTRANSPORT_PUSH_MIRROR
flag would only be set after we calling 'do_push()
', so the checks would miss it entirely.This leads to surprises for users (see above).
Fix this by making sure we set the flag (if appropriate) before checking for compatibility of the various options.
That leads to, with Git 2.29 (Q4 2020), a code cleanup.
See commit 842385b, commit 9dad073, commit 26e28fe, commit 75d3bee, commit 20f4b04, commit 5b9427e, commit 8d2aa8d, commit 424e28f, commit e885a84, commit 185e865 (30 Sep 2020) by Jeff King (peff
).
(Merged by Junio C Hamano -- gitster
-- in commit 19dd352, 05 Oct 2020)
push
: drop unused repo argument todo_push()
Signed-off-by: Jeff King
We stopped using the "repo" argument in 8e4c8af058 ("
push
: disallow --all and refspecs when remote..mirror is set", 2019-09-02, Git v2.24.0-rc0 -- merge listed in batch #4), which moved thepushremote
handling to its caller.
As it says in the documentation:
--all
Push all branches (i.e. refs under
refs/heads/
); cannot be used with other <refspec>.--mirror
... specifies that all refs under
refs/
(which includes but is not limited torefs/heads/
,refs/remotes/
, andrefs/tags/
) be mirrored ...
So a, if not the, key difference is that one means refs/heads/*
and one means refs/*
. The refs/heads/*
names are the branch names. Anything in refs/remotes/
is a remote-tracking name, and anything in refs/tags/
is a tag name. Other notable name-spaces include refs/notes/
, refs/replace/
, and the singular refs/stash
.
The --mirror
option goes on to mention:
locally updated refs will be force updated on the remote end, and deleted refs will be removed from the remote end.
Hence --mirror
effectively implies both --force
and --prune
; --all
does not. You can, however, add --force
and/or --prune
to git push --all
, if you like.
It is always up to the other Git to decide whether to obey polite requests (those sent without --force
) or commands (--force
) to make changes to its references.
With deleted local branch,
--all
doesn't push it and--mirror
does.
This is a consequence of the --prune
option: telling your Git to use --prune
means "ask them to delete names in their name-space(s) that are not in mine".