2009-02-15 2 views
6

У меня есть файл журнала, хранящийся в базе данных SQLite, которую я хотел бы распространять в репозитории git.SQLite table with Git merging

Позже я хотел бы, чтобы изменения в файле журнала были автоматически списаны с оригиналом.

Будет ли это работать? Будет ли чаще всего бинарное слияние в SQLite-файл взорваться?

+1

Будет ли он действительно слияние? То есть будет ли файл изменяться по-разному на двух отдельных ветвях? –

ответ

6

Я не уверен, что git - это действительно инструмент для вашей работы. git - это инструмент управления распределенным исходным кодом, а не инструмент репликации базы данных.

Единственное автоматическое слияние, которое git будет пытаться, заключается в слиянии текстовых файлов. Файл журнала (обычно) представляет собой текстовый файл, поэтому почему бы не поместить его непосредственно в git, а не в базу данных?

+0

Спасибо за предложение. –

5

Я сомневаюсь, что любая система управления версиями (git, svn, cvs и т. Д.) Может обрабатывать базу данных описанными вами способами. Если вы настаиваете на использовании git для объединения баз данных, лучше всего конвертировать базу данных в текстовый файл, объединить текстовый файл и повторно создать базу данных. Например,

sqlite3 .dump > dump_file.txt 

может создать все SQL заявления, необходимые для повторного сделать базу данных, то вы делаете вещи в сбрасываемой файл, а затем сделать SQLite базу данных с

sqlite3 newdatabase.db < modified_dump_file.txt 

Вы должны быть в состоянии автоматизировать это с помощью какого-то git-крючка (я не слишком знаком с git).

1

Невозможно правильно объединить двоичные файлы в общем случае, поэтому git не может и не будет этого делать.

С некоторыми усилиями вы можете использовать git для дампов базы данных, но кроме очень простых случаев вам придется делать больше, чем просто использовать прямые дампы. Вам нужно будет подумать о том, как отсортированные строки сортируются на основе ваших ключевых столбцов, по крайней мере. Кроме того, вы получите ложные конфликты или слияния, которые производят синтаксически допустимые дампы, представляющие базу данных мусора.

F.ex., если разные версии строки с одним и тем же ключом отображаются в разных областях линии разных версий дампа, git может считать разумным сохранить их обоих. Результирующий дамп будет иметь два представления одной и той же строки, что является бессмыслицей.

Одним словом, вы, вероятно, будете недовольны попыткой сохранить версию базы данных с использованием системы управления версиями.

17

Вам необходимо определить пользовательские параметры слияния и разности в конфигурации git, а затем использовать атрибуты для связывания их с файлами.

Это просто простой слияние текста на свалки, поэтому он вполне может произвести полную бессмыслицу. Вам абсолютно необходимо проверить его работу, чтобы убедиться, что он сделал правильную вещь. Однако, несмотря на легкие слияния, нужно взять скуку.

В вашем .git/конфигурации:

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

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

в.gitattributes:

signons.sqlite diff=sqlite3 merge=sqlite3 

И где-то на своем пути, названный дифф-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]; 
} 

также на своем пути, названный слиянием 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]; 
} 

Я просто взломал их прямо сейчас, теперь, возможно, вам придется сгладить изломы.

см: http://git-scm.com/docs/gitattributes и http://git-scm.com/docs/git-config

+0

Это замечательно! Спасибо, @smoofra! Очень полезно! – lindes

1

Я переписана драйвер дифф выше в сценарии оболочки и обнаружили, что он не работает должным образом во всех случаях. Сценарий предполагает, что первые два параметра дают файлы различий, но в соответствии с man git заданными параметрами для сценария являются:

путь старого файла старого шестигранной старого режима нового файла нового шестигранной нового режима

Вот разница, что сделал это для меня:

#!/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

хотя этот вопрос был задан 8+ лет назад, я выпустил инструмент, который делает именно то, что вы просите. Он использует настраиваемый драйвер различий, используя инструмент sqlite project 'sqldiff', UUID в качестве первичных ключей и покидает sqlite rowid. Он по-прежнему находится в альфа, поэтому отзывы приветствуются.

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