2009-02-15 56 views
6

我有一個日誌文件存儲在SQLite數據庫,我想分佈在一個Git倉庫。與Git合併SQLite表

後來我想改變日誌文件自動與原來的合併。

這是否正常工作?自動二進制文件合併成一個SQLite文件會不會更頻繁?

+1

它真要合併?也就是說,文件在兩個獨立的分支上會有不同的變化嗎? – 2009-02-15 09:32:58

回答

6

我不相信git真的是你工作的工具。 git是一個分佈式源代碼管理工具,而不是數據庫複製工具。

git將嘗試的唯一自動合併是合併文本文件。日誌文件通常是一個文本文件,爲什麼不直接把它直接放到git中,而是先放到數據庫中呢?

+0

感謝您的建議。 – 2009-02-15 09:57:09

5

我懷疑任何通用版本控制系統(git,svn,cvs等)都可以用你描述的方式處理數據庫。如果你堅持使用git來合併數據庫,最好的辦法是將數據庫轉換爲文本文件,合併文本文件並重新創建數據庫。例如,

sqlite3 .dump > dump_file.txt 

可以建立必要的所有SQL語句重新使數據庫,那麼你做的東西到轉儲文件,然後做一個SQLite數據庫與

sqlite3 newdatabase.db < modified_dump_file.txt 

您應該能夠使用某種類型的git hook來自動執行此操作(我對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 
在你的路徑

而且某處,一個名爲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]; 
} 

也是在你的路徑,命名合併-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/gitattributeshttp://git-scm.com/docs/git-config

+0

這太棒了!謝謝@smoofra!很有幫助! – lindes 2012-05-17 14:45:49

1

我在shell腳本重新實現上面的差異驅動程序,發現它並非在所有情況下正常工作。腳本假設前兩個參數給出的文件差異,但根據man git給腳本的參數是:

路徑舊文件舊六角舊模式的新文件新六角新模式

下面是爲我做的DIFF:

#!/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項目工具'sqldiff',UUID作爲主鍵,並離開sqlite rowid。它仍然在阿爾法,所以反饋表示讚賞。

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