git clone does not checkout active branch

北城以北 提交于 2019-12-10 21:32:45

问题


I have a remote bare repository with two branches 'master' and 'testing', where HEAD refers to 'testing'. When cloning this repository git checks out 'master', if 'master' and 'testing' are on the same revision (i.e. HEAD == testing == master). Only if 'testing' is one (or more) commit(s) behind or ahead, git clone checks out the 'testing' branch on the local side. I tried this with git 1.7.5 on Mac OS X (10.6.8).

Addendum: I just tried the same with a non-bare repository:

mkdir A
cd A
git init
touch a
git add a
git commit -m "init repo A with a"
git checkout -b testing

now back in the root dir:

cd ..
git clone A B
cd B
git branch -v -a
* master                 28f599b init A
  remotes/origin/HEAD    -> origin/master
  remotes/origin/master  28f599b init A
  remotes/origin/testing 28f599b init A

it's 'master'! Back to repo A (we are still in branch 'testing'):

cd ../A
touch b
git add b
git commit -m "add b in branch testing"

now 'testing' is one commit ahead 'master'. Now let's clone A again:

cd ..
git clone A C
cd C
git branch -a -v
* testing                23bca39 add b in branch testing
  remotes/origin/HEAD    -> origin/testing
  remotes/origin/master  28f599b init A
  remotes/origin/testing 23bca39 add b in branch testing

You can re-verify this weird behavior by going back to A, checkout 'master' and merge it with 'testing' (so that all branches have the same head). Now clone A into D and D will be checked out on master!


回答1:


git clone copies all branches and their history, and the SHA1 and not refs of their heads. AFAIK refspecs are not transferred because they are newer to git than cloning (obviously), and the clone protocol does not preserve them... this means that it guesses (edit: this has been confirmed by the mailing list).

The ref for head is guessed during clone by matching its SHA1. In your case, the SHA1 is ambiguous because master and testing both match, so master is chosen by convention. This is not documented anywhere to my knowledge, but should be.

To see that this is so, go to your B example repo and run git ls-remote. The output will give you SHA1s, and not refs:

1c3eebcd1bd3659a40f02880918d5fbd5614b51a    HEAD
1c3eebcd1bd3659a40f02880918d5fbd5614b51a    refs/heads/master
1c3eebcd1bd3659a40f02880918d5fbd5614b51a    refs/heads/testing

As a workaround,

git clone -b <branch_name>

will clone and checkout your desired branch branch_name, such as master or test.

I think at this time you are forced to stick to the convention that HEAD is master and master is the default branch for checkout, and if you are set on having a different head for devs to clone use the -b switch.




回答2:


Got an answer from the git mailing list - @Shelhamer: you're right

Yes, this is a known issue.

The git protocol just sends the list of refs and the objects they point to. So the local clone is forced to guess which ref HEAD is pointing to. E.g., with something like:

28f599b... HEAD 1234abc... refs/heads/master 28f599b... refs/heads/testing

it can see that HEAD is probably "testing". But if it sees:

28f599b... HEAD 28f599b... refs/heads/master 28f599b... refs/heads/testing

then it has to pick one arbitrarily. Our current heuristic is to prefer "master" over others, and otherwise pick first alphabetically. So it's at least deterministic, but as you noticed, it's not always right.

The real solution to this would be to extend the git protocol to convey symbolic ref information (and then wait for both client and server to be upgraded). Some patches have been floated in the past, but nothing came of it. Maybe it's time to resurrect them.

As a workaround, you can use "git clone -b testing ..." if you know ahead of time that "testing" is what you want.

See:

1. http://thread.gmane.org/gmane.comp.version-control.git/102039

2. http://article.gmane.org/gmane.comp.version-control.git/113567



来源:https://stackoverflow.com/questions/6927778/git-clone-does-not-checkout-active-branch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!