Git
Sumario
- 1 Enlaces y referencias
- 2 Comentarios iniciales
- 3 Configuración
- 4 Hooks
- 5 Errores
- 6 Avisos
- 7 Recetario
- 7.1 Excluir archivos
- 7.2 Ignorar archivos residuales
- 7.3 Emplear un repositorio central
- 7.4 Crear un parche y enviarlo al autor
- 7.5 Importar un repositorio SubVersion
- 7.6 Provocando acciones
- 7.7 Páginas web en repositorios
- 7.8 Resolución de conflictos
- 7.9 Recuperando un archivo
- 7.10 Corrigiendo el registro de un cambio
- 7.11 Registros de cambios en paquetes Debian
- 7.12 Borrar un archivo sólo del repositorio
- 7.13 Configurar mensaje de registro de cambios
- 7.14 Ver registro de cambios en un archivo
- 7.15 Ver archivos implicados en un cambio
- 7.16 Seleccionando un editor para el registro
Enlaces y referencias
- Ref: Git en la wikipedia
- Ref: Wiki oficial de Git
- Ref: Git Community Book
- Ref: Stackoverflow: git for beginners, the definitive practical guide
- Ref: Tutorial de git (recetario) en español
Comentarios iniciales
Para todos los ejemplos presentes y futuros de esta página nos situaremos en dos máquinas, un servidor que conserva la copia central del repositorio y al que llamaremos [server] en un ataque de originalidad, y otra máquina que será la que contenga finalmente una copia de trabajo del repositorio, y que se llamará [desktop] siguiendo la misma tendencia.
¿ Por qué copia central del repositorio ? Dado que Git anima precisamente a lo contrario, ¿ por qué insistir en imitar el esquema CVS ? Pues porque desarrollo en solitario, tanto en casa como en mi trabajo, y como no suelo estar en los dos sitios al mismo tiempo necesito tener a mano siempre la última versión actualizada de los fuentes.
Configuración
El siguiente texto describe el uso que tienen algunas variables en la configuración de git. Para cambiar su valor se puede emplear el programa git config con el parámetro --global para que afecten a toda la configuración del usuario que lo emplee. El archivo en cuestión es ~/.gitconfig.
| Sección y variable | Descripción |
|---|---|
| user.name | Nombre completo del usuario para los registros de operaciones |
| user.email | Correo electrónico del usuario para lo mismo que el anterior. |
| core.excludesfile |
Archivo que contiene la lista de patrones de archivos que deben ignorarse a nivel de usuario cuando se gestiona un repositorio. Los patrones a nivel de repositorio se definen en el archivo |
| alias.nombre |
Define un alias (nombre) para un subprograma de Git de manera que sea más cómodo emplearlo y recordarlo. Ejemplos:
|
| sendemail.smtpserver | Máquina a la que conectarse para enviar un correo. |
| sendemail.aliasesfile | Archivo con los alias de correo específicos para el programa git-email. |
| sendemail.smtpuser | Usuario con el que conectarse al servidor de correo. |
| sendemail.smtppass | Contraseña para envío de correo. |
| sendemail.smtpssl | Habilita (true) el empleo de conexiones seguras cuando se envía correo. |
Ahora algunas aclaraciones puntuales más:
- sendemail.aliasesfile
- Este archivo está formado por líneas de texto con tres elementos cada una separados por espacios en blanco: la palabra clave alias, el nombre del alias y la dirección completa de correo electrónico como el siguiente ejemplo
alias yo victor@taquiones.net
Hooks
- Ref: Pro Git - Git Hooks
Git tiene la posibilidad de efectuar algunas acciones en respuesta a ciertos eventos en forma de programas especiales llamados hooks. Son de dos tipos atendiendo a dónde se emplean: en el lado del cliente y en el lado del servidor.
Errores
remote HEAD refers to nonexistent ref, unable to checkout
Si estamos intentando clonar un repositorio y aparece este mensaje, casi seguro que se trata de que, al crearlo, no hemos actualizado la información del servidor mediante:
[server] $ cd repositorio
[server] $ git update-server-info
y si es así, casi seguro que no hemos dado permisos de ejecución al programa de post-actualización:
[server] $ chmod u+x .git/hooks/post-update
refusing to update checked out branch: refs/heads/master
- Ref: Problema y soluciones en stackoverflow.com
- Ref: Repositorios desnudos
- Ref: What does git “updating currently checked out branch” warning mean?
Este error aparece cuando se intenta actualizar la rama actual sobre un repositorio non-bare, sobre todo a partir de loa versión 1.7 de Git, en la que ya no se avisa de esta circunstancia, sino que se rechaza la operación. Los repositorios de trabajo no deben recibir operaciones push.
Para arreglarlo, si es que por error tenemos un repositorio de trabajo como destino de nuestro árbol, es convertir éste en un directorio desnudo.
Suponiendo que el repositorio final en [server] se llamase almacen se podría hacer así:
[server] $ cd /var/lib/git
[server] $ git clone --bare almacen almacen-bare
Cloning into bare repository almacen-bare...
done.
[server] $ mv almacen almacen-non-bare
[server] $ mv almacen-bare almacen
[server] $ rm -rf almacen-non-bare
src refspec master does not match any
Este error aparece cuando -empleando un repositorio central- intento actualizar el lado remoto.
[client] $ git config remote.origin.url victor@server:git/myrepo [client] $ git push origin master error: src refspec master does not match any. fatal: The remote end hung up unexpectedly error: failed to push some refs to ...
Por lo visto se me olvidó añadirle cosas al repositorio local así que se arregla simplemente efectuando un commit y proporcionándole de esa forma algo que enviar al extremo remoto.
Avisos
commit message does not conform to UTF-8
Git espera que todos los mensajes estén en UTF-8 y cuando recibe un texto en otro juego de caracteres emite esta queja aunque llega a completar la tarea.
Para arreglarlo se puede cambiar la configuración e indicar cuál es el juego de caracteres que se emplea en el registro de cambios del repositorio:
$ git config --global --add i18n.commitencoding latin1
Recetario
Excluir archivos
- Ref: Git Community Book: ignoring files
- Ref: Stackoverflow: how do i tell git to ignore gitignore
- Ref: gitignore man page
Los repositorios Git disponen de un mecanismo para ignorar archivos cuando se intenta su inclusión en ellos, principalmente debido a operaciones sobre directorios completos o máscaras de archivos demasiado genéricas.
Este mecanismo consiste en una lista de patrones de nombres de archivos contra la que se comprueban los nuevos archivos a incluir (no los ya incluídos) y si coinciden se les ignora.
La lista puede incluirse en tres sitios dependiendo del alcance que queramos que tenga:
- Para todos los usuarios del repositorio
- Crear un archivo
.gitignorey mantenerlo bajo control del repositorio. - Sólo para la copia local del repositorio
- Añadir la lista de patrones al archivo
.git/info/excludedel repositorio. - Para todos los repositorios de tu máquina
- Crear un archivo con la lista de patrones, por ejemplo en
~/.gitglobalignore, y definirlo en la configuración del usuario en el archivo~/.gitconfigen la variable core.excludesfile = ~/.gitglobalignore.
Respecto a los archivos .gitignore anoto que:
- El ámbito del archivo cubre el directorio en el que residen y aquellos subdirectorios bajo él, hasta que encuentre otro archivo .gitignore que anule lo anterior.
- Estos archivos son comunes y por lo tanto deben ser manipulados como tal. Eso incluye añadirlos al repositorio (git add) y mantenerlos como cualquier otro (git commit -m " ... " .gitignore).
La lista de patrones tiene la siguiente síntaxis:
- Las líneas en blanco o comenzadas con una almohadilla (#) son ignoradas.
- El prefijo cierre de admiración (!) niega el patrón.
- Admite caracteres comodín.
- Si un patrón apunta a un nombre de directorio (terminando con una barra inclinada) se incluye el directorio y todo lo que está por debajo, pero no al mismo nivel a archivos regulares ni enlaces simbólicos.
- Una barra inclinada al comienzo de una expresión fija los archivos al comienzo de la ruta (relativa al repositorio) y no aplica el patrón en otros subdirectorios.
Ejemplo:
#
# Ignoramos copias de seguridad
*.bak
# y todo el directorio de salida de resultados
output/
# además de cualquier archivo de registro en
# el directorio raíz del repositorio
/*.log
Proyecto Perl
Relación de archivos residuales de un proyecto Perl:
*.bak *.orig *-stamp *.tar.gz Build _build blib
Paquete Debian
Para un paquete Debian los archivos ignorables son:
# Aplicable en el subdirectorio debian/ del repositorio /*.log /*.debhelper /*.substvars /files # Directorio temporal también en debian/ /tmp/
Ignorar archivos residuales
Como me he encontrado con esta situación un montón de veces, y hasta que adopte una solución más elegante, anoto aquí el contenido genérico del archivo .gitignore correspondiente a estos casos.
*.bak *.orig *-stamp *.tar.gz Build _build blib debian/files
y conviene incluir los resultantes según el nombre del paquete, como por ejemplo
debian/ikiwiki-plugin-hl*
Emplear un repositorio central
Con Git podemos trabajar de varias formas dado que se proporciona a cada copia clon la totalidad del repositorio, incluyendo el historial de cambios, y una de ellas es el estilo CVS en el que existe un repositorio central en el que terminan todos los cambios y desde el que parten todas las contribuciones, puesto que es la copia principal.
Si en un momento dado necesitamos que nuestro repositorio de trabajo sea una copia satélite de dicho repositorio central podemos hacer lo siguiente:
- Crear un repositorio vacío y desnudo (bare repository) en la localización central que aquí asumimos va a ser otra máquina.
[desktop] $ ssh victor@server "GIT_DIR=git/coco git-init --bare"
Initialized empty Git repository in /home/victor/git/coco/
- Cambiar el URL al que apunta nuestra copia local:
[desktop] $ cd git/adriano
[desktop] $ git config remote.origin.url victor@server:git/coco
Enviamos todo el repositorio al servidor central:
[desktop] $ git push origin master
Ahora podemos experimentar obteniendo copias desde el repositorio central, efectuando cambios y mezclándolos o no con el desarrollo principal, y/ó directamente borrando nuestra copia y transladándola a otra máquina.
Crear un parche y enviarlo al autor
Fue el propio Joey Hess el que me proporcionó, a petición mía, una guía simple para realizar esta tarea dado que me encargaba de las traducciones al español de IkiWiki.
- Creamos el parche
[desktop] $ git commit -a -m 'updated spanish translation'
[desktop] $ git format-patch HEAD^
0001-updated-spanish-translation.patch
- Enviamos el parche
[desktop] $ git send-email 0001-updated-spanish-translation.patch
Who should the emails appear to be from? [Víctor Moral <victor@taquiones.net>]
Emails will be sent from: Víctor Moral <victor@taquiones.net>
Who should the emails be sent to? author@ikiwiki
Message-ID to be used as In-Reply-To for the first email?
(mbox) Adding cc: =?utf-8?q?V=C3=ADctor=20Moral?= <victor@taquiones.net> from line 'From: =?utf-8?q?V=C3=ADctor=20Moral?= <victor@taquiones.net>'
OK. Log says:
Server: myserver.net
MAIL FROM:<victor@taquiones.net>
RCPT TO:<author@ikiwiki>,<victor@taquiones.net>
From: =?utf-8?q?V=C3=ADctor=20Moral?= <victor@taquiones.net>
To: author@ikiwiki
Cc: =?utf-8?q?V=C3=ADctor=20Moral?= <victor@taquiones.net>
Subject: [PATCH] updated spanish translation
Date: Wed, 22 Apr 2009 09:23:50 +0200
Message-Id: <1240385030-12089-1-git-send-email-victor@taquiones.net>
X-Mailer: git-send-email 1.6.2.3
Result: 250 OK id=1LwWoA-0006ZY-Ot
[desktop] $
Para ello antes tenemos que haber instalado y configurado correctamente el programa git send-email del paquete git-email. En la sección de configuración se detallan las variables necesarias bajo el prefijo sendemail.
Importar un repositorio SubVersion
El objetivo es conseguir en un directorio una copia Git de un repositorio subversion existente; dicha copia deberá estar limpia de particularidades del entorno subversion pero con su registro de cambios y lista de autores intacta.
Según la [http://www.simplisticcomplexity.com/2008/03/05/cleanly-migrate-your-subversion-repository-to-a-git-repository/ guía de Jon Maddox] se deben seguir los siguientes pasos:
- Instalar el correspondiente paquete git-svn.
[server] $ sudo apt-get install git-svn
- Crear un archivo de autores que permite establecer una relación entre los usuarios subversion y los usuarios Git.
[server] $ echo "victor = Victor Moral <victor@taquiones.net>" > users.txt
- Crear un directorio temporal y pasarse a él.
[server] $ mkdir adriano-tmp
[server] $ cd adriano-tmp
- Inicializar el repositorio:
[server] $ git-svn init svn+ssh://victor@venexma.net/var/lib/svn/adriano --no-metadata
cuidando de no incluir información específica de SVN, aunque sí el histórico
de cambios (commit log), mediante el parámetro --no-metadata.
- Definir en el repositorio el mapa de usuarios:
[server] $ git config svn.authorsfile ../users.txt
- Importar el contenido del repositorio:
[server] $ git-svn fetch
This may take a while on large repositories
A t/00.load.t
A t/perlcritic.t
A t/pod.t
A t/pod-coverage.t
.
.
.
r2524 = 8197e214cb753d146d1e6b205eeb7cc6cbb5a332 (git-svn)
M lib/Adriano.pm
r2527 = 0fab890c998ed8b670f435a28dfe91c066326bee (git-svn)
Checked out HEAD:
svn+ssh://victor@venexma.net/var/lib/svn/adriano r2527
[server] $
variando los detalles, naturalmente, ya que aquí en realidad estoy transcribiendo fragmentos de un proyecto antiguo que tengo por ahí.
- Verificar el resultado para quedarnos más tranquilos:
[server] $ git log
commit 0fab890c998ed8b670f435a28dfe91c066326bee
Author: Victor Moral <victor@taquiones.net>
Date: Fri Oct 10 11:01:42 2008 +0000
- Eliminada la dependencia y uso de variables de entorno.
commit 0fab890c998ed8b670f435a28dfe91c066326bee
Author: Victor Moral <victor@taquiones.net>
Date: Fri Oct 10 11:01:42 2008 +0000
- Eliminada la dependencia y uso de variables de entorno.
commit 8197e214cb753d146d1e6b205eeb7cc6cbb5a332
Author: Victor Moral <victor@taquiones.net>
Date: Thu Oct 9 13:35:22 2008 +0000
- Nueva versión para añadirle soporte a configuración externa vía YAML.
commit 48124296889fc73a3764deac735d41a9a70b9521
Author: Angel Ortega <angel@triptico.com>
Date: Tue Jul 24 10:41:52 2007 +0000
Referenciada Adriano::idfiscal desde la clase clientes_recientes.
...
[server] $
- Clonamos el repositorio importado de subversion en un directorio Git limpio (y
desnudo o bare puesto que lo vamos a emplear como base):
[server] $ cd ..
[server] $ git clone --bare adriano-tmp adriano
Initialized empty Git repository in /home/victor/git/adriano/.git/
[server] $
¿ Cuál es exactamente la diferencia entre uno y otro ? Bueno, a primera vista las diferencias son sobre todo en los orígenes. Si nos situamos en cada uno de ellos y pedimos un listado de la configuración podremos verlo mejor.
[server] $ cd adriano-tmp
[server] $ git-config --list
...
svn-remote.svn.nometadata=1
svn-remote.svn.url=svn+ssh://victor@venexma.net/var/lib/svn/adriano
svn-remote.svn.fetch=:refs/remotes/git-svn
...
[server] $ cd ../adriano
[server] $ git-config --list
...
remote.origin.url=/home/victor/git/adriano-tmp/.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
Lo siguiente es eliminar las referencias anteriores del repositorio, y para ello Bernhard Hartleb sugiere lo siguiente en un comentario de la guía anteriormente citada:
[server] $ cd
[server] $ rm -R adriano-tmp
[server] $ cd adriano
[server] $ git remote rm origin
Y para terminar preparamos una copia de trabajo en nuestra máquina habitual:
[desktop] $ git clone victor@server:git/adriano
Provocando acciones
- Ref: Git Tip: Auto update working tree via post-receive hook
- Ref: A web-focused Git Workflow
- Ref: Ikiwiki y git
Tenemos un repositorio en [server] donde estamos centralizando todos los elementos que construyen una página web y queremos que cada vez que se envíen cambios a dicho repositorio (operación push) se ejecuten unos programas y se actualice también dicha web.
Sabemos que no es bueno enviar cambios a un repositorio que tenga directorio de trabajo, y como tenemos que emplear los archivos para trabajar con ellos nos vemos en la necesidad de utilizar dos repositorios en [server]: uno desnudo (central) para centralizar cambios y otro con directorio de trabajo (working) que tendremos que tener sincronizados de alguna manera.
En realidad el segundo repositorio podría recrearse desde el principio cada vez que se actualizase el primero simplemente clonándolo
cd /tmp; git clone /var/lib/git/central working
pero esta técnica tiene la desventaja -entre otras- de ser costosa en tiempo de proceso y perder así bastante rendimiento según la página web crezca.
Primero creamos ambos repositorios en el servidor e indicamos que el segundo tiene al primero como remoto.
[server] $ mkdir /var/lib/git/central [server] $ cd /var/lib/git/central [server] $ git init --bare Initialized empty Git repository in /var/lib/git/central [server] $ cd /var/lib/git [server] $ git clone /var/lib/git/central working Initialized empty Git repository in /var/lib/git/working/.git/ warning: remote HEAD refers to nonexistent ref, unable to checkout. [server] $ cd working [server] $ git remote add central /var/lib/git/central [server] $
y luego añadimos un programa enganche para que cuando se complete un envío de cambios desde cualquier copia remota se ejecute alguna acción concreta. Este programa se pasará al directorio de trabajo del repositorio working, obtendrá los cambios desde el repositorio central y después ejecutará un programa para construir la web, o cualquier otra cosa que se necesite para ello.
Después clonamos el repositorio central en [desktop], efectuamos los trabajos normales de actualización de archivos, registramos los cambios y terminamos por enviarlos usando git push central. Los cambios se comprometerán en el repositorio remoto y al terminar ejecutará el programa -que hemos tenido que instalar allí directamente porque no podemos tener el directorio .git bajo control de sí mismo- que provocará la reconstrucción de las páginas web.
#!/bin/sh echo echo "**** building the web site " echo # Actualizar repositorio working cd /var/lib/git/working || exit unset GIT_DIR git pull central master # Construir la web make build # Actualizamos la información auxiliar en el servidor exec git-update-server-info
Debemos tener algunas cosas en cuenta con este tipo de programas ...
- que debe situarse dentro del directorio
/var/lib/git/central/hooks/bajo el nombre correspondiente al evento ante el que quiere reaccionar (post-update en este caso) y con los correspondientes permisos de ejecución. - que no existe un mecanismo de bloqueo en el programa y que actualizaciones concurrentes crearán ejecuciones concurrentes. Se debe comprobar este extremo e implementar una solución llegado el caso.
- que todos los canales de salida del programa (el estándar y el de errores) son reenviados mediante git-send-pack al otro extremo, por lo que cualquier cosa que se emita durante el proceso se recibe en el lado cliente.
- que siempre se pueden leer valores de la configuración del repositorio y de esta forma parametrizar su funcionamiento.
Páginas web en repositorios
Aunque el ejemplo anterior construye la página web con un paso intermedio (ejecutando un programa específico), también es posible tener un árbol de directorios bajo el control directo de un repositorio Git. En este caso situaríamos el repositorio con el árbol de trabajo en la raíz de documentos del servidor web para lo que tendremos que tomar algunas precauciones:
- La actualización de la web se realiza con el ID de usuario que efectúa la actualización del repositorio. Los archivos resultantes deben tener -al menos- permiso de lectura y paso al usuario del servidor web o en caso contrario no será posible servir su contenido.
- A menos que se retoque la configuración del servidor web todo el contenido del repositorio estará disponible para él.
También será conveniente que nos aseguremos de que el servidor web (Apache en mi caso) no permite el acceso a los datos internos del repositorio. Para ello tenemos varias opciones dentro de la configuración del servidor:
- Denegar el acceso al directorio directamente
<Directory /var/www/.git>
Deny from All
</Directory>
- Filtrar mediante una regla de reescritura:
RewriteEngine On RewriteRule \.git - [F,L]
- Restringir los permisos de acceso al directorio físico
[server] $ cd /var/www [server] $ chmod o-rx .git
Resolución de conflictos
- Ref: git-merge(1)
Cuando se actualiza un repositorio desde una localización remota puede ocurrir que algunos archivos contengan cambios dispares resultado de haberlos modificado tanto en el extremo local como en el remoto. Como git no puede discernir cuál es la versión correcta debe recurrir al usuario para que resuelva a mano.
En el ejemplo tenemos una actualización de un repositorio en la que ocurre ésto:
$ git pull remote: Counting objects: 5, done. remote: Compressing objects: 100% (3/3), done. remote: Total 3 (delta 2), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. From taquiones.net:git/config-misc 0e87bc3..646b4e5 master -> origin/master Auto-merging bash-profile CONFLICT (content): Merge conflict in bash-profile Automatic merge failed; fix conflicts and then commit the result.
y vemos que el archivo conflictivo tiene los siguientes añadidos:
...
# load normal environment
if [ -f ~/.environment ]; then
source ~/.environment
fi
# recover last screen session or create a new session
<<<<<<< HEAD
if [ "$SSH_CONNECTION" -a not -e ~/.dont-screen ]; then
=======
if [ "$SSH_CONNECTION" ]; then
>>>>>>> 646b4e5dd37377e2299613c6e605241ebb48812c
if [ -z "$STY" ]; then
exec screen -d -R
fi
fi
El texto en discusión se presenta acotado con marcas como <<<<<<<<, ====== y >>>>>. Normalmente el texto presente entre la línea <<<<<<<< y ====== representa el lado local mientras que lo que aparece entre ====== y >>>>> es lo que procede de la versión remota. Otra forma de ver las diferencias más sencilla es emplear git diff.
Para resolver este conflicto debemos hacer lo siguiente:
- Modificar el archivo en cuestión, eliminando las marcas de acotación y dejando una versión final aceptable.
- Añadirlo de nuevo al repositorio con
git add bash-profile. - Crear un commit con
git commit -aen el que podemos ver que el mensaje ya ha sido creado con los datos del conflicto.
$ git commit -a
[master 6da1509] Merge branch 'master' of taquiones.net:git/config-misc
$ git log -1
commit 6da15096d5d5db56955a6ff1586474b558889649
Merge: 0130126 646b4e5
Author: Víctor Moral <victor@taquiones.net>
Date: Mon Jun 27 14:02:47 2011 +0200
Merge branch 'master' of taquiones.net:git/config-misc
Conflicts:
bash-profile
Recuperando un archivo
Para recuperar un archivo desde una versión anterior se emplea la orden checkout con la ruta del archivo:
$ git checkout archivo $
Se puede emplear el parámetro -f para forzar la operación y se deberá indicar la rama si no es la última.
Corrigiendo el registro de un cambio
Si acabamos de hacer un cambio en el repositorio y nos equivocamos con el mensaje de registro podemos cambiarlo empleando el parámetro --amend de la orden commit.
$ git commit --amend -m "Nuevo mensaje"
Si necesitamos algo más complicado podemos reiniciar el último cambio, corregir los errores y volver a efectuarlo:
$ git reset --soft HEAD^ ... $ git commit -c ORIG_HEAD
Registros de cambios en paquetes Debian
- Ref: git-dch manual page
Cuando estamos empaquetando un programa para Debian nos podemos encontrar con que el registro de cambios debe mantenerse por duplicado ya que los mecanismos que los mantienen están separados. Existe un paquete llamado git-buildpackage que incluye útiles para estas situaciones. En concreto el programa git-dch sirve para crear y mantener el registro del paquete partiendo del registro del repositorio.
La recomendación es la siguiente:
- Emplear el etiquetado en el registro de cambios del repositorio; los autores sugieren el empleo de la expresión
debian/VERSION
para las etiquetas porque coincidiría con la versión del paquete a construir. - Antes de reconstruir el paquete sincronizar los registros desde la etiqueta que marca el comienzo de la nueva versión.
- Empaquetar y distribuir
Borrar un archivo sólo del repositorio
- Ref: Git: Remove a file from the repository without deleting it from the local filesystem
- Ref: git: how to remove sensitive data
Para borrar un archivo del repositorio pero conservar la copia física del mismo se emplea:
$ git rm --cached archivo rm 'archivo'
y a continuación conviene registrar el cambio y el por qué de esa decisión. Después conviene ignorar el archivo para que no vuelva a incluirse en el repositorio en un futuro si por error añadimos todo un directorio.
Configurar mensaje de registro de cambios
Al escribir el registro de un cambio en el repositorio podemos encontrarnos con que nos falta información sobre qué hemos cambiado exactamente. Empleando el parámetro --verbose de la orden git commit conseguiremos que la información sobre diferencias entre versiones se incluya al final del texto.
Un ejemplo sería:
- Añadido un título al archivo - Incluída una nota sobre cuál es el programa más importante de la sección. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: multibase/README # diff --git a/multibase/README b/multibase/README index bf67da3..15a3c15 100644 --- a/multibase/README +++ b/multibase/README @@ -1,4 +1,10 @@ +Notas sobre la sección multibase +================================ + Este documento contiene algunas notas sobre el paquete venexma-printers. Los scripts situados en el archivo de documentación deben ser transferidos al servidor de impresión done funciona Multibase. + +El principal de todos los programas es mb2cups + ~
Y aunque las diferencias no se incluyen comentadas el registro es lo bastante inteligente como para tomar únicamente la información relevante:
$ git log | head
commit 8fe78172efce46249df6f08c1857d4eb2f241b0a
Author: Víctor Moral <victor@taquiones.net>
Date: Tue Jan 3 14:47:00 2012 +0100
- Añadido un título al archivo
- Incluída una nota sobre cuál es el programa más importante de la sección.
commit 82de5d44a099e0f95cb712e6e2b3e48a44b82864
Author: Víctor Moral <victor@taquiones.net>
Date: Tue Jan 3 09:41:34 2012 +0100
$
Ver registro de cambios en un archivo
Usamos el siguiente truco:
$ git whatchanged -p archivo
Ver archivos implicados en un cambio
Para ver todos los archivos implicados en un cambio emplearemos el parámetro diff-tree o show:
$ git diff-tree --no-commit-id --name-only -r 0043d3621edb4833ed0c1fa91ebf2df6209e9ecd lib/Venexma/AEAT/Filter/DefaultAlfa.pm t/aeat-record-field.t t/email.t $
$ git show --pretty="format:" --name-only 0043d3621edb4833ed0c1fa91ebf2df6209e9ecd lib/Venexma/AEAT/Filter/DefaultAlfa.pm t/aeat-record-field.t t/email.t $
Si en el último quitamos el parámetro --name-only obtendremos también la lista de cambios completa
diff --git a/lib/Venexma/AEAT/Filter/DefaultAlfa.pm b/lib/Venexma/AEAT/Filter/DefaultAlfa.pm
index bd7f475..fff57a1 100644
--- a/lib/Venexma/AEAT/Filter/DefaultAlfa.pm
+++ b/lib/Venexma/AEAT/Filter/DefaultAlfa.pm
@@ -152,8 +152,8 @@ sub _accents_from_latin1 {
$text =~ s{($search)}{$replace}ge;
}
- $text =~ s{(\xd1)}{N}g;
- $text =~ s{(\xf1)}{n}g;
+ #$text =~ s{(\xd1)}{N}g;
+ #$text =~ s{(\xf1)}{n}g;
return $text;
}
diff --git a/t/aeat-record-field.t b/t/aeat-record-field.t
index d20c00f..25fb3fe 100644
--- a/t/aeat-record-field.t
+++ b/t/aeat-record-field.t
@@ -167,7 +167,8 @@ my @tests_alfanumeric = (
$obj = Venexma::AEAT::Record::Field->new( %alfa_params );
ok( $obj, sprintf("New alfanumeric field with %u characters",
$alfa_params{size} ));
-$filter->set_to_encode('utf8');
+$filter->set_from_encode('utf8');
+$filter->set_to_encode('iso8859-1');
$obj->set_filter( $filter );
foreach my $pair (@tests_alfanumeric) {
diff --git a/t/email.t b/t/email.t
index a6118d1..28c985f 100644
--- a/t/email.t
+++ b/t/email.t
@@ -54,6 +54,11 @@ done_testing;
sub _check_smtp {
my ($smtp, $port) = @_;
+ # Si no existe una variable de entorno cerrojo ignoramos los test
+ if (not exists $ENV{SEND_EMAIL}) {
+ return 0;
+ }
+
# Si no tenemos alguno de los dos valores
if (not defined $smtp or not defined $port) {
return diag("SMTP server or SMTP port not defined");
Seleccionando un editor para el registro
Git emplea un editor de texto para componer los registros de cambios antes de comprometerlos en el repositorio. En Linux normalmente usa el editor predeterminado pero es posible indicarle que use uno específico.
En la referencia de arriba se indica que se pueden emplear dos métodos para ello:
- Indicarlo en la variable de entorno GIT_EDITOR
- Definirlo en la configuración de git: ya sea de forma global (para la instalación) o local (para el repositorio)
$ git config --global core.editor "vim"
Si se quiere emplear la versión gráfica del editor es necesario indicarle que no haga un fork para que se pueda integrar en el ciclo de la operación commit. En este caso el editor vim se podría indicar así:
$ git config --global core.editor "vim -g --nofork"