¿Por qué Git me permitió crear dos twigs con el mismo nombre?

Todavía soy relativamente nuevo en Git y he hecho un desastre en mi repository. Espero que haya una manera de solucionarlo sin volver a clonar.

Tengo un repository que he clonado de Github. El repository tiene varias twigs. Trabajé en la twig principal por un time, pero luego tuve que cambiar a una de las otras twigs.

Entonces, tuve:

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

Problema: quería cambiar a la twig 'abc', pero en lugar de hacer los git checkout remotes/origin/abc , accidentalmente hice git branch remotes/origin/abc que me deja con lo siguiente:

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

Mis preguntas son:

  • ¿Por qué en la Tierra Git te permite crear dos twigs con el mismo nombre?
  • ¿Cómo identifico cuál es la twig real de remotos / origen / abc?
  • ¿Cómo elimino los controles remotos / origen / abc no deseados que creé por crash?

Cualquier ayuda muy apreciada.

No puede crear dos twigs locales o dos twigs distantes con el mismo nombre.

  • Aquí tienes una twig local llamada remotes/origin/abc y una twig distante llamada abc en el origin remoto. No tienen el mismo nombre, pero parece cuando usas la git branch --all command.

  • Para identificar qué twig es cuál, puede mostrar las twigs locales con la git branch , o mostrar las twigs remotas con la git branch --remote . También podría diferenciarlos fácilmente incluso cuando usa git branch --all con la coloración de syntax de twig ( git config --global color.branch auto ).

  • Para eliminar el abc twig local creado accidentalmente, debe hacer git branch -d abc (o git branch -D abc para forzar la eliminación, ver man git-branch ).

La verdadera historia es que Git tiene un esquema de simplificación para sus "refs" (una jerga de Git para "references", que es el término utilizado para referirse a las twigs, tags, etc.). De hecho, las references viven en sus espacios de nombres, que, con la implementación de reference de Git, son solo directorys bajo .git . Por ejemplo, el "maestro" de su twig local es realmente "refs / heads / master" – un file llamado "master" ubicado en el .git/refs/heads . También hay espacio de nombres "refs / tags" y espacio de nombres "refs / remotes" para las tags y las twigs remotas (las creadas por el command git fetch ).

Ahora cuando le dices a Git que cree una twig de remotes/origin/abc realmente crea refs/heads/remotes/origin/abc que no entra en conflicto con refs/remotes/origin/abc porque las reglas para manejar ese esquema de simplificación hacen que triunfo de este último En cualquier momento, puede usar la forma completa de ref nominación para eliminar cualquier desambiguación.

Los sangrientos detalles de cómo Git interpreta los nombres de las references se describen en la sección "Especificación de revisiones" del manual de git-rev-parse :

<refname>, por ejemplo, master, heads / master, refs / heads / master

Un nombre de reference simbólico. Por ejemplo, maestro generalmente significa el object de compromiso referencedo por refs / heads / master. Si tienes ambos cabezales / maestro y tags / maestro, puedes decir explícitamente cabezas / maestro para decirle a quien te refieres. Cuando es ambiguo, se elimina la ambigüedad de un <refname> tomando la primera coincidencia en las siguientes reglas:

Si $ GIT_DIR / <refname> existe, eso es lo que quiere decir (esto suele ser útil solo para HEAD, FETCH_HEAD, ORIG_HEAD, MERGE_HEAD y CHERRY_PICK_HEAD);

de lo contrario, refs / <refname> si existe;

de lo contrario, refs / tags / <refname> si existe;

de lo contrario, refs / heads / <refname> si existe;

de lo contrario, refs / remotos / <refname> si existe;

de lo contrario, refs / remotes / <refname> / HEAD si existe.

Git coloca muy poca restricción en los nombres de las twigs y, por ejemplo, las barras en los nombres de las twigs están perfectamente bien. También eliminar una twig en el control remoto se hace con, por ejemplo,

 $ git push origin :abc 

mientras que eliminar una twig local es, por ejemplo

 $ git branch -d remotes/origin/abc 

donde no hay ambigüedad porque estas dos entidades viven en espacios de nombres diferentes.

Use gitk o gitk --all para inspeccionar las twigs. Allí puedes ver las sucursales locales y remotas con diferentes colors. Y cree, compruebe y elimine las sucursales locales con facilidad y sin ambigüedad simplemente haciendo clic derecho sobre ellas.

Para las sucursales de seguimiento remotas, puede usar git gui , crear un menu de bifurcación, solo elegir la sucursal remota y la idea de nomenclatura local adecuada. De esa forma es bastante difícil equivocarse.

En cuanto a la primera pregunta: realmente no se pueden crear twigs con el mismo nombre, pero un nombre sintético de aspecto similar puede suceder si luchas por ello. Con las herramientas adecuadas no están confundidos, por lo que no hay ninguna razón para prohibir el escenario.