I’m trying to rename my master branch to 'liveBranch', create a new branch ('devBranch'), then clone the repo (call it repo A) in another folder on the same computer (call it repo B). But when I do so, if I do a git branch -a
on repo B, it shows the HEAD of repo A to be pointing to 'devBranch' while git branch -a
on repo A claims that 'liveBranch' is checked out.
Here are my exact steps (note: repoA is a non-empty directory):
cd path/to/repoA
git init
git add .
git commit
git branch -m master liveBranch
git branch devBranch
git clone path/to/repoA path/to/repoB
cd path/to/repoB
Running git branch -a
in repo B returns:
* devBranch
remotes/origin/HEAD -> origin/devBranch
remotes/origin/devBranch
remotes/origin/liveBranch
While running git branch -a
in repo A returns:
devBranch
* liveBranch
I thought this might be because both the two branches are actually pointing to the same commit, so neither repo is technically wrong. So I made a commit on one of the branches in repo A to advance the branch and did a git pull
in repo B, but the disconnect is still occurring (repo B and repo A disagree on what branch repo A has checked out).
There is something a bit wrong with your "exact steps", because if I begin by trying to reproduce the problem:
cd path/to/repoA git init git add . git commit
I get this on my system:
$ cd /tmp; mkdir btest; cd btest
$ mkdir repoA; cd repoA
$ git init
Initialized empty Git repository in /tmp/btest/repoA/.git/
$ git add .
$ git commit
On branch master
Initial commit
nothing to commit
$
It seems as though perhaps you are doing your git init
in a repository that already exists and has some commit(s), otherwise master
would still be an unborn branch at this point. Anyway, so now I change your steps a bit:
$ echo 'dummy repo for testing' > README
$ git add .
$ git commit -m initial
[master (root-commit) 82f36fb] initial
1 file changed, 1 insertion(+)
create mode 100644 README
$ git branch -m master liveBranch
$ git branch devBranch
$ git branch
devBranch
* liveBranch
$
Now let's try cloning this to /tmp/btest/repoB:
$ git clone /tmp/btest/repoA /tmp/btest/repoB
Cloning into '/tmp/btest/repoB'...
done.
$ cd ../repoB
$ git status
On branch liveBranch
Your branch is up-to-date with 'origin/liveBranch'.
nothing to commit, working directory clean
$
and it is working the way you would like.
Let's take a different approach to repeating the problem, beginning with removing both test repositories, then making a fresh repository with HEAD
pointing to devBranch, then cloning that repository:
$ cd /tmp/btest
$ rm -rf *
$ mkdir repoA; cd repoA; git init
Initialized empty Git repository in /tmp/btest/repoA/.git/
$ echo > README; git add README; git commit -m initial
[master (root-commit) 8278cc4] initial
1 file changed, 1 insertion(+)
create mode 100644 README
$ git branch -m master devBranch
$ cd ..; git clone repoA repoB; (cd repoB; git status; git branch -A)
Cloning into 'repoB'...
done.
On branch devBranch
Your branch is up-to-date with 'origin/devBranch'.
nothing to commit, working directory clean
* devBranch
remotes/origin/HEAD -> origin/devBranch
remotes/origin/devBranch
$
So we have repoB in a suitable state. Now we alter repoA so that it has HEAD
pointing to liveBranch
:
$ (cd repoA; git checkout -b liveBranch; git branch)
Switched to a new branch 'liveBranch'
devBranch
* liveBranch
$
If we ask git to git pull
in repoB, what should we now expect to happen? Well, let's see what does happen (note, this is with Git version 2.8.1; pre-1.8.4 behavior would be a bit different in some cases):
$ cd repoB; git pull
From /tmp/btest/repoA
* [new branch] liveBranch -> origin/liveBranch
Already up-to-date.
$ git branch -a
* devBranch
remotes/origin/HEAD -> origin/devBranch
remotes/origin/devBranch
remotes/origin/liveBranch
$
Now let's try something different, namely, running git fetch
in repoB, and also git ls-remote
:
$ git fetch
$ git branch -a
* devBranch
remotes/origin/HEAD -> origin/devBranch
remotes/origin/devBranch
remotes/origin/liveBranch
$ git ls-remote
From /tmp/btest/repoA
8278cc44d45cad50f34dc2c788cd9df7bf9375ec HEAD
8278cc44d45cad50f34dc2c788cd9df7bf9375ec refs/heads/devBranch
8278cc44d45cad50f34dc2c788cd9df7bf9375ec refs/heads/liveBranch
Clearly neither git pull
nor git fetch
is reading the new remote HEAD
state, or if it is, is falling back to name-to-ID translation. Let's update repoA with a new commit and re-fetch:
$ (cd ../repoA; git commit -m update --allow-empty)
[liveBranch 2234cf1] update
$ git fetch
remote: Counting objects: 1, done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (1/1), done.
From /tmp/btest/repoA
8278cc4..2234cf1 liveBranch -> origin/liveBranch
$ git branch -a
* devBranch
remotes/origin/HEAD -> origin/devBranch
remotes/origin/devBranch
remotes/origin/liveBranch
$ git ls-remote
From /tmp/btest/repoA
2234cf14c9f7c63785e8fe31b7e5f37bcaf51823 HEAD
8278cc44d45cad50f34dc2c788cd9df7bf9375ec refs/heads/devBranch
2234cf14c9f7c63785e8fe31b7e5f37bcaf51823 refs/heads/liveBranch
$
So, yes, Git simply fails to update remotes/origin/HEAD
after the initial clone, at least when using absolute paths. Changing the URL to file:///tmp/btest/repoA
makes no difference:
$ git config remote.origin.url file:///tmp/btest/repoA
$ git fetch
$ git branch -a
* devBranch
remotes/origin/HEAD -> origin/devBranch
remotes/origin/devBranch
remotes/origin/liveBranch
and a quick look at the source code suggest that after the initial clone
step, git never bothers to update remotes/origin/HEAD
.