Clonar la Wiki de un proyecto «forkeado» en GitHub

GitHub es una plataforma increíble que hace todo más fácil en la gestión de proyectos versionados con Git. Una de las grandes cosas que tiene GitHub es la de hacer un fork, que es una copia vinculada al repositorio original bajo tu completa administración.

Esta copia no es completa, puesto que no incluye algunas cosas relevantes como la Wiki, que es donde se documenta la información del proyecto. A efectos prácticos la Wiki se comporta exactamente igual que un repositorio gestionado con Git y que se compuesto por ficheros markdown. A mi juicio, el hacer un fork del proyecto debería incluir tanto el repositorio principal del proyecto como el repositorio Wiki del mismo. Quizás en un futuro no muy lejano lo veamos, quién sabe... 😉

Cuando hacemos un fork de un proyecto y vamos a la Wiki nos anima a crear nuestra primera página:

Aunque pudiera parece que al haber una sección Wiki, existe un repositorio, esto no es así. Hasta que no creemos la primera página que suele denominarse "Home", el repositorio de la Wiki no existirá. Si se intenta hacer push al repositorio, seguramente os arroje un error como este:

remote error: access denied or repository not exported

Esto es un error de falta de permisos que puede hacerte perder bastante el tiempo, si no caes en la cuenta que el error no es por falta de permisos, sino por la ausencia de repositorio.

Una vez aclarado el tema basta con darle a "Create the first page":

Dejaremos tal cual está todo porque sobrescribiremos el contenido, sólo lo hacemos para que se cree el repositorio de la Wiki. Avanzamos hacia abajo y le damos a "Save Page".

Ahora tenemos nuestra Wiki inicializada con su reapositorio activo:

Una vez llegados a este punto hay dos formas de hacer las cosas. En la primera de ellas, puede que la más fácil, sea hacer un clone del repositorio Wiki del original, hacer otro clone de nuestro repositorio Wiki en el fork, y copiar todos los archivos del repositorio Wiki original al de nuestro fork. De esta forma al hacer commit y luego push en nuestro repositorio, tendremos la Wiki. El mayor problema de este método es que primero vamos a tener un commit inicial y que luego vamos a tener un segundo con toda la Wiki. Esto nos hace perder el versionado que traía consigo el repositorio Wiki del proyecto original.

Otra forma más óptima que nos permite mantener el versionado del repositorio Wiki del proyecto original, es el que paso a describiros a continuación de manera detallada.

Primero hacemos un "git clone" del repositorio Wiki del proyecto original:

git clone url_wiki_original

Una vez clonado añadimos nuestra Wiki del fork como remoto con "git remote" (no usar como "remote_name" el nombre de origin):

git remote add remote_name url_wiki_fork

Ahora con el nuevo remoto añadido podemos hacer un "git push" forzado:

git push remote_name master --force

El parámetro "remote_name" es el mismo que cuando hemos añadido el remote en el paso anterior (el de la Wiki de nuestro fork), la rama es "master" (rama principal pero que puede ser cualquier otra que se quiera), y el parámetro "--force" que sirve para sobrescribir la referencia que tuviese anteriormente de la rama y sobrescribir por la que se manda (cuidado con este parámetro que puede resultar peligroso).

El resultado como podéis ver es la de nuestra Wiki actualizada con la del proyecto original:

Ahora queda un minúsculo detalle y es el "HEAD", la referencia que indica cual es remote y rama por defecto. Por defecto apunta a "origin/master", que es el remoto de donde se hace el clone. Por esta razón hay que cambiar el "HEAD" para que apunte a nuestro fork como origin y a nuestra rama master. La manera más sencilla es coger y hacernos un "git clone" del repositorio Wiki de nuestro fork y todo listo. 😉

Con este procedimiento ya podéis incluir en vuestros forks la tan preciada y a veces escasa documentación  que se adjunta en los repositorios de los proyectos.

Crear y Eliminar un Submódulo Git de un Proyecto

Una de las formas más eficientes de gestionar la adhesión de subproyectos y librerías en Git, es mediante el uso de submódulos que nos permiten trabajar con ellos dentro de un proyecto, o de manera desacoplada con cada submódulo como si fuera un repositorio Git.

La creación de un submódulo dentro de un proyecto se limita a ejecutar el siguiente comando dentro del directorio deseado en el que se quiera añadir el submódulo, dentro de la raíz del proyecto:

git submodule add http://porject-url

Donde la URL después del comando "add" indica la localización del proyecto Git que queremos montar como submódulo.

Una vez tengamos el submódulo añadido podemos gestionarlo como si fuera un proyecto Git independiente, moviéndonos hasta la raíz del submódulo, o ejecutar comandos en lote sobre los submódulos de un proyecto.

Si deseas clonar el repositorio e incluir en el clonado los submódulos, deberás hacer un clone recursivo:

git clone --recursive http://porject-url

Donde deberás especificar la URL del proyecto.

Si no realizas el clonado recursivo, del proyecto deberás realizar una inicialización manual de los submódulos:

git submodule init
git submodule update

Por otro, lado, igual que es interesante crear un submódulo dentro del un proyecto, lo es también eliminar un submódulo de un proyecto. Por ejemplo porque queramos moverlo de sitio o porque queramos prescindir de él. Para ello os explicaré la forma de hacerlo borrando el repositorio, que puede servir para conseguir ambos objetivos.

Escontrándonos en la raíz del proyecto que contiene el submódulo que queremos borrar ejecutamos los siguientes comandos:

# Desinicializamos el submódulo de la lista de submódulos
git submodule deinit path/submodule
# Borramos físicamente el directorio del submódulo
git rm path/submodule
# Eliminar cache del árbol de trabajo de Git
git rm --cached path/submodule
# Eliminamos la meta información del submódulo que por alguna razón no borra Git
rm -rf .git/modules/path/submodule

Con las sucesión de comandos detallados, desvincularás totalmente el submódulo deseado y eliminarás los archivos innecesarios.

De esta forma queda cubierta la gestión de submódulos Git en su carácter más esencial, siendo una herramienta muy potente a la hora de gestionar las dependencias de un proyecto, y a la vez facilitando la actualización de las mismas.

Feliz Navidad y Próspero Año 2017

Simple RFC1738 Encoder – Codificación de una URL

La Informática e Internet es una piña de estándares que muchas veces a los desarrolladores nos son transparentes. Esto provoca que habitualmente no nos formulemos la pregunta de cómo se codifica, se procesa y se manda una dato, ya que existen funciones de alto nivel que nos resuelven dicha problemática o simplemente se realiza de manera transparente al desarrollador mediante un Framework o Librería.

¿Alguna vez te has preguntado cómo se codifican los caracteres que escribes? La verdad es que esto de la informática nació en los Estados Unidos y su Silicon Valley. Esto hace obvio que las codificaciones se pensaron para el inglés.

Con el tiempo la informática se extendió hasta su uso normalizado que tenemos hoy en día. El problema que tuvimos los de habla latina era que la codificación de base era UTF-8 y no incluía nuestros caracteres latinos, tales como: tildes, signos de exclamación e interrogación en la apertura, letra ñ ... para caracteres codificados con 1 byte. Esto hacía necesario usar 2 bytes para codificar los caracteres latinos, ya que con 1 byte los caracteres incluidos son los de US-ASCII, subconjunto con un total de 128 caracteres correspondientes a las primeras posiciones de la tabla ASCII (American Standard Code for Information Interchange).

UTF-8 es un formato de codificación de caracteres Unicode e ISO-10646. La necesidad de usar 2 bytes para codificar caracteres latinos hace que la codificación en términos de consumo de espacio sea mayor, siendo necesario usar el doble de espacio (16 bits) si estamos codificando en algún idioma con caracteres latinos. A tal efecto se creó ISO-8859 y la derivación concreta ISO-8859-1 que es la norma de la ISO que define la codificación del alfabeto latino, incluyendo los diacríticos (como letras acentuadas, ñ, ç), y letras especiales (como ß, Ø). Esta codificación permite que dichos caracteres latinos se codifiquen en 8 bits, permitiendo la codificación del rango de los 128 primeros caracteres de la tabla ASCII y otros 128 caracteres más para lo que se denomina el conjunto de códigos extendidos de la tabla extendida ASCII. Puedes echarle un ojo a dicha tabla en:

https://github.com/RDCH106/Simple-RFC1738-Encoder#ascii-code---the-extended-ascii-table

Esta introducción que espero que haya servido para aclarar ciertos conceptos, sirve como base para la segunda parte que paso a explicar en las siguientes líneas.

Una forma habitual de pasar información en peticiones HTTP, es mediante el uso de encolado de parámetros en la URL (Uniform Resource Locator). Esto nos permite comunicarnos con APIs de otros servicios y a la vez es la base de las APIs RESTful como la que presentaba en la entrada "Linkero – Creación de APIs RESTful en Python".

Obviamente de nuevo tenemos una especificación para codificar las URLs que es la RFC-1738 de 1994 creada por Tim Berners-Lee, el inventor de World Wide Web. Dicha especificación define que sólo un reducido conjunto de caracteres puede usarse en las URLs, los cuales son:

  • A to Z (ABCDEFGHIJKLMNOPQRSTUVWXYZ)
  • a to z (abcdefghijklmnopqrstuvwxyz)
  • 0 to 9 (0123456789)
  • $ (Dollar Sign)
  • - (Hyphen / Dash)
  • _ (Underscore)
  • . (Period)
  • + (Plus sign)
  • ! (Exclamation / Bang)
  • * (Asterisk / Star)
  • ' (Single Quote)
  • ( (Open Bracket)
  • ) (Closing Bracket)

Para mapear el amplio rango de caracteres utilizados en todo el mundo en los 60 caracteres permitidos en una URL, se utiliza un proceso estándar de dos pasos:

  • Conversión de la cadena de caracteres, en una secuencia de bytes utilizando la codificación UTF-8.
  • Conversión de cada byte que no sea una letra o dígito ASCII a% HH, donde HH es el valor hexadecimal del byte.

Por ejemplo, la cadena: "Rubén", sería codificada como: "Rub%C3%A9n"

Este es el proceso que de manera estándar se usa y que puedes encontrar en funciones como encodeURI en Javascript o urlencode en PHP. Pero esto no quiere decir que no puedas usar ISO-8859 como codificación base y luego codificar la URL con RFC-1738, consiguiendo de esta forma trabajar sobre una base de caracteres que permite ciertos caracteres, que aunque se puedan codificar en UTF-8, resultan ilegibles. Por ejemplo, la cadena: "Rubén", sería codificada como: "Rubén". No se entiende, ¿verdad?

El uso de UTF-8 nos obliga siempre a codificar dos veces, mientras que si se asume la codificación  ISO-8859, sólo es necesario aplicar la RFC-1738. Veis por donde voy, ¿no? UTF-8 es un estándar que nos penaliza por no ceñirse nuestra grafía de las letras de nuestro alfabeto al conjunto de caracteres ingleses. A pesar de que podamos codificarlo luego de nuevo, se antoja un paso prescindible si directamente se asume ISO-8859 en cualquiera de sus variantes como base de codificación de los caracteres. En mi caso la ISO-8859-1. De esta forma la codificación con RFC-1738 queda con un único valor hexadecimal (perteneciente a la tabla ASCII extendida) para los caracteres ilegibles codificados con UTF-8. Esto además genera URLs más cortas al no tener que usar dos conjuntos de hexadecimales para un único caracter. Por ejemplo, la cadena: "Rubén", sería codificada como: "Rub%E9n".

Esta problemática me llevó a desarrollar Simple RFC1738 Encoder, al cual podéis acceder a su código desde la dirección del proyecto:

https://github.com/RDCH106/Simple-RFC1738-Encoder

En el proyecto se explica de manera más resumida lo presentado en esta entrada y se ofrece la posibilidad de probar la librería desde:

https://rawgit.com/RDCH106/Simple-RFC1738-Encoder/master/demo.html

En la demo se pueden probar los distintos ejemplos de codificación presentados durante la entrada como son la codificación UTF-8 y la codificación RFC-1738 con o sin UTF-8 como codificación base. Podéis comprobar los resultados con las tablas facilitadas en el README del proyecto:

https://github.com/RDCH106/Simple-RFC1738-Encoder/blob/master/README.md

El proyecto Simple RFC1738 Encoder pretende ofrecer la capacidad de codificar las URLs usando RFC-1738 pero sin la necesidad de codificar con UTF-8 como base, pudiendo usar cualquier otra codificación como las recogidas en ISO-8859.