-
1. Inicio - Sobre el Control de Versiones
-
2. Fundamentos de Git
-
3. Ramificaciones en Git
-
4. Git en el Servidor
- 4.1 Los Protocolos
- 4.2 Configurando Git en un servidor
- 4.3 Generando tu clave pública SSH
- 4.4 Configurando el servidor
- 4.5 El demonio Git
- 4.6 HTTP Inteligente
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Git en un alojamiento externo
- 4.10 Resumen
-
5. Git en entornos distribuidos
-
6. GitHub
-
7. Herramientas de Git
- 7.1 Revisión por selección
- 7.2 Organización interactiva
- 7.3 Guardado rápido y Limpieza
- 7.4 Firmando tu trabajo
- 7.5 Buscando
- 7.6 Reescribiendo la Historia
- 7.7 Reiniciar Desmitificado
- 7.8 Fusión Avanzada
- 7.9 Rerere
- 7.10 Haciendo debug con Git
- 7.11 Submódulos
- 7.12 Agrupaciones
- 7.13 Replace
- 7.14 Almacenamiento de credenciales
- 7.15 Resumen
-
8. Personalización de Git
-
9. Git y Otros Sistemas
- 9.1 Git como Cliente
- 9.2 Migración a Git
- 9.3 Resumen
-
10. Los entresijos internos de Git
-
A1. Apéndice A: Git en otros entornos
- A1.1 Interfaces gráficas
- A1.2 Git en Visual Studio
- A1.3 Git en Eclipse
- A1.4 Git con Bash
- A1.5 Git en Zsh
- A1.6 Git en Powershell
- A1.7 Resumen
-
A2. Apéndice B: Integrando Git en tus Aplicaciones
- A2.1 Git mediante Línea de Comandos
- A2.2 Libgit2
- A2.3 JGit
-
A3. Apéndice C: Comandos de Git
- A3.1 Configuración
- A3.2 Obtener y Crear Proyectos
- A3.3 Seguimiento Básico
- A3.4 Ramificar y Fusionar
- A3.5 Compartir y Actualizar Proyectos
- A3.6 Inspección y Comparación
- A3.7 Depuración
- A3.8 Parcheo
- A3.9 Correo Electrónico
- A3.10 Sistemas Externos
- A3.11 Administración
- A3.12 Comandos de Fontanería
3.5 Ramificaciones en Git - Ramas Remotas
Ramas Remotas
Las ramas remotas son referencias al estado de las ramas en tus repositorios remotos. Son ramas locales que no puedes mover; se mueven automáticamente cuando estableces comunicaciones en la red. Las ramas remotas funcionan como marcadores, para recordarte en qué estado se encontraban tus repositorios remotos la última vez que conectaste con ellos.
Suelen referenciarse como (remoto)/(rama)
.
Por ejemplo, si quieres saber cómo estaba la rama master
en el remoto origin
, puedes revisar la rama origin/master
.
O si estás trabajando en un problema con un compañero y este envía (push) una rama iss53
, tú tendrás tu propia rama de trabajo local iss53
; pero la rama en el servidor apuntará a la última confirmación (commit) en la rama origin/iss53
.
Esto puede ser un tanto confuso, pero intentemos aclararlo con un ejemplo.
Supongamos que tienes un servidor Git en tu red, en git.ourcompany.com
.
Si haces un clon desde ahí, Git automáticamente lo denominará origin
, traerá (pull) sus datos, creará un apuntador hacia donde esté en ese momento su rama master
y denominará la copia local origin/master
.
Git te proporcionará también tu propia rama master
, apuntando al mismo lugar que la rama master
de origin
; de manera que tengas donde trabajar.
Nota
|
“origin” no es especial
Así como la rama “master” no tiene ningún significado especial en Git, tampoco lo tiene “origin”. “master” es un nombre muy usado solo porque es el nombre por defecto que Git le da a la rama inicial cuando ejecutas |
Si haces algún trabajo en tu rama master
local, y al mismo tiempo, alguien más lleva (push) su trabajo al servidor git.ourcompany.com
, actualizando la rama master
de allí, te encontrarás con que ambos registros avanzan de forma diferente.
Además, mientras no tengas contacto con el servidor, tu apuntador a tu rama origin/master
no se moverá.
Para sincronizarte, puedes utilizar el comando git fetch origin
.
Este comando localiza en qué servidor está el origen (en este caso git.ourcompany.com
), recupera cualquier dato presente allí que tú no tengas, y actualiza tu base de datos local, moviendo tu rama origin/master
para que apunte a la posición más reciente.
git fetch
actualiza las referencias de tu remotoPara ilustrar mejor el caso de tener múltiples servidores y cómo van las ramas remotas para esos proyectos remotos, supongamos que tienes otro servidor Git; utilizado por uno de tus equipos sprint, solamente para desarrollo.
Este servidor se encuentra en git.team1.ourcompany.com
.
Puedes incluirlo como una nueva referencia remota a tu proyecto actual, mediante el comando git remote add
, tal y como vimos en [ch02-git-basics].
Puedes denominar teamone
a este remoto al asignarle este nombre a la URL.
Ahora, puedes usar el comando git fetch teamone
para recuperar todo el contenido del remoto teamone
que tú no tenías.
Debido a que dicho servidor es un subconjunto de los datos del servidor origin
que tienes actualmente, Git no recupera (fetch) ningún dato; simplemente prepara una rama remota llamada teamone/master
para apuntar a la confirmación (commit) que teamone
tiene en su rama master
.
teamone/master
Publicar
Cuando quieres compartir una rama con el resto del mundo, debes llevarla (push) a un remoto donde tengas permisos de escritura. Tus ramas locales no se sincronizan automáticamente con los remotos en los que escribes, sino que tienes que enviar (push) expresamente las ramas que desees compartir. De esta forma, puedes usar ramas privadas para el trabajo que no deseas compartir, llevando a un remoto tan solo aquellas partes que deseas aportar a los demás.
Si tienes una rama llamada serverfix
, con la que vas a trabajar en colaboración; puedes llevarla al remoto de la misma forma que llevaste tu primera rama.
Con el comando git push (remoto) (rama)
:
$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
* [new branch] serverfix -> serverfix
Esto es un atajo.
Git expande automáticamente el nombre de rama serverfix
a refs/heads/serverfix:refs/heads/serverfix
, que significa: “coge mi rama local serverfix
y actualiza con ella la rama serverfix
del remoto”.
Volveremos más tarde sobre el tema de refs/heads/
, viéndolo en detalle en [ch10-git-internals]; por ahora, puedes ignorarlo.
También puedes hacer git push origin serverfix:serverfix
, que hace lo mismo; es decir: “coge mi serverfix
y hazlo el serverfix
remoto”.
Puedes utilizar este último formato para llevar una rama local a una rama remota con un nombre distinto.
Si no quieres que se llame serverfix
en el remoto, puedes lanzar, por ejemplo, git push origin serverfix:awesomebranch
; para llevar tu rama serverfix
local a la rama awesomebranch
en el proyecto remoto.
Nota
|
No escribas tu contraseña todo el tiempo
Si utilizas una dirección URL con HTTPS para enviar datos, el servidor Git te preguntará tu usuario y contraseña para autenticarte. Por defecto, te pedirá esta información a través del terminal, para determinar si estás autorizado a enviar datos. Si no quieres escribir tu contraseña cada vez que haces un envío, puedes establecer un “cache de credenciales”. La manera más sencilla de hacerlo es estableciéndolo en memoria por unos minutos, lo que puedes lograr fácilmente al ejecutar Para más información sobre las distintas opciones de cache de credenciales, véase Almacenamiento de credenciales. |
La próxima vez que tus colaboradores recuperen desde el servidor, obtendrán bajo la rama remota origin/serverfix
una referencia a donde esté la versión de serverfix
en el servidor:
$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
* [new branch] serverfix -> origin/serverfix
Es importante destacar que cuando recuperas (fetch) nuevas ramas remotas, no obtienes automáticamente una copia local editable de las mismas.
En otras palabras, en este caso, no tienes una nueva rama serverfix
. Sino que únicamente tienes un puntero no editable a origin/serverfix
.
Para integrar (merge) esto en tu rama de trabajo actual, puedes usar el comando git merge origin/serverfix
.
Y si quieres tener tu propia rama serverfix
para trabajar, puedes crearla directamente basandote en la rama remota:
$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
Esto sí te da una rama local donde puedes trabajar, que comienza donde origin/serverfix
estaba en ese momento.
Hacer Seguimiento a las Ramas
Al activar (checkout) una rama local a partir de una rama remota, se crea automáticamente lo que podríamos denominar una “rama de seguimiento” (tracking branch).
Las ramas de seguimiento son ramas locales que tienen una relación directa con alguna rama remota.
Si estás en una rama de seguimiento y tecleas el comando git pull
, Git sabe de cuál servidor recuperar (fetch) y fusionar (merge) datos.
Cuando clonas un repositorio, este suele crear automáticamente una rama master
que hace seguimiento de origin/master
.
Sin embargo, puedes preparar otras ramas de seguimiento si deseas tener unas que sigan ramas de otros remotos o no seguir la rama master
.
El ejemplo más simple es el que acabas de ver al lanzar el comando git checkout -b [rama] [nombreremoto]/[rama]
.
Esta operación es tan común que git ofrece el parámetro --track
:
$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
Para preparar una rama local con un nombre distinto a la del remoto, puedes utilizar la primera versión con un nombre de rama local diferente:
$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch serverfix from origin.
Switched to a new branch 'sf'
Así, tu rama local sf
traerá (pull) información automáticamente desde origin/serverfix
.
Si ya tienes una rama local y quieres asignarla a una rama remota que acabas de traerte, o quieres cambiar la rama a la que le haces seguimiento, puedes usar en cualquier momento las opciones -u
o --set-upstream-to
del comando git branch
.
$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Nota
|
Atajo al upstream
Cuando tienes asignada una rama de seguimiento, puedes hacer referencia a ella mediante |
Si quieres ver las ramas de seguimiento que tienes asignadas, puedes usar la opción -vv
con git branch
. Esto listará tus ramas locales con más información, incluyendo a qué sigue cada rama y si tu rama local está por delante, por detrás o ambas.
$ git branch -vv
iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets
master 1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
testing 5ea463a trying something new
Aquí podemos ver que nuestra rama iss53
sigue origin/iss53
y está “ahead” (delante) por dos, es decir, que tenemos dos confirmaciones locales que no han sido enviadas al servidor.
También podemos ver que nuestra rama master
sigue a origin/master
y está actualizada.
Luego podemos ver que nuestra rama serverfix
sigue la rama server-fix-good
de nuestro servidor teamone
y que está tres cambios por delante (ahead) y uno por detrás (behind), lo que significa que existe una confirmación en el servidor que no hemos fusionado y que tenemos tres confirmaciones locales que no hemos enviado. Por último, podemos ver que nuestra rama testing
no sigue a ninguna rama remota.
Es importante destacar que estos números se refieren a la última vez que trajiste (fetch) datos de cada servidor. Este comando no se comunica con los servidores, solo te indica lo que sabe de ellos localmente. Si quieres tener los cambios por delante y por detrás actualizados, debes traértelos (fetch) de cada servidor antes de ejecutar el comando. Puedes hacerlo de esta manera: $ git fetch --all; git branch -vv
Traer y Fusionar
A pesar de que el comando git fetch
trae todos los cambios que no tienes del servidor, este no modifica tu directorio de trabajo.
Simplemente obtendrá los datos y dejará que tú mismo los fusiones.
Sin embargo, existe un comando llamado git pull
, el cuál básicamente hace git fetch
seguido por git merge
en la mayoría de los casos.
Si tienes una rama de seguimiento configurada como vimos en la última sección, bien sea asignándola explícitamente o creándola mediante los comandos clone
o checkout
, git pull
identificará a qué servidor y rama remota sigue tu rama actual, traerá los datos de dicho servidor e intentará fusionar dicha rama remota.
Normalmente es mejor usar los comandos fetch
y merge
de manera explícita pues la magia de git pull
puede resultar confusa.
Eliminar Ramas Remotas
Imagina que ya has terminado con una rama remota, es decir, tanto tú como tus colaboradores habéis completado una determinada funcionalidad y la habéis incorporado (merge) a la rama master
en el remoto (o donde quiera que tengáis la rama de código estable).
Puedes borrar la rama remota utilizando la opción --delete
de git push
.
Por ejemplo, si quieres borrar la rama serverfix
del servidor, puedes utilizar:
$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
- [deleted] serverfix
Básicamente, lo que hace es eliminar el apuntador del servidor. El servidor Git suele mantener los datos por un tiempo hasta que el recolector de basura se ejecute, de manera que si la has borrado accidentalmente, suele ser fácil recuperarla.