Git Internals

Especificaciones de Referencia (Refspec)

Especificaciones de Referencia (Refspec)

En Flujo Basico de Git y Flujos Remotos + Rebase vimos un poco de mapeados sencillos con ramas remotas, pero las cosas pueden ser bastante mas complejas. Cuando añades un remoto:

git remote add origin https://github.com/schacon/simplegit-progit

Git añade una nueva seccion a tu archivo .git/config con el nombre del remoto (origin), la URL del repositorio remoto y la referencia para recuperar (fetch) desde el:

[remote "origin"]
    url = https://github.com/schacon/simplegit-progit
    fetch = +refs/heads/*:refs/remotes/origin/* # Recuperar todas las ramas desde el servidor

El formato de esa linea de recuperacion es +<orig>:<dest>:

  • <orig> es la plantilla para referencias en el lado remoto.
  • <dest> es donde esas referencias se escribiran en el lado local.
  • El + indica a Git que debe actualizar la referencia incluso si no se trata de un fast-forward.

Por defecto, git remote add recupera todas las referencias bajo refs/heads/ y las escribe localmente en refs/remotes/origin/. Si existe una rama master en el servidor, puedes acceder a ella localmente a traves de cualquiera de estas formas, que son equivalentes:

git log origin/master
git log remotes/origin/master
git log refs/remotes/origin/master

Si quisieras que Git recupere unicamente la rama master y no cualquier otra rama del servidor remoto, puedes cambiar la linea de recuperacion a:

fetch = +refs/heads/master:refs/remotes/origin/master # Recuperar solo master del servidor

O si quisieras recuperar la rama master del servidor a una rama local mymaster:

git fetch origin master:refs/remotes/origin/mymaster

Tambien puedes indicar multiples referencias en un solo comando:

git fetch origin master:refs/remotes/origin/mymaster \
    topic:refs/remotes/origin/topic

O bien poner multiples lineas fetch en el archivo de configuracion, por ejemplo si siempre recuperas master y experiment

[remote "origin"]
    url = https://github.com/schacon/simplegit-progit
    fetch = +refs/heads/master:refs/remotes/origin/master
    fetch = +refs/heads/experiment:refs/remotes/origin/experiment

No puedes usar referencias genericas parciales en el patron. Algo como fetch = +refs/heads/qa*:refs/remotes/origin/qa* seria invalido. Para lograr algo similar, debes usar espacios de nombres.


Espacios de Nombres

Si tienes un equipo QA que envia al servidor una serie de ramas y deseas recuperar solo las de ese equipo sin mezclarlas con las del resto, puedes usar una seccion de configuracion como esta:

[remote "origin"]
    url = https://github.com/schacon/simplegit-progit
    fetch = +refs/heads/master:refs/remotes/origin/master
    fetch = +refs/heads/*:refs/remotes/origin/*
    fetch = +refs/heads/qa/*:refs/remotes/origin/qa/*

De esta forma puedes asignar facilmente espacios de nombres y resolver flujos de trabajo complejos cuando tengas multiples equipos colaborando en ramas remotas.


Enviando (Push) Referencias

Si alguien del equipo QA quiere enviar su rama master a la ubicacion qa/master en el servidor remoto:

git push origin master:refs/heads/qa/master

Para que esto ocurra automaticamente cada vez que ejecute git push origin, puedes añadir una entrada push al archivo de configuracion:

[remote "origin"]
    url = https://github.com/schacon/simplegit-progit
    fetch = +refs/heads/*:refs/remotes/origin/*
    push = refs/heads/master:refs/heads/qa/master

Esto hara que git push origin envie por defecto la rama local master a la rama remota qa/master.


Borrando Referencias

Las refspec tambien pueden usarse para borrar referencias en el servidor remoto:

git push origin :topic

Como el formato es <orig>:<dest> y se omite la parte <orig>, esto le dice a Git que envie nada al destino topic en el remoto, lo que efectivamente la elimina.


Recursos