Uma alternativa usando git-annex
:
Primeiro, vamos configurar os arquivos de teste:
#!/bin/bash
# faster than /dev/urandom
randfile='openssl enc -aes-256-ctr -pass pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" -nosalt < /dev/zero'
dd='dd bs=1M count=5 iflag=fullblock'
for I in 1 2
do
mkdir root$I
cd root$I
for J in 1 2
do
mkdir dir$J
if [ -e dir2 ]
then
cd dir2
eval $randfile | eval $dd of=file1
eval $randfile | eval $dd of=file2
if [ 'pwd | grep root1' ]; then
eval $randfile | eval $dd of=file3
elif [ 'pwd | grep root2' ]; then
eval $randfile | eval $dd of=file4
fi
cd ..
fi
done
cd ..
done
Isso cria os diretórios, com arquivos binários contendo dados aleatórios. Neste ponto, os arquivos são:
user@host$ find root? -path '*/.git*' -prune -o -print | sort -n
root1
root1/dir1
root1/dir2
root1/dir2/file1
root1/dir2/file2
root1/dir2/file3
root2
root2/dir1
root2/dir2
root2/dir2/file1
root2/dir2/file2
root2/dir2/file4
Agora, inicializamos os repositórios e realizamos uma sincronização:
cd root1
git init
git annex init 'root1'
git remote add root2 ../root2
#git annex direct
git annex add .
git commit -a -m 'Files added.'
cd ..
cd root2
git init
git annex init 'root1'
git remote add root1 ../root1
#git annex direct
git annex add .
git commit -a -m 'Files added.'
cd ..
mkdir unioned
cd unioned
git init
git annex init 'unioned'
git remote add root1 ../root1
git remote add root2 ../root2
git annex add .
git commit -a -m 'Files added.'
git annex sync
cd ..
Neste ponto, o conteúdo de unioned/
é:
user@host$ find root? unioned -path '*/.git*' -prune -o -print | sort -n
root1
root1/dir1
root1/dir2
root1/dir2/file1
root1/dir2/file2
root1/dir2/file3
root2
root2/dir1
root2/dir2
root2/dir2/file1
root2/dir2/file2
root2/dir2/file4
unioned
unioned/dir2
unioned/dir2/file1
unioned/dir2/file1.variant-065a
unioned/dir2/file1.variant-a33e
unioned/dir2/file2
unioned/dir2/file2.variant-08f3
unioned/dir2/file2.variant-75c4
unioned/dir2/file3
unioned/dir2/file4
Em que *.variant-*
vincula os arquivos diferentes nos diferentes repositórios. Além disso, unioned
ainda não contém dados até que conduzamos um git annex get
. Por enquanto, git annex list
mostra onde os arquivos estão localizados e / ou provenientes de:
user@host$ cd unioned; git annex list
here
|root1
||root2
|||web
||||
__X_ dir2/file1.variant-065a
_X__ dir2/file1.variant-a33e
__X_ dir2/file2.variant-08f3
_X__ dir2/file2.variant-75c4
_X__ dir2/file3
__X_ dir2/file4
Uma alternativa em um formato mais longo é git annex whereis
. Finalmente, para resolver os conflitos e propagar a mesclagem, de dentro de unioned/dir2
:
cd unioned/dir2
git annex get # retrieve the actual content
git annex unlock # unlock the files - replace the symlinks with the actual repofiles
rm file1
git mv file1.variant-065a file1
git rm -f file1.variant-a33e
rm file2
git mv file2.variant-75c4 file2
git rm -f file2.variant-08f3
git annex add . # "commits" the changes, converts files back into symlinks
git annex sync # propagates the changes back to the other repos
Quais rendimentos:
git annex sync
commit ok
pull root2
ok
pull root1
ok
push root2
Counting objects: 61, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (26/26), done.
Writing objects: 100% (37/37), 2.67 KiB | 0 bytes/s, done.
Total 37 (delta 14), reused 0 (delta 0)
To ../root2
e5df80f..720b34b git-annex -> synced/git-annex
b055385..ad8c5c2 master -> synced/master
ok
push root1
Counting objects: 61, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (26/26), done.
Writing objects: 100% (37/37), 2.67 KiB | 0 bytes/s, done.
Total 37 (delta 14), reused 0 (delta 0)
To ../root1
e5df80f..720b34b git-annex -> synced/git-annex
b055385..ad8c5c2 master -> synced/master
ok
Por fim, um git annex list
mostra onde esses arquivos estão localizados após a sincronização: o diretório unioned/
tem cópias de todos os arquivos, escolhidos nos diferentes servidores conforme acima.
git-annex
também tem um modo direto que opera diretamente no sistema de arquivos sem o uso de links simbólicos.
Configurar isso para uso em computadores remotos é uma questão de configurar controles remotos sobre o ssh usando o git padrão, no entanto, o comportamento é descrito aqui: link
O passo a passo geral do git anexo está localizado aqui: link