Bifurcaciones y repositorios upstream: instrucciones y consejo interesante
Nicola Paolucci
Experto en desarrollo
Si bifurcas proyectos para hacer tus propios cambios, podrás integrar fácilmente tus contribuciones. Sin embargo, si no envías esos cambios en sentido ascendente —es decir, de vuelta al repositorio principal—, corres el riesgo de perderlos de vista, lo que puede provocar líneas divergentes en tu repositorio. Para asegurarte de que todos los colaboradores partan del mismo punto, necesitarás conocer algunos principios de cómo interactúa git fork con git upstream. En esta entrada, te presentaré los conceptos básicos, los trucos e incluso te daré un consejo genial para tomar la delantera.
git upstream: actualizar y contribuir
Vamos a comenzar detallando una configuración común y el flujo de trabajo más básico para interactuar con los repositorios upstream
.
En una configuración estándar, generalmente tienes un origin
y un remote
upstream; este último es el "guardián" del proyecto o la fuente de información a la que quieres contribuir.
Para empezar, comprueba que has configurado un remoto para el repositorio upstream
(y confío en que también un origin
):
git remote -v
origin git@bitbucket.org:my-user/some-project.git (fetch)
origin git@bitbucket.org:my-user/some-project.git (push)
Si no tienes un upstream
, puedes añadirlo fácilmente con el comando remote
:
git remote add upstream git@bitbucket.org:some-gatekeeper-maintainer/some-project.git
Material relacionado
Cómo mover un repositorio de Git completo
VER LA SOLUCIÓN
Aprende a usar Git con Bitbucket Cloud
Comprueba que el remoto se ha añadido correctamente:
git remote -v
origin git@bitbucket.org:my-user/some-project.git (fetch)
origin git@bitbucket.org:my-user/some-project.git (push)
upstream git@bitbucket.org:some-gatekeeper-maintainer/some-project.git (fetch)
upstream git@bitbucket.org:some-gatekeeper-maintainer/some-project.git (push)
Ahora puedes recopilar los últimos cambios del repositorio upstream
con fetch
. Repite esto cada vez que quieras recibir actualizaciones:
Si el proyecto tiene etiquetas que no se han fusionado en la main, también debes hacer: git fetch upstream --tags.
git fetch upstream
Por lo general, conviene que la rama main
local sea lo más parecida posible a la main
de upstream
y ejecutar el trabajo en las ramas de función, ya que más adelante podrían convertirse en solicitudes de incorporación de cambios.
En este punto, no importa si usas merge
o rebase
, ya que el resultado será normalmente el mismo. En este ejemplo, vamos a usar merge
:
git checkout main
git merge upstream/main
Cuando quieras compartir algo de trabajo con los mantenedores upstream
que ramificas desde main
, crea una rama de función. Cuando la tengas lista, envíala a tu repositorio remoto.
También puedes usar rebase
en su lugar y luego merge
para que el upstream
tenga un conjunto limpio de confirmaciones (lo ideal sería una) para evaluar:
git checkout -b feature-x
#some work and some commits happen
#some time passes
git fetch upstream
git rebase upstream/main
Publica con git fork
Una vez seguidos todos los pasos anteriores, publica tu trabajo en la bifurcación remota con un simple push
:
git push origin feature-x
git push -f origin feature-x
Personalmente, prefiero mantener el historial lo más limpio posible y optar por la tercera opción, pero cada equipo tiene su propio flujo de trabajo. Nota: Solo deberías hacer esto cuando trabajes con tu propia bifurcación. NUNCA deberías reescribir el historial de repositorios y ramas compartidos.
Consejo del día: indicación del número de confirmaciones por delante/detrás
Después de un fetch
, git status
muestra cuántas confirmaciones estás por delante o por detrás de la rama remote
sincronizada. ¿No estaría genial ver esta información en el símbolo del sistema? A mí también me lo pareció, así que empecé a toquetear bash
y lo conseguí.
Así es cómo se verá en el mensaje cuando lo hayas configurado:
nick-macbook-air:~/dev/projects/stash[1|94]$
Solo tendrías que añadir una función (una sola) a tu .bashrc
o equivalente:
function ahead_behind {
curr_branch=$(git rev-parse --abbrev-ref HEAD);
curr_remote=$(git config branch.$curr_branch.remote);
curr_merge_branch=$(git config branch.$curr_branch.merge | cut -d / -f 3);
git rev-list --left-right --count $curr_branch...$curr_remote/$curr_merge_branch | tr -s '\t' '|';
}
export PS1="\h:\w[\$(ahead_behind)]$"
Funcionamiento interno
Si te gusta tener todos los detalles, así es cómo funciona:
Obtenemos el nombre simbólico del HEAD actual, es decir, la rama actual:
curr_branch=$(git rev-parse --abbrev-ref HEAD);
Obtenemos el remoto al que apunta la rama actual:
curr_remote=$(git config branch.$curr_branch.remote);
Obtenemos la rama en la que se debe fusionar este remoto (con un truco de Unix para descartar todo hasta la última barra inclinada [ / ], inclusive):
curr_merge_branch=$(git config branch.$curr_branch.merge | cut -d / -f 3);
Ahora tenemos lo que necesitamos para recopilar el número de confirmaciones que estamos por delante o por detrás:
git rev-list --left-right --count $curr_branch...$curr_remote/$curr_merge_branch | tr -s '\t' '|';
Usamos el antiguo tr
Unix para convertir el TAB
en un separador |
.
Primeros pasos con git upstream
Este es un recorrido básico por git upstream
: cómo configurar un git upstream, crear una nueva rama, recopilar cambios, publicar con git fork y un consejo para saber a cuántas confirmaciones estás por delante o por detrás de la rama remota.
Bitbucket Data Center incluye sincronización de bifurcaciones que básicamente libera al desarrollador de la carga de actualizar las bifurcaciones. Además, Bitbucket Cloud tiene una sencilla sincronización en un solo paso, ¡échale un vistazo!
Compartir este artículo
Tema siguiente
Lecturas recomendadas
Consulta estos recursos para conocer los tipos de equipos de DevOps o para estar al tanto de las novedades sobre DevOps en Atlassian.