There are two remote repositories as follows.
git clone --mirror original.git
.Pushing refs from the mirror to the original remote using git push --mirror
works as expected. However, when refspec
(e.g. branch name) is combined with git-push
, Git tries to delete all the other branches except for the specified one, from both original and mirror repositories.
receive.denyDeletes
is not set in remote repositories? (I just deleted remote branches by mistake.)Note: I'm using git v2.18.0
now, and as far as I know, git push --mirror <repo> <refsepc>
is not allowed in older versions such as git v1.7.1
.
bash-4.1$ cd mirror.git/
bash-4.1$ git branch
* master
new_branch
bash-4.1$ git config --list | grep remote
remote.origin.url=/user/han/git/original.git/
remote.origin.fetch=+refs/*:refs/*
remote.origin.mirror=true
bash-4.1$ git push --mirror
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 16 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 280 bytes | 280.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /user/han/git/original.git/
* [new branch] new_branch -> new_branch
bash-4.1$ git push origin master
To /user/han/git/original.git/
- [deleted] new_branch
The specification for the --mirror
option in git push
is:
Instead of naming each ref to push, specifies that all refs under
refs/
(which includes but is not limited torefs/heads/
,refs/remotes/
, andrefs/tags/
) be mirrored to the remote repository. Newly created local refs will be pushed to the remote end, locally updated refs will be force updated on the remote end, and deleted refs will be removed from the remote end. This is the default if the configuration optionremote.<remote>.mirror
is set.
(boldface mine). Combining --mirror
with a command-line refspec causes your Git to believe that all references not mentioned on the command line are deleted, which causes your Git to send "delete this ref" requests1 to the other Git.
One could argue that this is a bug—that your own Git should simply reject the attempt to combine --mirror
with command-line-argument refspecs—and it's certainly a bit unkind. See also --prune
, which has similar behavior and is meant to be combined with command-line refspecs.
1As usual, these take the form of polite "please, if you're willing, do <thing>" unless you add the --force
flag to your command line, or a plus sign to the refspec that generates the request. Unfortunately, polite requests to delete a branch are by default obeyed, unlike polite requests to move a branch in a fashion that is not a fast-forward.