# "git fetch -p" incorrectly deletes branches

2 messages from 2017-01-17 to 2017-01-26. Participants: Reimar Döffinger, Jeff King.
Thread: https://gitlist.dev/t/44897

## Reimar Döffinger, 2017-01-17 06:04

Subject: "git fetch -p" incorrectly deletes branches
Message-ID: <20170117060428.nanqz5lr4hi6dum6@reimardoeffinger.de>
URL: https://gitlist.dev/e/20170117060428.nanqz5lr4hi6dum6%40reimardoeffinger.de

```
Hello!
The command:
git fetch -p -v origin master:refs/heads/test

Deletes refs/heads/test every second time when run repeatedly:

$ git fetch -p -v origin master:refs/heads/test
From https://github.com/git/git
 * [new branch]          master     -> test
 = [up to date]          master     -> origin/master
$ git fetch -p -v origin master:refs/heads/test
From https://github.com/git/git
 - [deleted]             (none)     -> test
 = [up to date]          master     -> test
 = [up to date]          master     -> origin/master

(the command is the result of cutting down the test case,
so yes it is rather silly, but the issue appears in much
less obviously silly cases and causes a lot of confusion)
This is specific to the case of specifying the origin branch
without "full path" AND the right side with.
Wild-guess on cause: "master" is auto-expanded into both
"refs/tags/master" and "refs/heads/master" and instead of
fetching either/merging the result, both are fetched.
Combined with a time-of-check/time-of-use style race condition
on the code that checks if a ref is "up to date" on top of it,
it would result in this behaviour.
Also note that this behaviour appears also when fetch.prune=yes
is set in the config (instead of -p on the command-line),
which makes it much less obvious and there is no option to turn
of prune just for that command to work-around this.
I hope someone has the time to make sure nobody else has to
debug this ever again ;-)

Regards,
Reimar Döffinger

```

## Jeff King, 2017-01-26 21:18

Subject: Re: "git fetch -p" incorrectly deletes branches
Message-ID: <20170126211834.eplmjcohv3d4zsym@sigill.intra.peff.net>
URL: https://gitlist.dev/e/20170126211834.eplmjcohv3d4zsym%40sigill.intra.peff.net
In-Reply-To: <20170117060428.nanqz5lr4hi6dum6@reimardoeffinger.de>

```
On Tue, Jan 17, 2017 at 07:04:28AM +0100, Reimar Döffinger wrote:

> Deletes refs/heads/test every second time when run repeatedly:
> 
> $ git fetch -p -v origin master:refs/heads/test
> From https://github.com/git/git
>  * [new branch]          master     -> test
>  = [up to date]          master     -> origin/master
> $ git fetch -p -v origin master:refs/heads/test
> From https://github.com/git/git
>  - [deleted]             (none)     -> test
>  = [up to date]          master     -> test
>  = [up to date]          master     -> origin/master

Hmm. It seems like the problem is that "-p" is saying "the other side
does not have refs/heads/test; we must prune it". But I think it is
probably nonsense to apply pruning to a non-wildcard refspec.


> Also note that this behaviour appears also when fetch.prune=yes
> is set in the config (instead of -p on the command-line),
> which makes it much less obvious and there is no option to turn
> of prune just for that command to work-around this.

There is a separate issue of whether it is sane to apply fetch.prune to
a refspec given on the command line; I can imagine it as surprising, to
say the least.

I think "--no-prune" would disable it, though.

-Peff

```
