miércoles, 18 de enero de 2012

Sincronización con RSync

RSync es una herramienta para Unix que permite sincronizar una carpeta con otra (remota o no) o como los autores especifican en la man page: "a fast, versatile, remote (and local) file-copying tool".


Los casos de uso son variados según la necesidad, por ejemplo, tenemos una copia local de archivos fuente de un proyecto web, deseamos publicar las modificaciones en el servidor de producción. Este sería el más común (por lo menos en mi caso) de los escenarios.




La carpeta src dentro del server A (o pc de trabajo) puede tener archivos que no se necesiten subir, o carpetas que no debe porque matchear contra la que está en el servidor B, todo esto lo resuelve el rsync según la configuración utilizada.


Como dije antes, es un comando de Unix, es por esto que tenemos la ventaja de usar "la bash" para generar un script completo complejo  que nos permita realizar muchas tareas.


Especificación del comando
rsync {opciones} {conexión} {origen} {destino}


Opciones

  • -v, --verbose               Extender info
  • -q, --quiet                 Suprimir información que no sean errores
  • -c, --checksum              utilizar solo el checksum para evaluar la comparación de archivos
  • -a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)
  • -r, --recursive             recursivo dentro de directorios
  • -b, --backup                realizar un backup (ver --suffix & --backup-dir)
  •     --backup-dir=DIR        realizar backup dentro de DIR
  •     --suffix=SUFFIX         backup suffix (default ~ w/o --backup-dir)
  • -p, --perms                 preservar permissions
  • -E, --executability         preservar executability
  • -o, --owner                 preservar owner (super-user only)
  • -g, --group                 preservar group
  • -t, --times                 preservar modification times
  • -n, --dry-run               Realizar una corrida en seco, excelente para poder probar si lo que hacemos es lo que necesitamos.
  • -z, --compress              comprimir durante la transferencia
  •     --compress-level=NUM    compression level
  • -f, --filter=RULE           Necesario al momento de realizar exclusiones (por ejemplo, carpetas .svn, archivos .project, etc)
  •     --exclude=PATTERN       matching PATTERN
  •     --exclude-from=FILE     Desde un archivo "FILE"
  •     --include=PATTERN       inverso al exclude
  •     --include-from=FILE     inverso exclude-from
  •     --files-from=FILE       inverso files-from
  • -h, --human-readable        En formato legible por humanos
  •     --progress              Mostrar el progreso (esto genera mucha suciedad al momento de ver el log)
  • -4, --ipv4                  preferir uso de IPv4
  • -6, --ipv6                  preferir uso de IPv6
  •     --delete                borrar archivos del destino que no macheen
Yo particularmente utilizo la configuración: -avz con eso basta para transferir los archivos de una carpeta a otra.

Script para bash:

#!/bin/bash
HOME=/home/usuario/carpeta/src/
DEST=/var/www/sitio/src/
rsync -avz --delete --exclude=.svn --exclude=Thumbs.db  $HOME $DEST
echo "Done"

En los casos donde deba copiar por ssh al servidor de destino:

#!/bin/bash
HOME=/home/usuario/carpeta/src/
DEST=usuario@ip_destino_o_direccion:/var/www/sitio/src/
rsync -avz --delete --exclude=.svn --exclude=Thumbs.db  $HOME $DEST
echo "Done"

Luego podemos combinar opciones del ssh (como por ejemplo obtener el password para conectarse desde un archivo) para incrementar los usos de ambas herramientas según nuestra necesidad.

viernes, 6 de enero de 2012

1 - Control de Versiones GIT

Este post no intenta explicar las ventajas y desventajas que tiene el sistema de versionado de GIT sino que intenta resumir los comandos más usados en la vida diaria de un programador.

Un breve resumen de comandos
Estos son los comandos utilizados en esta sección

  • git config
  • git clone
  • git status
  • git add
  • git commit
  • git rm
  • git mv
  • git log
Recordamos los tres estados de un archivo en GIT
  • Committed: La información del archivo esta almacenada en forma segura en la database local.
  • Modified: El archivo sufrió cambios locales pero no fue "comiteado" hasta el momento.
  • Staged: Se ha marcado el archivo como modificado y pronto para el commit de la próxima snapshoot.
Configuraciones en GIT
Git trabaja en principio con 3 archivos que manejan gran parte de la configuración.
  • /etc/gitconfig: Contiene los valores de todos los usuarios y todos los repositorios; para acceder a este recurso se hace git config --system (lectura y escritura)
  • ~/.gitconfig file: Contiene la información del usuario local; se accede con git config --global. 
  • .git/config: especifica la información particular de ese repositorio.

Cada nivel sobrescribe la configuración del anterior, por lo que el .git/config sobrescribe los que están en  /etc/gitconfig.

Configurar quien soy yo
Lo primero que debemos hacer una vez instalado GIT (sudo apt-get install git) es setear quien somos; esto lo hacemos con el comando git config --global para no tener que hacerlo nuevamente (notar el --global):

git config --global user.name "Juan Perez"
git config --global user.email "juan.perez@email.com"

Configuración de herramientas
Lo básico, el editor y el diff tool.

git config --global core.editor vim
git config --global merge.tool vimdiff
Una (extensa) lista de opciones se puede encontrar haciendo git config --help; un resumen del seteo de opciones se puede encontrar haciendo git config --list o en su defecto si solo se quiere cierta propiedad, se hace git config user.name


Hacer un checkout clone de un repo existente
Para eso tan solo necesitamos tener la url del repo y hacer un git clone
git clone git://github.com/schacon/grit.git
Nótese que el protocolo es git, también se puede hacer bajo un protocolo https o ssh si el repo lo permite:
git clone https://github.com/schacon/grit.git
user@server:/path/to/git/repository.git

Viendo el status de los archivos
Mediante el git status podemos acceder a la lista de estado de los archivos (o como aparece en la documentación, "show the working tree status"), recordamos que los archivos pueden estar versionados traked o no traked; a su vez, aquellos que estén bajo el versionado, pueden estar sin modificación, modificado o en staged.
Si ejecutamos un git status en el repo recién clonado deberíamos obtener:
$ git status
# On branch master
nothing to commit (working directory clean)
Nótese que al final nos dice bajo que branch estamos trabajando, en este caso como es un repo recientemente clonado, nos indica que estamos en el branch master.

Versionando los archivos
Esto se realiza mediante un simple git add {archivo, lista de archivos, expresión regular} esto nos marca al archivo como pronto para ser agregado, o mejor aún, nos indica que el archivo está en "stage" y que esta pronto para ser "comiteado"

Modificando archivos
Suponiendo un escenario donde tenemos un archivo no versionado y uno versionado pero modificado, podemos ver la siguiente salida después de ejecutar un git status.


$ git status

# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
# new file:   README
#
# Changed but not updated:
#   (use "git add ..." to update what will be committed)
#
# modified:   some_file.txt
#
Aquí se deben apreciar dos cosas; primero, vemos que el archivo nuevo no traked esta bajo el grupo "Changes to be committed" eso significa que el archivo no está traked pero si esta pronto para ser agregado en el caso que sea necesario. En segundo lugar vemos que bajo el grupo "Changed but not updated" está el archivo modificado localmente, esto implica que el archivo fue modificado localmente pero no fue puesto en "stage" por el momento. Para agregarlo en el stage debejos ejecutar git add {archivo, lista, exp. regular} .
$ git add some_file.txt
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
# new file:   README
# modified:   some_file.txt
#
Ahora ambos archivos están en "stage" prontos para hacer commit. Un punto importante aquí es que si nosotros modificamos nuevamente algún archivo, éste será vuelto a pertenecer al grupo de "Changed but not updated" pero a su vez estaría perteneciendo al grupo "Changes to be committed". Aquí hay un par de bifurcaciones, si hacemos git commit, se fijaran los cambios con el archivo tal cual estaba luego de hacer el primer git add omitiendo los últimos cambios realizados. Por el contrario, si deseamos agregar los últimos cambios debemos volver a ejecutar git add del archivo antes de hacer el git commit. 

Ciclo de estados de un archivo en GIT
Imagen extraída de: http://progit.org/book/ch2-2.html
Committing los cambios
Una vez agregado todos los archivos al stage, estamos prontos para hacer el commit, lo mejor es hacer git commit -m "comentario" si la opción -m no es incluída, el editor seteado se abrirá para ingresar el comentario, lo cual es un poco molesto.
Existe otra opción para el commit que permite "saltearse" el paso de stage, esto es mediante el comando:
git commit -a -m "Commit sin hacer add"
Esto agrega los archivos y les hace commit todo en un solo paso.

Remover archivos
Mediante el comando git rm se pueden borrar archivos del versionado (en realidad lo saca del stage) y una vez que se haga commit ya no pertenecerá a la estructura del repo local. Si necesitáramos remover un archivo que está trakeado pero no queremos que lo borre del disco (algún archivo de configuración del ide por ejemplo) lo podemos hacer mediante el comando git rm --cached.
Nota: casi todos los comando permiten la identificación de un archivo, una lista de archivos o una expresión regular, esto por ejemplo nos permite git rm logs_folder/\*.log que sería eliminar todos los archivos .log dentro de la carpeta logs_folder.

Mover archivos
Para mover archivos es uno de los sistemas más sencillos que existen, tal cual en unix, basta ejecutar git mv old_file new_file una vez hecho esto, el nuevo archivo figurará como modificado y estará bajo el grupo de "Changes to be committed".

Historia de los commit
El comando git log provee una amplia gama para ver los logs de un repo, recordar que al clonar uno, éste baja todos los logs junto con los arhcivos por lo que no necesita ir al servidor a buscarlo para mostrarlo y esto redunda en una rapidez importante.


  • git log --graph - muestra el log como un grafo
  • git log --reverse - invierte la salida del log
  • git log -4 - limita la salida a n logs
  • git log --since={--since, --after, --until, --before} {2.weeks, "2008-10-10", etc}
  • git log --author=User - Que el autor coincida con User.
  • git log --committer=User - Que el committer coincida con User.
  • git log --help
  • git log -p - muestra el diff de cada commit
  • git log --stat - muestra la lista de archivos modificados en cada commit
  • git log --pretty=OPCION - muestra el output de según la forma predefinida

    Opciones
  • oneline - muestra cada commit (comentario del) en una sola línea
  • short - la salida pero resumida
  • full
  • fuller
  • format: "%h - %an, %ar : %s"

    Etiquetas de formateo

  • %H - Commit hash
  • %h - Abbreviated commit hash
  • %T - Tree hash
  • %t - Abbreviated tree hash
  • %P - Parent hashes
  • %p - Abbreviated parent hashes
  • %an - Author name
  • %ae - Author e-mail
  • %ad - Author date (format respects the –date= option)
  • %ar  - Author date, relative
  • %cn  - Committer name
  • %ce  - Committer email
  • %cd  - Committer date
  • %cr - Committer date, relative
  • %s - Subject
Para los amantes de log viewer gráficos existe la herramienta gitk que provee las funcionalidades de forma más amigable.

Fuentes: la mayor parte de la información es un resumen de ProGIT y de Git In The Trenches