2009-02-15 11 views
6

Tengo un archivo de registro almacenado en una base de datos SQLite que me gustaría distribuir en un repositorio git.Tabla SQLite con Git merging

Más tarde me gustaría que los cambios en el archivo de registro se combinen automáticamente con el original.

¿Esto va a funcionar? ¿Una combinación binaria automática en un archivo SQLite explotará más de las veces?

+1

será realmente una fusión? Es decir, ¿cambiará el archivo de forma diferente en dos ramas separadas? –

Respuesta

6

No estoy seguro de que git sea realmente la herramienta para su trabajo. git es una herramienta de administración de código fuente distribuida, no una herramienta de replicación de base de datos.

La única combinación automática que intentará git es fusionar archivos de texto. Un archivo de registro es (generalmente) un archivo de texto, entonces ¿por qué no poner esto directamente en git y no en una base de datos primero?

+0

Gracias por la sugerencia. –

5

Dudo que ningún sistema de control de versiones genérico (git, svn, cvs, etc.) pueda manejar la base de datos de la manera que usted describió. Si insiste en usar git para fusionar bases de datos, lo mejor que puede hacer es convertir la base de datos en un archivo de texto, combinar el archivo de texto y volver a crear la base de datos. Por ejemplo,

sqlite3 .dump > dump_file.txt 

puede crear todas las sentencias SQL necesarias para volver a hacer que la base de datos, a continuación, haces cosas para el archivo descargado, a continuación, hacer una base de datos SQLite con

sqlite3 newdatabase.db < modified_dump_file.txt 

Usted debe ser capaz de automatizar esto usando algún tipo de git hook (no estoy muy familiarizado con git).

1

No hay forma de combinar los archivos binarios correctamente en el caso general, por lo que git no puede y no lo hará.

Con algo de esfuerzo, puede usar git para descargar bases de datos de versiones, pero a excepción de casos muy simples, tendrá que hacer algo más que simplemente usar descargas directas. Tendrá que pensar en cómo las filas volcadas se ordenan en función de las columnas clave, como mínimo. De lo contrario, obtendrá conflictos espurios o fusiones que producen volcados sintácticamente válidos que representan una base de datos basura.

F.ex., si aparecen diferentes versiones de una fila con la misma clave en diferentes regiones de línea de diferentes versiones del volcado, git podría considerar razonable mantener ambas. El volcado resultante tendría dos representaciones de la misma fila, lo cual no tiene sentido.

En resumen, probablemente no esté contento de intentar mantener una base de datos versionada utilizando un sistema de control de origen.

17

Debe definir controladores de combinación y diferencia personalizados en su configuración de git, y luego usar atributos para asociarlos con los archivos.

Esto simplemente hace una simple combinación de texto en los volcados, por lo que podría muy bien producir una total tontería. Sin embargo, deberá verificar su trabajo para asegurarse de que hizo lo correcto. Sin embargo, debería eliminar el tedio de las fusiones fáciles.

En su .git/config:

[merge "sqlite3"] 
    name = sqlite3 merge driver 
    driver = merge-sqlite3 %O %A %B 

[diff "sqlite3"] 
    name = sqlite3 diff driver 
    command = diff-sqlite3 

en.gitattributes:

signons.sqlite diff=sqlite3 merge=sqlite3 

y en algún lugar en su camino, el nombre diff-SQLite3

#!/usr/bin/perl -w 

use File::Temp qw/ :POSIX /; 
use IPC::Run qw/run/ ; 

@ARGV == 7 or die sprintf 'wtf %s', join(' ', @ARGV); 

my ($name, $x, $y) = ($ARGV[0], $ARGV[1], $ARGV[4]); 

my ($a, $b); 

eval { 
    $a = tmpnam(); 
    $b = tmpnam(); 

    run ['sqlite3', $x, '.dump'], '>', $a or die 'sqlite3 failed'; 
    run ['sqlite3', $y, '.dump'], '>', $b or die 'sqlite3 failed'; 

    print "diff-sqlite3 a/$name b/$name\n"; 
    run ['diff', '-u', $a, $b, '--label', "a/$name", '--label', "b/$name"], '>', \*STDOUT; 

    unlink $a; 
    unlink $b; 
    1; 
} or do { 
    unlink $a if defined $a; 
    unlink $b if defined $b; 
    die [email protected]; 
} 

también en su camino, llamado fusión-sqlite3

#!/usr/bin/perl -w 

use File::Temp qw/ :POSIX /; 
use IPC::Run qw/run/ ; 

@ARGV == 3 or die sprintf 'wtf %s', join(' ', @ARGV); 

my ($o, $a, $b) = @ARGV; 

print "MERGEING SQLITE FILES $o $a $b\n"; 


eval { 
    $ad = tmpnam(); 
    $bd = tmpnam(); 
    $od = tmpnam(); 

    run ['sqlite3', $o, '.dump'], '>', $od or die 'sqlite3 failed'; 
    run ['sqlite3', $a, '.dump'], '>', $ad or die 'sqlite3 failed'; 
    run ['sqlite3', $b, '.dump'], '>', $bd or die 'sqlite3 failed'; 

    run ['merge', $ad, $od, $bd] or do { 
    my $newname = "$a.dump"; 
    my $n = 0; 
    while (-e $newname) { 
     ++$n; 
     $newname = "$a.dump.$n"; 
    } 
    print "merge failed, saving dump in $newname\n"; 
    rename $ad, $newname; 
    undef $ad; 
    die 'merge failed'; 
    }; 

    unlink $a or die $!; 
    my $err; 
    run ['sqlite3', $a], '>', \*STDOUT, '2>', \$err, '<', $ad; 
    if ('' ne $err) { 
    print STDERR $err; 
    die 'sqlite3 failed'; 
    } 

    unlink $ad if defined $ad; 
    unlink $bd; 
    unlink $od; 
    1; 
} or do { 
    unlink $ad if defined $ad; 
    unlink $bd if defined $bd; 
    unlink $od if defined $od; 

    die [email protected]; 
} 

acabo hackeado estos hasta ahora, ahora puedes tener que resolver los problemas.

ver: http://git-scm.com/docs/gitattributes y http://git-scm.com/docs/git-config

+0

Esto es genial! Gracias, @smoofra! ¡Muy útil! – lindes

1

I Reimplementado el conductor del diff anterior en la secuencia de comandos shell y se encontró que no funciona correctamente en todos los casos. La secuencia de comandos supone los dos primeros parámetros dan los archivos para diferenciar, pero de acuerdo con man git los parámetros dados a la secuencia de comandos son:

trayectoria pasada de archivo viejo-hex-viejo modo nuevo-nuevo archivo-hex nuevo modo

Aquí está el diff que lo hizo por mí: hace

#!/bin/sh 

FILE_PATH=$1 
OLD_FILE=$2 
OLD_HEX=$3 
OLD_MODE=$4 
NEW_FILE=$5 
NEW_HEX=$6 
NEW_MODE=$7 

A=`tempfile` 
B=`tempfile` 
test -f ${A} && test -f ${B} || exit 1 

sqlite3 ${OLD_FILE} .dump > ${A} && 
sqlite3 ${NEW_FILE} .dump > ${B} && 
diff -u ${A} ${B} --label "${FILE_PATH}@${OLD_HEX}" --label "${FILE_PATH}@${NEW_HEX}" 

rm ${A} 
rm ${B} 
2

años a pesar de que esta pregunta fue hecha 8+, he publicado una herramienta que hace exactamente lo que estás pidiendo. Utiliza un controlador de diferencias personalizado que aprovecha la herramienta de proyectos sqlite 'sqldiff', los UUID como claves principales y deja el sqlite rowid. Todavía está en alfa, por lo que se agradece la retroalimentación.

https://github.com/cannadayr/git-sqlite