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

时间:2013-06-28 08:00:38

标签: git github

我还是相对较新的Git而且我的存储库有点混乱。我希望有一种方法可以修复它而无需重新克隆。

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

所以,我有:

$ 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分支?
  • 如何删除我创建的不需要的遥控器/ origin / abc 事故?

任何帮助都非常感激。

5 个答案:

答案 0 :(得分:19)

您不能创建两个具有相同名称的本地分支或两个远程分支。

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

  • 要确定哪个分支是哪个,您可以使用git branch显示本地分支,或使用git branch --remote显示远程分支。即使将git branch --all与分支语法着色(git config --global color.branch auto)一起使用,您也可以轻松区分它们。

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

答案 1 :(得分:6)

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

现在,当你告诉Git创建一个分支remotes/origin/abc时,它确实创建了refs/heads/remotes/origin/abc,它不会与refs/remotes/origin/abc发生冲突,因为处理该简化方案的规则使前者胜过后者。您可以随时使用完整形式的引用命名来消除任何歧义消除。

git-rev-parse manual的“指定修订”部分中描述了Git如何解释引用名称的详细信息:

  

< refname>,例如master,heads / master,refs / heads / master

     

符号引用名称。例如。 master通常表示refs / heads / master引用的commit对象。如果你碰巧有head / master和tags / master,你可以明确地说head / master告诉git你的意思。当含糊不清时,< refname>通过以下规则中的第一场比赛来消除歧义:

     

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

     

否则,refs /< refname>如果它存在;

     

否则,refs / tags /< refname>如果它存在;

     

否则,refs / heads /< refname>如果它存在;

     

否则,refs / remotes /< refname>如果它存在;

     

否则,refs / remotes /< refname> / HEAD(如果存在)。

     

...

答案 2 :(得分:1)

Git对分支名称的限制很少,例如分支名称中的斜杠非常好。同样删除遥控器上的分支也可以通过例如

完成
$ git push origin :abc

删除本地分支时,例如

$ git branch -d remotes/origin/abc

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

答案 3 :(得分:1)

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

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

mklink /d remotes nul
mklink /d origin nul
mklink /d upstream nul

它们创建到nul的符号链接,这将阻止在这些名称下创建子目录。现在,像git branch origin/feature这样的意外错误将产生错误:

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

答案 4 :(得分:-2)

使用gitkgitk --all检查分支机构。在那里你可以看到不同颜色的本地和远程分支。并且只需右键单击它们,即可轻松创建,签出,删除本地分支,而不会产生歧义。

对于远程跟踪分支,您可以使用git gui,创建分支菜单,只需选择远程分支和正确的本地命名理念。这样很难搞砸。

关于第一个问题:你不能真正创建具有相同名称的分支,但如果你为它而战,可能会发生看似相似的合成名称。使用适当的工具,他们不会混淆,所以没有理由禁止这种情况。