Repo和它的克隆不同意HEAD指针

时间:2016-06-01 01:31:03

标签: git git-branch git-clone git-remote

我正在尝试将我的主分支重命名为'liveBranch',创建一个新分支('devBranch'),然后在同一台计算机上的另一个文件夹中克隆repo(称之为repo A)(称之为repo B) 。但是当我这样做的时候,如果我在回购B上做git branch -a,它会显示回购A的HEAD指向'devBranch'而回购时的git branch -a A声称'liveBranch'被检出

以下是我的确切步骤(注意:repoA是非空目录):

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

在回购B中运行git branch -a返回:

* devBranch
  remotes/origin/HEAD -> origin/devBranch
  remotes/origin/devBranch
  remotes/origin/liveBranch

在回购A中运行git branch -a时返回:

  devBranch
* liveBranch

我认为这可能是因为两个分支实际上都指向同一个提交,因此两个repo在技术上都是错误的。所以我在回购A中的一个分支上提交了一个推进分支并在回购B中做了git pull,但是仍然发生了断开连接(回购B和回购A不同意哪个分支回购A已经检出)。

2 个答案:

答案 0 :(得分:2)

你的“确切步骤”有点不对劲,因为如果我开始试图重现这个问题:

cd path/to/repoA
git init
git add .
git commit

我在我的系统上得到了这个:

$ 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
$ 

似乎您可能正在已经存在的存储库中执行git init并且有一些提交,否则master此时仍然是未出生的分支。无论如何,现在我改变你的步骤:

$ 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
$ 

现在让我们尝试将其克隆到/ 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
$ 

它按照你想要的方式工作。

让我们采用不同的方法来重复这个问题,从删除两个测试存储库开始,然后创建一个新的存储库,HEAD指向devBranch,然后克隆该存储库:

$ 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
$ 

所以我们让repoB处于合适的状态。现在我们更改repoA,使其HEAD指向liveBranch

$ (cd repoA; git checkout -b liveBranch; git branch)
Switched to a new branch 'liveBranch'
  devBranch
* liveBranch
$ 

如果我们在repoB中询问git git pull,我们现在应该期待发生什么?好吧,让我们看看发生了什么(请注意,这是使用Git版本2.8.1;在某些情况下,1.8.4之前的行为会有所不同):

$ 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
$ 

现在让我们尝试一些不同的东西,即在repoB中运行git fetch,以及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

显然,git pullgit fetch都没有读取新的远程HEAD状态,或者如果是,则回退到名称到ID的转换。让我们用新的提交更新repoA并重新获取:

$ (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
$ 

所以,是的,Git在初始克隆之后根本无法更新remotes/origin/HEAD,至少在使用绝对路径时。将网址更改为file:///tmp/btest/repoA没有任何区别:

$ 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

快速查看源代码表明,在最初的clone步骤之后,git从不会更新remotes/origin/HEAD

答案 1 :(得分:0)

<块引用>

似乎您正在一个已经存在并有一些提交的存储库中执行 git init,否则 master 此时仍将是一个未出生的分支。

即使 master 未出生,您仍然可以(现在,Git 2.30,2021 年第一季度)重命名它:

这是用户培训的一部分,为他们将来更改 init.defaultBranch 配置变量做好准备。

请参阅 commit 675704ccommit cc0f13ccommit cfaff3acommit 1296cbeJohannes Schindelin (dscho)(2020 年 12 月 11 日)。
(由 Junio C Hamano -- gitster --commit 772bdcd 合并,2020 年 12 月 18 日)

<块引用>

branch -m:允许重命名尚未出生的分支

签字人:约翰内斯·辛德林

<块引用>

在接下来的一次提交中,我们想给用户一些关于初始分支名称以及如何修改它的建议。

为此,如果 git branch -m <name>(man) 在没有任何提交的情况下在新初始化的存储库中工作会很好。
就这样吧。

测试表明:

test_expect_success 'branch -m with the initial branch' '
    git init rename-initial &&
    git -C rename-initial branch -m renamed &&
    test renamed = $(git -C rename-initial symbolic-ref --short HEAD) &&
    git -C rename-initial branch -m renamed again &&
    test again = $(git -C rename-initial symbolic-ref --short HEAD)