Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Control de Versiones - Guión
1. Guión charla control de versiones
Que controla un VCS
Un VCS controla las diferencias (deltas) entre versiones de un mismo fichero. Una versión
es una foto del contenido de un fichero. Ejemplo de cálculo de diferencias en una imagen:
Revisión 1 Revisión 2 delta
GIF: 62046 bytes GIF: 62591 bytes GIF: 8280 bytes
(también nos sirve para ganar muy rápido al “busca las 10 diferencias”)
A esta técnica se le llama delta-compression.
La idea de fondo es que si somos capaces de aplicar delta a la primera revisión,
obtendremos la segunda revisión.
Esto con ficheros de texto es trivial y en entornos Unix lo llevamos haciendo desde los 70
con los comandos diff y patch. Del concepto de patch (parche) se evolucionó hacia el
concepto de Control de Revisión y de aquellas barros, estos lodos.
Anécdota: hasta hace bien poco, la horda de “contributors” del kernel de linux mandaba
parches al mismísimo Linus Trovalds, quien los iba aplicando a mano en su copia local.
Estuvieron así durante años hasta que les dio por dominar el mundo con Git.
2. ¿VCS = backup?
¡NO!
Bueno, vale, es algo que se parece mucho a un backup, pero va mucho más allá. E
incluso, usarlo como backup es motivo suficiente para usar un VCS en cualquier proyecto.
El control de versiones, en definitiva, va de poder responder a estas
preguntas:
1. ¿Qué constituye una versión concreta de mi trabajo? ¿Cómo
puedo reproducir un determinado estado de cualquiera de las
versiones que he entregado?
2. ¿Quién ha hecho qué, cuándo y por qué? No solo es útil para
saber cuándo han ido mal las cosas, sino también para contar la
historia de tu producto.
(Traducido de Continuous Delivery, de Jef Humble y David Farley)
Además, resulta que tiene unos mecanismos excepcionales para permitir la colaboración
entre distintos “actores” en el marco de un proyecto.
Podemos editar el mismo fichero a la vez y nuestro VCS favorito se desvivirá por intentar
mezclar todos los cambios sin romper nada. Muchas veces lo consigue y otras, nos toca
arreglar “los líos de otros” (nunca los nuestros, eh?, que siempre hacemos los commits
bien).
Branching y merging: el comienzo del fin
Normalmente trabajaremos en la rama troncal o maestra de nuestro repositorio de CVS.
Cuando queremos desviar la evolución de nuestro desarrollo por un camino distinto,
hacemos un branch, o rama en inglés. A partir de ese momento, los deltas que el CVS
almacene para los ficheros de la rama irán por separado de los deltas de la rama
principal.
Cuando queremos que los deltas acumulados aisladamente dentro de una rama se
importen a la rama principal, hacemos un merge
A priori son funcionalidades que tienen muy buena pinta. Aislar una determinada vía de
desarrollo para una sola nueva funcionalidad y no ensuciar la rama principal... ¿Ensuciar?
Si para desarrollar algo nuevo vamos a ensuciar la rama principal, seguramente que
estamos haciendo algo mal.
3. En última instancia, según los autores de Continuous Delivery (que de esto saben un
huevo), todo commit al CVS debe constituir una pieza de producto entregable. Muchos de
los branchs que creamos para no mancillar la castidad de la rama principal, suelen
terminar conteniendo mucho código duplicado y cuanto más largo es su recorrido, más
difícil suele resultar la reincorporación del branch a la rama principal.
Por otro lado, si el branch no va a ser reincorporado al branch principal y no va a estar
activo indefinidamente, puede tener sentido prepararlo.
En cualquier caso, esta es solo mi opinión y os recomiendo experimentar y sacar vuestras
propias conclusiones.
Marcha atrás: la esquiva quimera
En el caso de que una entrega no llegue a buen puerto, el control de versiones nos puede
ayudar a recuperar un estado previo de nuestro proyecto.
Sin embargo, en un proyecto de cierta envergadura, resulta
complicado llevar una gestión tan exigente sobre el control de
versiones como para permitir el rollback a la versión anterior.
Aunque es posible hacerlo, muchas veces tendremos que
valorar su coste frente a otras alternativas menos elegantes
como el nunca suficientemente valorado backup previo o
mediante el despliegue de una nueva versión del proyecto que
corrija cualquier defecto detectado en la entrega. A veces la huida hacia delante es la
mejor opción.
Subversion para geeks
Mergeo parcial entre dos branches:
1) Nos movemos al punto en el que queremos mergear y obtenemos la ruta actual sobre
la que queremos mergear:
cerebro:/src/bar/chuchu/blabla cocotero$ svn info
Ruta: .
URL: http://foo.com/bar/trunk/chuchu/blabla
Raíz del repositorio: http://foo.com
UUID del repositorio: 4fda1d5b-c8f9-44cf-8ad8-48e2fb4af63b
...
(tomamos nota de la URL)
2) Ejecutamos un merge contra la misma ruta del branch rc4:
cerebro:/src/bar/chuchu/blabla cocotero$ svn merge http://foo.com/
bar/trunk/chuchu/blabla http://foo.com/bar/branches/rc4/chuchu/
blabla .
4. 3) Revisamos los cambios y hacemos commit de lo que haga falta.
Añadir y eliminar externals
cerebro:/src/bar/blabla cocotero$ svn propset svn:externals
“chuchu http://foo.com/bar/trunk/chuchu” vendor/.
Crea un external en vendor/chuchu que apunta al repo que indicamos
cerebro:/src/bar/blabla cocotero$ svn propdel svn:externals
vendor/.
Elimina cualquier external que pueda haber en vendor. Si necesitas borrar un external en
concreto, puedes usar el comando svn propedit svn:externals
Ignorar ficheros o directorios
cerebro:/src/bar/blabla cocotero$ echo “*” > .svnignore
cerebro:/src/bar/blabla cocotero$ svn add .svnignore
cerebro:/src/bar/blabla cocotero$ svn propset svn:ignore -
F .svnignore .
Ignoramos cualquier cosa dentro de blabla que no esté ya en nuestro repo
cerebro:/src/bar/blabla cocotero$ echo “cache” > .svnignore
cerebro:/src/bar/blabla cocotero$ svn add .svnignore
cerebro:/src/bar/blabla cocotero$ svn propset svn:ignore -
F .svnignore .
Ignoramos el fichero o directorio cache dentro de blabla
Git para humanos
Antes de empezar, diré que la clave es usar GitHub. Si usas GitHub unas semanas le
coges el tranquillo a Git sin problemas.
Rompiendo el modo centralizado
1) Crea un repo que sera el “maestro”
2) Te haces un fork del maestro para ti
cerebro:/src/ cocotero$ git clone git@github.com:ggalmazor/
BusinessLayer.git
3) Te añades al resto de contributors como origen
cerebro:/src/ cocotero$ git remote add ruben
git@github.com:regiluze/BusinessLayer.git
cerebro:/src/ cocotero$ git remote add mikel
git@github.com:mintxaus/BusinessLayer.git
5. 4) Te traes sus repos:
cerebro:/src/ cocotero$ git fetch ruben
cerebro:/src/ cocotero$ git fetch mikel
5) Premio:
cerebro:/src/ cocotero$ git branch -a
* master
remotes/mikel/master
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/ruben/master
Tienes todos sus branches en local :) Ahora puedes mergearte con ellos sin pasar por el
repo “maestro”.
Además de esto, podrás organizar mejor las aportaciones del equipo mediante pull-
requests.
Supervivencia 101: manual de etiqueta
Haz commits a menudo
El diámetro de la potencial cagada es proporcional al tamaño del commit. Tus
compañeros te lo agradecerán.
Trata de que 1 commit = 1 funcionalidad/historia de usuario/bug/ticket
Añade mensajes descriptivos
¡Hazlo siempre! No hay excusa.
Que la primera línea contenga un resumen del commit.
Que el resto de líneas sean el detalle.
Si usas Subversion y Trac añade un link al ticket que resuelves y para que
en el Trac salga un enlace al commit.
Si usas GitHub aprovecha para meter MarkDown y enlaza al issue relacionado con el
commit.
Si usas historias de usuario mete una referencia al código de la historia que resuelves.
Piensa en otras maneras de mejorar los mensajes de commit y ponlas en práctica.
Ten en cuenta que, con toda probabilidad, tus compañeros son unos psicópatas y que
saben dónde vives o, peor aún, los bares que frecuentas.
6. Rescepto a los commits ajenos
No pises los commits de los demás.
Evita hacer commits de ficheros que solo consistan en cambios de
indentación o líneas vacías. A no ser que pongan las llaves en la línea
siguiente. Si es así, tenéis mi permiso para arrasar.
Evita cambios en ficheros debidos a distintos encodings.
VCS != basurero
Usa la definición de ficheros y directorios ignorados de tu VCS.
No hagas commit de las carpetas que genera tu IDE para el
proyecto.
No hagas commit de las carpetas de la papelera de reciclaje o
los _DS_STORE
Convén con tus compañeros la estructura de directorios del
proyecto y respétala
Blame before you claim
Ante cualquier posible afrenta, usa el comando blame (o similar) de
tu VCS para ver quién ha sido el malhechor y cuales eran sus
verdaderas intenciones. En el mejor de los casos, estaban
corrigiendo una cagada tuya. En el peor, tendrás pruebas
irrefutables.
Resolución de conflictos
Si las opciones de tu VCS no son suficientes o no se te da bien el comando
de línea, usa alguna herramienta gráfica como Meld para aplicar los
cambios a mano. Eclipse incluye un editor de conflictos bastante majo y
SmartSVN también. ¿Git tiene alguna?
Por último: usa el comando de línea
Adquirir expertise con la shell es algo que revierte en muchas
ventajas, no solo para manejar un VCS. Los clientes gráficos suelen
ser pesados y solo pueden aportar alguna ventaja en operaciones
complejas de verdad. El comando de línea, al contrario, es todo lo
rápido que puede llegar a ser y los interfaces de usuario suelen estar
muy bien pensadas para sortear el handicap del “modo texto”.
Además, podrás fardar ante propios y ajenos con tu shell kungfu.
7. Centralizado y distribuido
Distribuido es cuando los participantes hacen checkin y checkout entre ellos. ¿El ejemplo
más conocido? Git
Centralizado es cuando los participantes hacen checkin y checkout de un repositorio
central. ¿El ejemplo más conocido? Git
¿Cuál es la diferencia? Los del centralizado no tienen más remedio.
Muchos estaréis usando Git como si de un VCS centralizado se tratara. ¿Usáis remotes
distintos que origin?
En el fondo, no importa demasiado si es centralizado o remoto. Mi percepción después de
6 años gestionando servidores Subversion y 1 con Git es que montar un Subversion está
chupado y que montar un Git no compensa existiendo servicios como GitHub.
Si alguien necesita instrucciones o ayuda para montar cualquiera de estos dos VCS le
puedo echar una mano o, al menos, ponerle en el buen camino.
8. Caso de uso: desarrollamos un Wordpress para un
cliente
Situación
Tenemos un que desarrollar y mantener un site con Wordpress. Además, tenemos que
añadir una serie de plugins y un tema que hemos desarrollado nosotros mismos.
Planteamiento
Creamos un repo para cada plugin de nuestra cosecha y para el tema que vamos a
implantar.
Creamos un repo para el Wordpress que vamos a entregar
Repo: Plugin
Contiene un único directorio tal y como se llamará cuando lo pongamos en la carpeta /wp-
content/plugins del Wordpress. Por ejemplo “cocotero_delux”. La estructura de directorios
básica va a contener los siguientes elementos:
cocotero_delux/
_sql/
README.md
En el fichero Readme.md guadaremos un registro de los cambios que le vamos haciendo
a las distintas releases y en el directorio sql deberíamos guardar un fichero schema.sql en
el que iríamos almacenando la estructura de datos completa de nuestro plugin. También
podríamos almacenar un fixtures.sql en el caso de que quisiéramos que nuestro plugin
tuviera algo de información de partida en dicha estructura y por cada release que nos
cambiara la estructura tendríamos un par de ficheros con alters para realizar el upgrade y
el downgrade sobre la base de datos de producción.
Repo: Theme
Al igual que con los plugins, contiene un único directorio donde ponemos los ficheros y
directorios de nuestro tema
Repo: Blog de nuestro cliente
Lo creamos y copiamos los ficheros de Wordpress en él. Hacemos commit y añadimos
nuestros plugins y nuestro tema como submódulos de Git con el comando git-remote.
En este caso no vamos a tener un directorio para los sql ya que es Wordpress quien se
encarga de los upgrades de base de datos.
De cara a las puestas en producción o las actualizaciones automágicas de Wordpress,
automatizaremos mediante un script la generación de un backup completo (¿idea para un
plugin?)