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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17359978/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 16:26:53  来源:igfitidea点击:

Why has Git allowed me to create two branches with the same name?

gitgithub

提问by MrCrinkle

I'm still relatively new to Git and I have made a bit of a mess of my repository. I'm hoping there is a way to fix it without re-cloning.

我对 Git 还是比较陌生,而且我的存储库有点乱。我希望有一种方法可以在不重新克隆的情况下修复它。

I have a repository which I have cloned from Github. The repository has several branches. I worked on the master branch for a while but then needed to switch to one of the other branches.

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

So, I had:

所以,我有:

$ git branch --all
* master
  remotes/origin/abc
  remotes/origin/def
  remotes/origin/HEAD -> origin/master
  remotes/origin/ghi

Problem:I wanted to switch to the 'abc' branch but instead of doing git checkout remotes/origin/abcI accidentally did git branch remotes/origin/abcwhich leaves me with the following:

问题:我想切换到“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

My questions are:

我的问题是:

  • Why on Earth does Git allow you to create two branches with the same name?
  • How do I identify which is the real remotes/origin/abc branch?
  • How do I remove the unwanted remotes/origin/abc that I created by accident?
  • 为什么 Git 允许你创建两个同名的分支?
  • 如何识别哪个是真正的遥控器/起源/ abc 分支?
  • 如何删除我不小心创建的不需要的遥控器/来源/abc?

Any help much appreciated.

非常感谢任何帮助。

回答by aymericbeaumet

You can't create two local branches or two distant branches with the same name.

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

  • Here you have a local branch named remotes/origin/abcand a distant branch named abcon the remote origin. They have not the same name, but it seems to when you use the git branch --allcommand.

  • To identify which branch is which, you can show local branches with git branch, or show remote branches with git branch --remote. You could also easily differentiate them even while using git branch --allwith the branch syntax coloration (git config --global color.branch auto).

  • To remove the accidentally created local branch abc, you have to do git branch -d abc(or git branch -D abcto force deletion, see man git-branch).

  • 在这里,您有一个名为的本地分支remotes/origin/abc和一个名为abcremote 的远程分支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)。

回答by kostix

The true story is that Git has a simplification scheme for its "refs" (a Git lingo for "references", which is the term used to refer to branches, tags etc). In fact, references live in their namespaces, which, with the reference Git implementation, are just directories under .git. For instance, your local branch "master" is really "refs/heads/master" — a file named "master" located in the .git/refs/headsdirectory. There are also "refs/tags" namespace and "refs/remotes" namespace — for tags and remote branches (those created by the git fetchcommand).

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

Now when you tell Git to create a branch remotes/origin/abcit really creates refs/heads/remotes/origin/abcwhich does not clash with refs/remotes/origin/abcbecause the rules to deal with that simplification scheme make the former trump the latter. At any time you can use the full form of ref naming to remove any disambiguation.

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

The gory detals of how Git interprets ref names are described in the section "Specifying Revisions" of the git-rev-parsemanual:

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

<refname>, e.g. master, heads/master, refs/heads/master

A symbolic ref name. E.g. master typically means the commit object referenced by refs/heads/master. If you happen to have both heads/master and tags/master, you can explicitly say heads/master to tell git which one you mean. When ambiguous, a <refname> is disambiguated by taking the first match in the following rules:

If $GIT_DIR/<refname> exists, that is what you mean (this is usually useful only for HEAD, FETCH_HEAD, ORIG_HEAD, MERGE_HEAD and CHERRY_PICK_HEAD);

otherwise, refs/<refname> if it exists;

otherwise, refs/tags/<refname> if it exists;

otherwise, refs/heads/<refname> if it exists;

otherwise, refs/remotes/<refname> if it exists;

otherwise, refs/remotes/<refname>/HEAD if it exists.

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

符号引用名称。例如,master 通常是指由 refs/heads/master 引用的提交对象。如果你碰巧同时拥有 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 如果存在。

回答by Benjamin Bannier

Git places very little restriction on branch names and e.g. slashes in branch names are perfectly fine. Also deleting a branch on the remote is done with e.g.

Git 对分支名称的限制很少,例如分支名称中的斜线就完全没问题。还删除了远程上的分支,例如

$ git push origin :abc

while deleting a local branch is e.g.

删除本地分支时例如

$ git branch -d remotes/origin/abc

where there is no ambiguity because these two entities live in different namespaces.

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

回答by Balog Pal

Use gitkor gitk --allto inspect branches. There you can see local and remote branches with different color. And create, checkout, delete local branches with ease and without ambiguity just right-clicking on them.

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

For remote tracking branches you can use git gui, create branch menu, just pick the remote branch and the proper local naming idea. That way it is pretty hard to mess up.

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

As for the first question: you can't really create branches with same name, but similar-looking synthetized name can happen if you fight for it. With proper tools they are not confused, so there's no reason to forbid the scenario.

关于第一个问题:你不能真正创建同名的分支,但如果你争取它,就会出现看起来相似的合成名称。使用适当的工具,他们不会混淆,因此没有理由禁止这种情况。