== Git Multijugador ==

Inicialmente usaba Git en un proyecto privado donde yo era el único desarrollador.
Entre los comandos relacionados a la naturaleza distribuida de Git, sólo necesitaba *pull*
y *clone* así yo podía mantener el mismo proyecto en diferentes lugares.

Más tarde quise publicar mi código con Git, e incluir cambios de los
contribuyentes. Tuve que aprender a administrar proyectos con múltiples desarrolladores
de todo el mundo. Afortunadamente, esta es la fortaleza de Git, y podría decirse
que su razón de ser.

=== ¿Quién Soy Yo? ===

Cada commit tiene un nombre de autor y email, los cuales son mostrados por *git log*.
Por defecto, Git usa la configuración del sistema para rellenar estos campos.
Para decirle explícitamente, escribe:

  $ git config --global user.name "John Doe"
  $ git config --global user.email johndoe@ejemplo.com

Omite el parámetro *--global* si quieres que estas opciones sólo sean aplicadas en el repositorio actual.

=== Git Sobre SSH, HTTP ===

Supón que tienes acceso SSH a un servidor web, pero Git no está instalado. Aunque
es menos eficiente que su protocolo nativo, Git se puede comunicar por HTTP.

Descarga, compila e instala Git en tu cuenta, y crea un repositorio en
tu directorio web:

 $ GIT_DIR=proj.git git init
 $ cd proj.git
 $ git --bare update-server-info
 $ cp hooks/post-update.sample hooks/post-update

En versiones antiguas de Git, el comando cp falla y debes ejecutar:

 $ chmod a+x hooks/post-update

Ahora tú puedes publicar tus últimas ediciones via SSH desde cualquier clon:

 $ git push servidor.web:/ruta/al/proyecto.git master

y cualquiera puede obtener tu proyecto con:

 $ git clone http://servidor.web/proyecto.git

=== Git Sobre Cualquier Cosa ===

¿Quieres sincronizar repositorios sin servidores, o incluso sin conexión de red?
¿Necesitas improvisar durante una emergencia? Hemos visto cómo <<makinghistory, *git
fast-export* y *git fast-import* pueden convertir repositorios a un único archivo
y viceversa>>. Podríamos transportar tales archivos de ida y vuelta para enviar repositorios
git sobre cualquier medio, pero una herramienta más eficiente es *git bundle*.

El emisor crea un 'bundle' (paquete):

 $ git bundle create algunarchivo HEAD

Luego envía el paquete, +algunarchivo+, a la otra parte de alguna forma: email,
pendrive, una impresión *xxd* y un escáner OCR, leyendo bits a través del teléfono,
señales de humo, etc. El receptor recupera los commits del paquete escribiendo:

 $ git pull algunarchivo

El receptor puede incluso hacer esto desde un repositorio vacío. A pesar de su
tamaño, +algunarchivo+ contiene el repositorio git original completo.

En proyectos más grandes, elimina la basura empaquetando sólo los cambios de los que
carece el otro repositorio. Por ejemplo, supón que el commit ``1b6d...'' es el commit
más reciente compartido por ambas partes:

 $ git bundle create algunarchivo HEAD ^1b6d

Si se hace a menudo, uno puede olvidar fácilmente cual commit fue el último enviado. La
página de ayuda sugiere usar tags para resolver esto. Es decir, después de que envías un paquete,
escribe:

 $ git tag -f ultimopaquete HEAD

y crea nuevos paquetes de actualización con:

 $ git bundle create nuevopaquete HEAD ^ultimopaquete

=== Parches: La Moneda Global ===

Los parches son representaciones de texto de tus cambios que pueden ser fácilmente entendidos
por computadores y humanos por igual. Esto les da una calidad universal. Puedes enviar por email un
parche a los desarrolladores sin importar qué sistema de control de versiones estén usando. Mientras
tu audiencia pueda leer su email, ella puede ver tus ediciones. Similarmente, por tu
lado, todo lo que requieres es una cuenta de correo: no hay necesidad de crear un repositorio
Git en línea.

Recuerda del primer capítulo:

 $ git diff 1b6d > my.patch

obtiene un parche que puede se pegado en un email para discusión. En un
repositorio Git, escribe:

 $ git apply < my.patch

para aplicar el parche.

En un ambiente más formal, cuando los nombres de los autores y quizás las firmas deben
ser guardadas, genera los parches correspondientes pasados un cierto punto escribiendo:

 $ git format-patch 1b6d

Los archivos resultantes pueden ser enviados a *git-send-email*, o enviado a mano. También puedes
especificar un rango de commits:

 $ git format-patch 1b6d..HEAD^^

En el extremo receptor, guarda el mensaje a un archivo, luego escribe:

 $ git am < email.txt

Esto aplica el parche entrante y también crea el commit, incluyendo información tal como el autor.

Con un cliente de correo, puedes necesitar hacer clic en un botón para ver el mensaje en su forma
original antes de guardar el parche a un archivo.

Hay algunas ligeras diferencias para los clientes basados en casillas de correo, pero si tú usas
uno de esos, ¡eres probablemente la persona que puede deducirlo fácilmente sin leer tutoriales!

=== Lo Siento, Nos Hemos Movido ===

Después de clonar un repositorio, correr *git push* o *git pull* hará push hacia o 
pull desde la URL original. ¿Cómo Git hace esto? El secreto está en las opciones
de configuración creadas con el clone. Echemos un vistazo:

 $ git config --list

La opción +remote.origin.url+ controla la URL fuente; ``origin'' es un alias
dado al repositorio fuente. Al igual que con la convención de la rama ``master'', podemos
cambiar o borrar este alias, pero usualmente no hay razón para hacerlo.

Si el repositorio original se mueve, podemos actualizar la URL con:

 $ git config remote.origin.url git://nueva.url/proyecto.git

La opción +branch.master.merge+ especifica la rama remota por defecto en un
*git pull*. Durante la clonación inicial, se configura a la rama actual del repositorio
fuente, incluso si el HEAD del repositorio fuente se mueve posteriormente a
una rama diferente, más tarde un pull va a seguir fielmente la rama original.

Esta opción sólo se aplica al repositorio en la primera vez que se clona, que es
guardado en la opción +branch.master.remote+. Si tiramos desde otros repositorios
debemos decirle explícitamente que rama queremos:

 $ git pull git://example.com/other.git master

El ejemplo de más arriba explica por qué algunos de nuestros ejemplos anteriores
de push y pull no tenían argumentos.

=== Ramas Remotas ===

Cuando clonas un repositorio, también clonas todas sus ramas. Tú puedes no haber
notado esto porque Git los esconde: debes consultar por ellos específicamente.
Esto evita que las ramas en el repositorio remoto interfieran con tus ramas, 
y también hace a Git más fácil para los principiantes.

Lista las ramas remotas con:

 $ git branch -r

Deberías ver algo como esto:

 origin/HEAD
 origin/master
 origin/experimental

Estas representan ramas y el HEAD del repositorio remoto, y pueden ser usados
en los comandos regulares de Git. Por ejemplo, supón que has hecho muchos commits, y
deseas compararlos con la última versión traída. Tú podrías buscar en los registros (logs)
por el hash SHA1 adecuado, pero es mucho más fácil escribir:

 $ git diff origin/HEAD

O puedes ver lo que ha sucedido con la rama ``experimental'':

 $ git log origin/experimental

=== Múltiples Remotes ===

Supón que otros dos desarrolladores están trabajando en nuestro proyecto, y 
queremos mantener pestañas en ambos. Podemos seguir más de un repositorio a la vez con:

 $ git remote add otro git://ejemplo.com/algun_repositorio.git
 $ git pull otro alguna_rama

Ahora hemos mezclado una rama desde el segundo repositorio, y tenemos
acceso fácil a todas las ramas de todos los repositorios:

 $ git diff origin/experimental^ otro/alguna_rama~5

Pero, ¿qué pasa si queremos comparar sus cambios sin afectar nuestro propio trabajo?
En otras palabras, queremos examinar las ramas evitando que sus cambios invadan nuestro
directorio de trabajo. Entonces, en vez de pull, ejecuta:

 $ git fetch       # Recuperamos desde el origen, por defecto.
 $ git fetch otro  # Recuperamos lo del segundo programador.

Esto sólo obtiene historias. Aunque el directorio de trabajo permanece intacto,
podemos referirnos a cualquier rama de cualquier repositorio en un comando Git
ya que ahora poseemos una copia local.

Recuerda que detrás de las cámaras, un pull es simplemente un *fetch* luego 
*merge*. Usualmente hacemos *pull* porque queremos mezclar el último commit 
después de un fetch; esta situación es una excepción notable.

Vea *git help remote* para saber cómo remover repositorios, ignorar ciertas
ramas, y más.

=== Mis Preferencias ===

En mis proyectos, me gusta que los contribuyentes preparen los repositorios desde
los cuales voy a hacer pull. Algunos servicios de hosting Git te permiten hospedar
tu propia bifurcación de un proyecto con el clic de un botón.

Después de que obtengo un árbol, uso comandos Git para navegar y examinar los cambios,
los que idealmente están bien organizados y bien descritos. Mezclo mis propios cambios,
y quizás hago más ediciones. Una vez satisfecho, los empujo al repositorio principal.

Aunque rara vez recibo contribuciones, creo que este enfoque escala bien. Vea
http://torvalds-family.blogspot.com/ncr/2009/06/happiness-is-warm-scm.html[esta
entrada de blog por Linus Torvalds].

Permanecer en el mundo Git es ligeramente más conveniente que parchar archivos,
dado que me ahorra convertirlos a commits de Git. Además, Git maneja detalles como
grabar el nombre y dirección de email del autor, así como la hora y fecha, y
le pide al autor describir sus propios cambios.
