0

I cloned a remote repo and want to have a own copy on my local git server.

So I did:

git clone ssh...

I created a new repo on my server

git init --bare

I added the new server

git remote add bm ssh...

Than I pushed to the new remote

git push --mirror bm

Now I can see on my bare server repo:

[gitmini@blaumeise simulavr]$ git branch -a
* master
  remotes/bm/master
  remotes/savannah/HEAD
  remotes/savannah/devel-tomk
  remotes/savannah/master
  remotes/savannah/oldstable
  remotes/savannah/python_3
  remotes/savannah/rel-1.0
  remotes/savannah/rel-1.1
  remotes/savannah/sbi_cbi_rework

Looks good I think.

But now I checked out from my local server

  git clone ssh...

and I only get:

  git branch -a

[krud@blaumeise simulavr]$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

I already did: git fetch --all and git pull --all, nothing changed.

Is there something wrong with my own server repo or something wrong while clone? What can I do in such a bad situation.

I already read: How to fetch all Git branches

Klaus
  • 24,205
  • 7
  • 58
  • 113
  • The accepted answer in the question you linked tells you how to set up to track all remote branches. Is that not what you want? If not, how is what you want different? – John Zwinck Oct 27 '19 at 08:39
  • @JohnZwinck: Sorry, you are right! The important point is to use the add on from the answer from Kamil Szot's . The first "solution" ends up in a long list of duplicate of branches. Using Kamil solution seems to work perfect! – Klaus Oct 27 '19 at 08:55
  • Possible duplicate of [Set up git to pull and push all branches](https://stackoverflow.com/questions/1914579/set-up-git-to-pull-and-push-all-branches) – Julian Oct 27 '19 at 09:00

2 Answers2

2

git clone defaults to copying only the (local) branches and tags of the other Git. You can get additional references, including remote-tracking names like remotes/savannah/oldstable. But that's usually not a good idea. Instead, in your bare repository, make it have branches with these names.

This is all a little bit tricky at first, but eventually it all starts to make sense. These names arise from the use of two separate Git repositories. Each Git repository has its own branch names, so:

  • A branch name is a reference whose full name starts with refs/heads/. So refs/heads/master represents branch master, and so on.

  • A remote-tracking name is a reference whose full name starts with refs/remotes/. The next part of the full name is the same as the name of the remote, and after that (and another slash) you get the branch name taken from the other Git.

This is the normal usage pattern for normal clones. There's some existing repository, which someone—or many someones—have set up somewhere out on the web (perhaps on GitHub, for instance), and it has a bunch of branches: master, develop, feature/A, feature/B, and so on. You clone that repository to your own machine (laptop or whatever) and would like to have your Git remember their branches for you, but not create a bunch of (local) branches. You now choose, perhaps, to do some work that you want to send to them later as a part of feature/A, so you create your own name feature/A on which to make new commits to send to them and recommend that they put those in their feature/A. You're not working on feature/B at all, so you don't get a feature/B, and you're not using master so you can delete your own master.

Once you do have some new commits, you will use:

git push origin feature/A

to send your new commits to their Git, and immediately—as part of git push itself—ask their Git to set their feature/A branch to remember those new commits.

That's not what you want here

When you're first setting up centralized server repository, you often don't want to follow the normal pattern. You have—or would like to copy—some existing repository that has, say, a dozen branch names. If this repository isn't on your own laptop yet, you can use git clone --mirror to make a temporary copy on your own laptop:

git clone --mirror <url> [<path>]

Now you have, on your laptop, a bare clone (--mirror implies --bare) that has no origin/* remote-tracking names at all. Instead, Git has created, in your copy of their repository, regular old branch names—not remote-tracking names—corresponding to their branch names. So you have the same dozen branch names that they have.

A mirror clone is useless for doing any work of your own! You create this mirror clone temporarily, to get a copy of their repository in which their branch names are your branch names too. If you already have a full working repository with your dozen (or whatever) branches, you skip this step.

Now that you have the clone that has all the branches, now you can create an empty repository on the server (or on GitHub). Now you can run:

git push --all <url-of-server-repository>

And now, if you made a mirror clone, you can throw away the mirror clone. You made it only for the purpose of sending everything, including all the branch names, to the server. So now you might like to remove the mirror clone and make a normal clone of the server clone to use to do actual work.

(If you did a git push from a local repository that was already all set, you don't want or need to remove the local clone, and you might want to use git remote add before the git push. See below.)

The above is somewhat wasteful!

You might object to having to make this silly mirror clone, only to then have to throw it out and make a normal, non-bare clone after pushing the mirror clone to the server.

You do not have to make the mirror clone. This is only for convenience.

Instead, you can:

  • make a regular clone
  • create local branches as needed to represent all the remote-tracking names
  • use git push --all to send these all to the server
  • remove all the local names you made (but keep any you didn't have to make).

Or, instead of the above, you can:

  • make (or have) a regular clone
  • use git push without --all: instead, use refspecs to push the remote-tracking names on your end to branch names on their end.

This last method is in some ways the neatest, but it requires understanding refspecs.

A refspec is, in its second-simplest form, a pair of references—full names like refs/heads/master or refs/remotes/feature/A—separated by a colon :. The name on the left side of the colon is the source and the name on the right side is the destination. Refspecs behave similarly, though not identically, in both git fetch and git push: the source ref provides a commit hash in the sending Git, and the destination ref provides a name to set in the receiving Git. Since git push sends from your Git repository to their Git repository, you can use your remote-tracking names on the left, and their branch names on the right:

# after creating an empty repository on github
git remote add origin <url-on-github>
git push origin master   # send your refs/heads/master to theirs
git push origin refs/remotes/savannah/devel-tomk:refs/heads/devel-tomk
git push origin refs/remotes/savannah/python_3:refs/heads/python_3

(assuming you want your remote-tracking savannah/devel-tomk to become their devel-tomk branch, and so on).

You can put all the refspecs into one big git push line, but it's ridiculously easy to typo part of it, which is annoying:

git push origin master refs/remotes/savannah/devel-tomk:refs/heads/devel-tomk refs/remotes/savannah/python_3:refs/heads/python_3

for instance, if I did not typo anything.

torek
  • 448,244
  • 59
  • 642
  • 775
0

You didn't create a copy of the entire repo. You only created a repo with master branch.

By default push is pushing only a single branch. Try adding the --all flag

git push --mirror --all bm
Mehdi
  • 7,204
  • 1
  • 32
  • 44
Igal S.
  • 13,146
  • 5
  • 30
  • 48