为什么Git允许我创建两个同名的分支?

为什么Git允许我创建两个同名的分支?,git,github,Git,Github,我对Git还比较陌生,我的存储库有点乱。我希望有一种不用重新克隆就能修复它的方法 我有一个从Github克隆的存储库。存储库有几个分支。我在主分支上工作了一段时间,但后来需要切换到其他分支之一 所以,我有: $ git branch --all * master remotes/origin/abc remotes/origin/def remotes/origin/HEAD -> origin/master remotes/origin/ghi 问题:我想切换到“abc

我对Git还比较陌生,我的存储库有点乱。我希望有一种不用重新克隆就能修复它的方法

我有一个从Github克隆的存储库。存储库有几个分支。我在主分支上工作了一段时间,但后来需要切换到其他分支之一

所以,我有:

$ git branch --all
* master
  remotes/origin/abc
  remotes/origin/def
  remotes/origin/HEAD -> origin/master
  remotes/origin/ghi
问题:我想切换到“abc”分支,但没有执行
git checkout remotes/origin/abc
我意外地执行了
git branch remotes/origin/abc
,这给我留下了以下几点:

$ git branch --all
* master
  remotes/origin/abc
  remotes/origin/abc
  remotes/origin/def
  remotes/origin/HEAD -> origin/master
  remotes/origin/ghi
我的问题是:

  • 究竟为什么Git允许您使用相同的方法创建两个分支 名字
  • 我如何确定哪个是真正的远程/原始/abc分支机构
  • 如何删除我创建的不需要的遥控器/原点/abc 意外

非常感谢您的帮助。

Git对分支名称几乎没有限制,例如,分支名称中的斜杠是非常好的。此外,删除远程服务器上的分支也可以通过以下方式完成:

$ git push origin :abc
当删除本地分支时,例如

$ git branch -d remotes/origin/abc

因为这两个实体位于不同的名称空间中,所以不存在歧义。

您不能使用相同的名称创建两个本地分支或两个远程分支

  • 这里有一个本地分支名为
    remotes/origin/abc
    ,远程分支名为
    abc
    ,位于远程
    origin
    上。它们的名称不相同,但当您使用
    git分支--all
    命令时,它们似乎是相同的

  • 要确定哪个分支是哪个分支,可以使用
    git branch
    显示本地分支,或者使用
    git branch--remote
    显示远程分支。即使使用分支语法着色(
    git config--global color.branch auto
    )的
    git branch--all
    ,也可以很容易地区分它们

  • 要删除意外创建的本地分支
    abc
    ,必须执行
    git branch-d abc
    (或
    git branch-d abc
    强制删除,请参阅
    man git branch


使用
gitk
gitk--all
检查分支。在那里你可以看到不同颜色的本地和远程分支。只需右键单击本地分支,即可轻松地创建、签出和删除本地分支

对于远程跟踪分支,您可以使用
gitgui
,创建分支菜单,只需选择远程分支和适当的本地命名方法。这样很难搞砸


至于第一个问题:您不能真正创建具有相同名称的分支,但是如果您为之奋斗的话,外观类似的合成名称可能会发生。有了适当的工具,它们不会被混淆,因此没有理由禁止这种情况。

真实的情况是Git的“refs”有一个简化方案(Git术语“references”,用于指分支、标记等)。事实上,引用存在于它们的名称空间中,在引用Git实现中,名称空间只是
.Git
下的目录。例如,您的本地分支“master”实际上是“refs/heads/master”——一个名为“master”的文件,位于
.git/refs/heads
目录中。还有“refs/tags”命名空间和“refs/remotes”命名空间-用于标记和远程分支(由
git fetch
命令创建的分支)

现在,当您告诉Git创建分支
remotes/origin/abc
时,它确实创建了
refs/heads/remotes/origin/abc
,这与
refs/remotes/origin/abc
不冲突,因为处理简化方案的规则使前者优于后者。在任何时候,您都可以使用ref命名的完整形式来消除歧义

Git如何解释ref名称的血淋淋的细节在以下部分的“指定修订版”一节中进行了描述:

,例如硕士、校长/校长、参考生/校长/校长

一个符号化的ref名称。例如,master通常指由refs/heads/master引用的提交对象。如果您碰巧同时拥有heads/master和tags/master,那么可以显式地说heads/master来告诉git您指的是哪一个。当不明确时,通过在以下规则中进行第一个匹配来消除歧义:

如果$GIT_DIR/存在,这就是您的意思(这通常只对HEAD、FETCH_HEAD、ORIG_HEAD、MERGE_HEAD和CHERRY_PICK_HEAD有用)

否则,参考/如果存在

否则,引用/标记/如果存在

否则,引用/标题/如果存在

否则,引用/远程/如果存在

否则,refs/remotes//HEAD(如果存在)

我犯了一个类似的错误(创建了一个名为
origin/…
)的本地分支)

为了防止此类错误(并且假设您永远不会想要名称以
origin/
开头的本地分支),您可以在
repo/.git/refs/heads
中运行以下命令:

mklink /d remotes nul
mklink /d origin nul
mklink /d upstream nul
它们创建指向
nul
的符号链接,这将阻止在这些名称下创建子目录。现在,像
git分支原点/特征
这样的意外错误将给出一个错误:

unable to create directory for .git/refs/heads/origin/feature

这里没有必要使用GUI。你显然没有注意OP,如果他使用GUI而不是命令行,他不会坐在第一位。我不同意你的观点,git GUI可能有用,但首先重要的是要了解它在幕后是如何工作的。他必须了解自己到底做了什么,以及他不再犯了什么错误。欢迎你接受任何意见,但这并不能改变事实,即使用精致的视觉工具只会防止简单的混乱。对于极客来说,学习git所做的一切可能都很有趣,但对于日常用例来说,这根本不是必需的。包括但不限于导航分支。F