克隆后恢复分支

时间:2016-07-02 17:32:38

标签: git github

我从github克隆了一个repo,创建了一个新分支,推回到github,然后在本地删除了repo,最后再次克隆。现在我想在我删除当地的回购之前将我的分支恢复到它们的状态,同时我想了解更多关于我的情况发生了什么以及它如何应用于{{{{{ 1}},分离头状态,遥控器和HEAD

我知道感兴趣的两个分支(refs/headsmbigras)仍在那里,但它们已被重命名:

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

有几件我很好奇的事情:

  1. 为什么我不能重命名分支?
  2. 为什么错误消息中的分支名称中包含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
  3. 同时看着树枝我也想知道:

    1. refs/heads/remotes/origin/HEAD分支是什么意思?
    2. 我正试图在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/mbigrasremotes/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 HEADmasterremotes/origin/HEAD都指向同一个地方,这是有道理的,因为他们指向的是最后一次提交:

      remotes/origin/master

      两个神秘的分支确实存在......某处。

      所以我很困惑到底发生了什么,特别是上面提到的三个问题。我特别喜欢一个答案,包括对正在发生的事情的视觉表现。谢谢

1 个答案:

答案 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 -aremotes/origin/mbigras,但该分支的名称为origin/mbigras。正如我们稍后会看到的那样,甚至是缩写。

git branch -a的格式有点令人困惑。 git branchgit 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。它通常表示默认分支是什么。使用不同命名方案的项目可能使用trunkdevelopment而不是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 pullgit push知道如果你不知道要与哪个远程和分支进行对话#39; t拼出git pull origin mbigras。那是origin mbigras,而不是origin/mbigras,因为它是git pull <remote name> <remote branch name>

(然后我们将在下面看到包装参考的例外情况。)

现在,您可以在本地分支mbigras上工作,并通过它的跟踪分支mbigrasorigin/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总是有新东西!我已经使用它八年了,这是我第一次遇到包装参考。

这可能看起来有点压倒性,但显示版本控制系统的内容意味着您可以完全理解它。