简体   繁体   中英

git branch -r shows different remote shared repo in different local working directory

I created a shared repo and then clone it into two folders (A and B). All in the same PC.

Now there are two branches, master and v0 . Folder A and B are now in branch v0 . On AI deleted the v0 branch on remote repo.

$ git push origin --delete v0
To file:///home/nanger/github/shared1.git
 - [deleted]         v0

and then I tried to pull the remote repo on both A and B (in branch v0 ):

Now, I see that

on A:

$ git pull
Already up-to-date.

$ git branch -r
origin/master

$ git branch
* master
v0

on B:

$ git pull
Already up-to-date

$ git branch -r
origin/HEAD -> origin/master
origin/master
origin/v0

$ git branch
* master
v0

Why do A and B have different views of the remote repo?

git pull doesn't remove local remote-tracking branches, such as origin/v0 , that are tracking remote-branches that no longer exist on the remote.

If you want to remove obsolete remote-tracking branches from your local repo, you need to use

git fetch <remote> --prune
# Or shorter
git fetch <remote> -p

Documentation

From Jan's mirror of the official git fetch docs :

 -p --prune 

After fetching, remove any remote-tracking references that no longer exist on the remote. Tags are not subject to pruning if they are fetched only because of the default tag auto-following or due to a --tags option. However, if tags are fetched due to an explicit refspec (either on the command line or in the remote configuration, for example if the remote was cloned with the --mirror option), then they are also subject to pruning.

If you want an even more detailed explanation about the different types of branches in Git (local, remote, and remote-tracking), and how to delete them, you can read about them all in my answer to How do I delete a Git branch both locally and remotely? .

Why would you expect them to be the same? (This is meant as a real question; I can think of some reasons to expect that. Obviously they're not the same, so those reasons must be wrong. You may come up with a different set of "possible reasons to expect them to be the same" than I would, though, so it's a useful exercise for you to think about why you expected them to be the same.)


In any case, git doesn't really care very much about what's in any other repository (on the same computer, or a different computer). It works on one repository at a time and cares only about what's in that one repository.

It's also important to note here that git pull is a script that does two things: first, it runs git fetch , which is the actual command that contacts some other git (usually, but not necessarily , on some other computer) to find out "what they have that you don't". Then, after that's done, git pull runs either git merge or git rebase 1 if needed.

The "other git" is called "the remote", and for a typical clone, there's just one remote, origin .

The git push command also talks to a (or the) "remote"—which, again, is usually, but not necessarily, on a different computer—and asks that the remote, which is another git repository, update its (the remote's) local branches.

We now need one more bit of background information. Your own git tries to keep track of "what's on the remote" using "remote-tracking" branches. These are the branches shown as origin/ whatever . Again, this is independent of where the remote is: these copies of the remote-branch labels are just stored locally.


When you did git push --delete v0 you had your git call up the other git and ask it (the other git) to delete its v0 . It did—it deleted the (local) v0 branch that it had before then—and your git then deleted your local copy, that your git called origin/v0 .

When you later changed to a different clone, you ran git pull which ran git fetch . This git fetch calls up the other git (usually on another computer, but in this case actually on the same laptop). I'm going to gloss over some details here (details that depend on the particular git version: there was a fairly major change in git 1.8.4 or so) and pretend you ran git fetch (which avoids needing to care about these details, that don't actually affect the final outcome).

This time, your git fetch calls up the remote git and asks it what it has now, and the remote does not list v0 , since it's now gone from the remote. This gives your (local) git a little bit of a problem. Your local git got v0 from that remote git some time earlier, and now it's gone. Should your local git delete its origin/v0 , or should it keep it?

The answer that the git programmers chose here is that your git should keep its origin/v0 around, in case you were using it for something. If you want your git fetch to delete your local origin/v0 copy of the v0 that's now missing on the remote, you should add the --prune option to your git fetch command. 2 This tells your local git to remove your local origin/ whatever whenever the remote's whatever has gone away. Otherwise, your local git keeps it.

Why does git push --delete delete it, when git fetch without --prune keeps it? That's a question for the people writing git itself. 3


1 The default is to run git merge , if you don't set up anything to override the default. Since git rebase is probably a better default, there are a lot of ways to make pull use rebase .

2 You can also use git remote prune origin or git remote update origin --prune . There were some minor git bugs that made each one act slightly differently. As far as I know they're all fixed in git versions 2.0 or higher.

3 I can guess , 4 of course: it seems that if you, the user running git push , are saying you want to delete a branch from a remote, you probably don't particularly want to keep your local copy of their branch once you've successfully deleted their branch. But it is just a guess.

4 I can call spirits from the vasty deep too, but they have never come forth. :-)

Depending on your configuration, git pull may pull only the branch you are on. Try git fetch, and then git branch -r.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM