Почему Git разрешил мне создать две ветки с тем же именем?

Я по-прежнему относительно новичок в 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?
  • Как удалить нежелательные удаленные файлы /origin/abc, которые я создал авария?

Любая помощь очень ценится.

Ответ 1

Вы не можете создать две локальные ветки или две отдаленные ветки с тем же именем.

  • Здесь у вас есть локальная ветвь с именем 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).

Ответ 2

Истинная история состоит в том, что Git имеет схему упрощения для своих "refs" (a Git lingo для "ссылок", которая является термином, используемым для обозначения ветвей, тегов и т.д.). Фактически, ссылки живут в своих пространствах имен, которые с помощью ссылки 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, потому что правила для работы с этой схемой упрощения делают прежний козырь последним. В любое время вы можете использовать полную форму именования для удаления любых значений.

Очерки о том, как Git интерпретирует имена ссылок, описаны в разделе "Указание ревизий" руководства git-rev-parse:

<refname> мастер, головки/мастер, refs/heads/master

Символическое имя ссылки. Например. master обычно означает объект фиксации, на который ссылаются refs/heads/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, если он существует.

& hellip;

Ответ 3

Git помещает очень мало ограничений на имена ветвей и, например, слэши в названиях веток отлично. Также удаление ветки на пульте дистанционного управления выполняется, например,

$ git push origin :abc

при удалении локальной ветки, например,

$ git branch -d remotes/origin/abc

где нет двусмысленности, поскольку эти два объекта живут в разных пространствах имен.

Ответ 4

Используйте gitk или gitk --all для проверки ветвей. Там вы можете видеть локальные и удаленные ветки разного цвета. И создавайте, проверяйте, удаляйте локальные ветки с легкостью и без двусмысленности, просто щелкая правой кнопкой мыши по ним.

Для удаленных ветвей отслеживания вы можете использовать git gui, создать меню ветки, просто выбрать удаленную ветку и соответствующую идею локального наименования. Таким образом, это довольно сложно испортить.

Что касается первого вопроса: вы не можете создавать ветки с тем же именем, но подобное синтетическое имя может произойти, если вы будете бороться за него. С помощью правильных инструментов они не путаются, поэтому нет причин запрещать сценарий.