我从github克隆了一个repo,创建了一个新分支,推回到github,然后在本地删除了repo,最后再次克隆。现在我想在我删除当地的回购之前将我的分支恢复到它们的状态,同时我想了解更多关于我的情况发生了什么以及它如何应用于{{{{{ 1}},分离头状态,遥控器和HEAD
。
我知道感兴趣的两个分支(refs/heads
和mbigras
)仍在那里,但它们已被重命名:
mcb-fix-type
所以最初我以为我可以将atom-pane-manager git:master ❯ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/mbigras
remotes/origin/mcb-fix-typo
分支重命名为remotes/origin/mbigras
并完成,但我收到以下错误:
mbigras
有几件我很好奇的事情:
atom-pane-manager git:master ❯ git branch -a | grep mbigras | pbcopy
atom-pane-manager git:master ❯ git branch -m remotes/origin/mbigras mbigras
error: refname refs/heads/remotes/origin/mbigras not found
fatal: Branch rename failed
?同时看着树枝我也想知道:
refs/heads/
和remotes/origin/HEAD
分支是什么意思?我正试图在remotes/origin/master
中试图解决问题的正面或反面
.git
我期望在atom-pane-manager git:master ❯ tree .git/refs
.git/refs
├── heads
│ └── master
├── remotes
│ └── origin
│ └── HEAD
└── tags
4 directories, 2 files
中至少找到remotes/origin/mbigras
和remotes/origin/mcb-fix-typo
,但他们不是,这也令人困惑。
我还阅读another post谈到“超级头状态”我不确定这是否适用于我的情况,但帖子确实超过了remotes
命令,这可能有助于解释:
git rev-parse
从这些结果看来,atom-pane-manager git:master ❯ git rev-parse master
73b3c240ff9b35d760d8e4302308d3c0e725fc76
atom-pane-manager git:master ❯ git rev-parse HEAD
73b3c240ff9b35d760d8e4302308d3c0e725fc76
atom-pane-manager git:master ❯ git rev-parse remotes/origin/HEAD
73b3c240ff9b35d760d8e4302308d3c0e725fc76
atom-pane-manager git:master ❯ git rev-parse remotes/origin/master
73b3c240ff9b35d760d8e4302308d3c0e725fc76
atom-pane-manager git:master ❯ git rev-parse remotes/origin/mbigras
9a25755b0175ba2a3548b439ffdb12b8010e74a6
atom-pane-manager git:master ❯ git rev-parse remotes/origin/mcb-fix-typo
6d235be40c7223fda7a8a6dbdf8b2fd7336e3d00
,HEAD
,master
和remotes/origin/HEAD
都指向同一个地方,这是有道理的,因为他们指向的是最后一次提交:
remotes/origin/master
两个神秘的分支确实存在......某处。
所以我很困惑到底发生了什么,特别是上面提到的三个问题。我特别喜欢一个答案,包括对正在发生的事情的视觉表现。谢谢
答案 0 :(得分:2)
为什么我不能重命名分支?
正如我们将在下面看到的那样,您不应该重命名远程分支,git-branch
不会让您失望。但事实并非如此。正如git所说,它无法找到它。
atom-pane-manager git:master ❯ git branch -m remotes/origin/mbigras mbigras
error: refname refs/heads/remotes/origin/mbigras not found
fatal: Branch rename failed
^^^^^^^^^
git branch -a
说remotes/origin/mbigras
,但该分支的名称为origin/mbigras
。正如我们稍后会看到的那样,甚至是缩写。
git branch -a
的格式有点令人困惑。 git branch
和git branch -r
都会显示分支名称。 git branch -a
向您显示本地分支的名称,但为了区分远程,它会在remotes/
之前对它们进行区分。例如......
$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
$ git branch -r
origin/HEAD -> origin/master
origin/master
遥控器/原点/ HEAD和遥控器/原点/主分支是什么意思?
HEAD
是当前签出的提交。 origin/HEAD
是远程当前检出的提交...或者这是Git最后一次查看。当你获取,推送,拉取和克隆时,Git只与远程控制器通信。其余的时间它使用&#34;远程跟踪分支&#34;它们存储在.git/remotes/<remote name>/<branch>
中。这些记录了上次查看时远程分支的状态。这是让Git非常快速的一部分,它几乎从不与网络交谈。
箭头告诉您origin / HEAD与origin / master在同一个提交中。这意味着远程控制台上当前已检出的分支是master。它通常表示默认分支是什么。使用不同命名方案的项目可能使用trunk
或development
而不是master
的Git约定。
为什么错误消息中的分支名称中包含refs / heads /?
本地分支存储在.git/refs/heads/
中,远程存储在.git/refs/remotes/
中。它们只是一个带有提交ID的文件,git称之为&#34;符号引用&#34;。
$ cat .git/refs/heads/master
177e49fff4348251ec30e3641d116accc0734c9d
$ cat .git/refs/remotes/origin/master
177e49fff4348251ec30e3641d116accc0734c9d
告诉我master和origin / master指向同一个提交。
master
实际上是分支的缩写名称。全名是refs/heads/master
,它只是.git/
中的文件名。 Git会互换使用它们。 master
含糊不清,它可能是一个标签,它可能是一个分支,它可能是一堆其他东西。因此,在错误消息中,Git将使用全名明确。
当你告诉Git你想使用master
时,它会进行搜索,就像你尝试运行命令时shell所做的PATH
查找一样。
1. If $GIT_DIR/<refname> exists (HEAD, FETCH_HEAD, ORIG_HEAD, ...);
2. otherwise, refs/<refname> if it exists; (???)
3. otherwise, refs/tags/<refname> if it exists; (it's a tag)
4. otherwise, refs/heads/<refname> if it exists; (it's a local branch)
5. otherwise, refs/remotes/<refname> if it exists; (it's a remote branch)
6. otherwise, refs/remotes/<refname>/HEAD if it exists. (it's a remote name)
gitrevisions docs详细解释了这一切。
了解这一点,我们可以找出为什么你不能重命名遥控器/起源/ mbigras的另一个原因:git branch
没有进行全面搜索,它假设&#39 ;当地分公司。</ p>
error: refname refs/heads/remotes/origin/mbigras not found
^^^^^^^^^^^
远程分支位于.git/refs/remotes/
。 git branch -m
永远不会重命名遥控器,因为它们位于不同的目录中。这很好!远程跟踪分支应该与远程存储库保持同步,如果你开始重命名它们会变得很奇怪。
你可以进入.git/refs/remotes
并开始重命名文件,这将重命名遥控器。不要那样做,因为 你实际上并不想重命名遥控器,你想从远程 创建一个新的本地分支。
git branch origin/mbigras mbigras
那就是它(你可能想要检查mbigras)。这大致相当于:
cp .git/refs/remotes/origin/mbigras .git/refs/heads/mbigras
加上对.git/config
的一些修改,以便记住mbigras
正在跟踪origin/mbigras
,因此git pull
和git push
知道如果你不知道要与哪个远程和分支进行对话#39; t拼出git pull origin mbigras
。那是origin mbigras
,而不是origin/mbigras
,因为它是git pull <remote name> <remote branch name>
。
(然后我们将在下面看到包装参考的例外情况。)
现在,您可以在本地分支mbigras
上工作,并通过它的跟踪分支mbigras
从origin/mbigras
的远程版本推送和拉取,该分支将保持同步你,但只有当你进行推,拉,取。
我期待至少在遥控器中找到遥控器/原点/ mbigras和遥控器/原点/ mcb-fix-typo,但它们不是,这也令人困惑。
这是因为优化。我上面描述的是Git在解压缩东西时的工作方式。为了优化目的,Git将使用packfiles和打包引用我没有资格解释,但与克隆更有效率有关。
长话短说,如果.git/refs/
中的参考号不在.git/packed-refs
,那么
$ cat .git/packed-refs
# pack-refs with: peeled fully-peeled
5f73dc320dbf320b6a6b497048dade6626d0c74b refs/remotes/origin/80_method_methods
260c0405871b7f92ed301041fef3f6c7ed90a5a5 refs/remotes/origin/appveyor
df99a98b7ba26bf5c4eb2a7fe3ec35bfe8090652 refs/remotes/origin/gh-pages
...
同样,有时候某个对象不会出现在.git/objects/
中,而是会出现在.git/pack/
中。 packfiles的格式远远超出我的理解。
Git总是有新东西!我已经使用它八年了,这是我第一次遇到包装参考。
这可能看起来有点压倒性,但显示版本控制系统的内容意味着您可以完全理解它。