26 diciembre 2015

Manteniendo sicronizado un fork de Github con respecto al repositorio original

Estupendo, has solicitado tu primer pull request y te lo han aceptado junto con algunos otros pull requests de otros  desarrolladores, o puede ser que todavía estes trabajando en tu propia versión pero la original esté recibiendo actualizaciones que te convenga tener en tu fork. En ambos casos lo que te interesará es importar todos los commits recibidos por el fork original en el tuyo.

Borrar tu fork y reclonar el original no es una solución porque podrías tener código inacabado que perderías si borrases tu repositorio. Trabajar de esa manera es ineficiente y tendente a errores.


Hay otra manera mucho mejor que esa pero para ser sincero no es evidente si se mira el interfaz web de Github. El truco es importar los commits del repositorio original en la copia local de nuestro fork y acto seguido hacer un merge de los cambios en local para luego subirlo todo a Github con un push.

A primera vista podría parecer excesivamente complicado pero tiene sentido si consideramos nuestro repositorio de Github como el lugar donde debemos dejar nuestros cambios definitivos mientras que dejamos nuestra copia local como el lugar donde cacharrear.


Como dije antes, para hacerlo así no he encontrado ninguna manera evidente a través del interfaz web de Github. Incluso Pycharm carece de una de la de las funcionalidades que necesitamos para hacer todo el proceso a través del GUI, por lo cual tendremos que recurrir a la consola en algún paso. Por suerte todo el asunto se resuelve con sólo unos pocos comandos.

El primer paso supone añadir el repositorio original de Github como una fuente remota de nuestro repositorio local. Voy a mostrar cómo hacerlo usando mi fork de vdist. Este paso es precisamente el que no podemos hacer visualmente a través del GUI de Pycharm. Para ver qué fuentes tenemos en nuestro repositorio de Git tendremos que teclear el siguiente comando:

dante@Camelot:~/vdist$ git remote -v origin https://github.com/dante-signal31/vdist.git (fetch) origin https://github.com/dante-signal31/vdist.git (push)


Como se puede ver, llamo origin a mi fork en Github. Ahora vamos a añadir el repositorio original a mis fuentes de git. Digamos que queremos llamar upstream al repositorio original:

dante@Camelot:~/vdist$ git remote add upstream https://github.com/objectified/vdist.git dante@Camelot:~/vdist$ git remote -v origin https://github.com/dante-signal31/vdist.git (fetch) origin https://github.com/dante-signal31/vdist.git (push) upstream https://github.com/objectified/vdist.git (fetch) upstream https://github.com/objectified/vdist.git (push)

Se puede ver que el repositorio original se encuentra ahora entre las fuentes de mi repositorio local de git.

Para descargar cualquier cambio en el repositorio original sin aplicarlo en el repositorio local debemos usar el comando git fetch:

dante@Camelot:~/vdist$ git fetch upstream remote: Counting objects: 1, done. remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 1 De https://github.com/objectified/vdist * [new branch] master -> upstream/master

Se puede hacer este último paso desde el GUI de Pycharm usando la entrada de menu: "VCS-> Git-> Fetch".

Los cambios descargados se guardan por defecto en la rama upstream/master. Una vez revisados los cambios, y si se está de acuerdo con ellos, se pueden aplicar a la rama master local haciendo:

dante@Camelot:~/vdist$ git checkout master Switched to branch 'master' dante@Camelot:~/vdist$ git merge upstream/master


Con lo anterior la rama master local y la del repositorio original quedarán sincronizados.  Ahora, lo que quedaría por hacer es actualizar nuestro repositorio de Github con un push:

dante@Camelot:~/vdist$ git push origin master


La buena noticia es que sólo hay que añadir una vez el repositorio original a nuestras fuentes de git, tras lo cual se puede usar git como hasta el momento, incluso a través del interfaz de Pycharm, ya que este último detecta las nuevas ramas remotas en cuanto hacemos un fetch desde su menú.