如何删除没有名称的 Git 分支

How do I delete a Git branch that has no name

我不确定这是怎么发生的。但是在 rebase 之后,我有一个无名的分离分支,它是 master 的部分副本。我可能在从一个分支的一个分支变基时犯了一些错误。那么基本上如何删除提示为 0ac0e6b 的分支?

* 11e604e (HEAD -> master) Some comment
* a50932a Another comment
....
....
* 0d85332 Activities: service <-- dupes below
* 5323616 Activities: setup   <-- 
* e4f5063 Results: fix        <--
* 5bf3ec0 Composer: update
| * 0ac0e6b XController Setup (tag: sometag)   <-- THIS BRANCH HAS NO NAME
| * a34b800
| * dccbd3b 
| * 020b15e Activities: service   <-- dupes above
| * f4231cf Activities: setup     <--
| * 118536f Results: fix          <--
|/  
* c42ad6f Some comment 

[原来这个问题是分支中的一个标签似乎阻止它被删除 - 我会把它留在这里以防有人遇到同样的问题。删除标签,我案例中的分支就消失了。在编辑中添加了标签。]

如果要清理存储库,可以使用 git gc commandgc 代表垃圾收集器,它删除不必要的(即不属于任何分支的提交)提交。

正如您所发现的,对于 Git 到 首先找到 一个提交,它必须查看 一些 提交的名称。在本例中,这是一个标签名称。

最奇怪的部分是这个 git log --all --decorate --oneline --graph 输出,我将把它剪下来只有两个关键行(和一个“...”):

* 11e604e (HEAD -> master) Some comment
...
| * 0ac0e6b XController Setup

第一个告诉我们您正在使用 --decorate:提交显示的名称是 Git 找到的在括号中提交。

然后我们进入神秘提交。由于您使用的是 --decorate,因此 应该 阅读:

| * 0ac0e6b (tag: sometag) XController Setup

这会告诉我们标签 sometag 是 Git 找到这个新引入的提交流的名称。

一旦 Git 找到任何特定的提交,当然,它会使用该提交的父哈希 ID 来查找提交的父,因此:

| * a34b800
| * dccbd3b 

等等并不神秘:它们是通过提交 0ac0e6b 的散列 ID(可以说是 "true name")找到的。特别是,a34b8000ac0e6b 的父级,dccbd3ba34b800 的父级,依此类推。

这实际上是对 Git

的关键洞察

值得考虑一下:Git 中的分支名称不会创建 提交。它只是让 Git 找到 提交,并且它通过直接指向一个 - 只是 一个 - 提交来做到这一点。 Git 将此指向提交称为分支的 提示

为了向现有分支添加新提交,Git 所做的是:

  • 编写一个新的提交,其中包含源快照、作者姓名以及您在 git log 中看到的所有其他常见元数据。这些元数据之一是提交的 父 ID 哈希。

    新提交的父ID是分支名称指向的提交:

    ... <--commit <--commit <--current-tip-commit   <-- branchname
                                     \
                               new-commit-just-made
    
  • 并且,现在 new 提交存在,更改 分支名称中存储的哈希。分支名称不再指向之前的提示提交。现在它指向您刚刚进行的新提交!

    ... <--commit <--commit <--current-tip-commit
                                     \
                               new-commit-just-made   <-- branchname
    

当 Git 对分支名称进行所有这些奇特的移动时,只有一个名称实际移动。那就是 git status 说你是 "on" 的分支,就像 git statuson branch master 一样。 所有其他现有名称未受干扰。如果其中任何一个指向当前提交,它们将继续指向当前提交。

这是 git rebase 最常出错的地方,它通过 复制 提交来工作——一些提交字符串由您传递给 [=28= 的参数计算得出]—闪亮的新提交(无论如何我们希望)是对旧的沉闷提交的改进。然后它移动一个分支名称。只要那个分支名称是 only 找到旧提交的方法,现在 Git 只能找到 new 提交,看起来提交已经改变了——但他们没有!旧的还在里面。

一旦我们有了第二个名字——分支名称、标签名称、refs/stash 引用、远程跟踪名称,或者你出于某种原因发明的任何新事物——Git 通过它找到old 提交,但是,它们在 git log --all 中。现在你必须想办法让那些名字移动;如果它们是标签名称,移动它们通常不是一个好主意。