Gerenciamento de grandes arquivos binários com Git
-
22-08-2019 - |
Pergunta
Eu estou procurando opiniões de como lidar com grandes arquivos binários em que o meu código fonte (aplicação web) é dependente. Atualmente estamos discutindo várias alternativas:
- Copie os arquivos binários com a mão.
- Pro:. Não tenho certeza
- Contra: Eu sou fortemente contra isso, pois aumenta a probabilidade de erros quando a criação de um novo site / migrar do antigo. Constrói-se um outro obstáculo a tomar.
- Gerenciar todos eles com Git .
- Pro: Remove a possibilidade de 'esquecer' para copiar um arquivo importante
- Contra:. Bloats o repositório e diminui a flexibilidade para gerenciar o código-base e checkouts, clones, etc. vai demorar um pouco
- repositórios separados.
- Pro:. O check-out / clonagem do código-fonte é rápido como sempre, e as imagens são devidamente arquivados em seu próprio repositório
- Contra: Remove a simplicidade de ter o único repositório Git no projeto. Ele certamente introduz algumas outras coisas que eu não tenha pensado.
Quais são suas experiências / pensamentos sobre isso?
Além disso:? Alguém tem experiência com múltiplos repositórios Git e gerenciá-los em um projeto
Os arquivos são imagens para um programa que gera PDFs com esses arquivos nele. Os arquivos não vai mudar muito frequentemente (como em anos), mas eles são muito relevantes para um programa. O programa não funcionará sem os arquivos.
Solução
Se o programa não funcionará sem os arquivos parece que dividi-los em um repositório separado é uma má idéia. Temos suites de teste grandes que quebram em um repositório separado, mas aqueles que são verdadeiramente arquivos "auxiliares".
No entanto, você pode ser capaz de gerenciar os arquivos em um repositório separado e, em seguida, usar git-submodule
para puxá-los em seu projeto de uma forma sã. Então, você ainda tem a história completa de toda a sua fonte, mas, como eu o entendo, você só teria a revisão relevante do seu imagens submodule. A instalação git-submodule
deve ajudá-lo a manter a versão correta do código de acordo com a versão correta das imagens.
Aqui está uma boa introdução à submódulos de Git Book.
Outras dicas
git-anexo recentemente que eu acho incrível. Ele foi projetado para o gerenciamento de arquivos grandes de forma eficiente. Eu uso ele para a minha foto / música (etc.) coleções. O desenvolvimento de git-anexo é muito ativa. O conteúdo dos arquivos pode ser removido a partir do repositório Git, somente a hierarquia de árvore é rastreado por Git (através de links simbólicos). No entanto, para obter o conteúdo do arquivo, uma segunda etapa é necessária depois de puxar / empurrar, por exemplo:.
$ git annex add mybigfile
$ git commit -m'add mybigfile'
$ git push myremote
$ git annex copy --to myremote mybigfile ## This command copies the actual content to myremote
$ git annex drop mybigfile ## Remove content from local repo
...
$ git annex get mybigfile ## Retrieve the content
## or to specify the remote from which to get:
$ git annex copy --from myremote mybigfile
Existem muitos comandos disponíveis, e há uma grande documentação no site. Um pacote está disponível em Debian .
Outra solução, desde abril de 2015 é Git Grande Storage File (LFS) (por GitHub).
Ele usa git-LFS (veja < a href = "https://git-lfs.github.com/" rel = "noreferrer"> git-lfs.github.com ) e testado com um servidor de suporte que: LFS-test-server :
Você pode armazenar metadados apenas no repo git, eo grande arquivo em outro lugar.
Tenha um olhar em git bup que é uma extensão Git para armazenar de forma inteligente grandes binários em um Git repositório.
Você gostaria de tê-lo como um sub-módulo, mas você não terá que se preocupar com o repositório ficando difícil de manusear. Um de seus casos de uso de amostra está armazenando imagens de VM em Git.
Eu não tenho realmente visto melhores taxas de compressão, mas meus repositórios não tem realmente grandes binários em si.
Sua milhagem pode variar.
Você também pode usar git-fat . Eu gosto que ele só depende de estoque Python e rsync
. Ele também suporta o fluxo de trabalho habitual Git, com os seguintes comandos auto-explicativos:
git fat init
git fat push
git fat pull
Além disso, é preciso verificar em um arquivo .gitfat em seu repositório e modificar suas .gitattributes para especificar as extensões de arquivo que você quer git fat
de gerir.
Você adiciona um binário usando o git add
normal, que por sua vez invoca git fat
com base em suas regras gitattributes.
Finalmente, ele tem a vantagem de que o local onde os binários são realmente armazenados podem ser compartilhados entre repositórios e usuários e suportes nada rsync
faz.
UPDATE: não usar git-gordura, se você estiver usando uma ponte Git-SVN. Ele vai acabar a remoção dos arquivos binários de seu repositório Subversion. No entanto, se você estiver usando um repositório Git pura, ele funciona muito bem.
Gostaria de usar sub-módulos (como Pat Notz) ou dois repositórios distintos. Se você modificar seus arquivos binários, muitas vezes, então eu iria tentar minimizar o impacto da enorme repositório de limpeza da história:
Eu tive um problema muito semelhante há vários meses: ~ 21 GB de arquivos MP3, não classificados (nomes mau, mau id3 de, não sei se eu como aquele arquivo MP3 ou não ...), e replicado em três computadores .
Eu usei um disco rígido externo com o principal repositório Git, e eu clonado lo em cada computador. Então, comecei a classificá-los da maneira habitual (empurrar, puxar, fundindo ... apagar e renomear muitas vezes).
No final, eu tinha apenas ~ 6 GB de arquivos MP3 e ~ 83 GB no diretório .git. Eu costumava git-write-tree
e git-commit-tree
para criar um novo commit, sem comprometer antepassados, e começou uma nova apontando galho em que cometeu. O "git log" para esse ramo só mostrou um commit.
Então, eu deletei o velho ramo, mantido apenas o novo ramo, eliminado o árbitro-logs, e executar "git ameixa seca": depois disso, minhas pastas .git ponderada apenas ~ 6 GB ...
Você poderia "purga" a enorme repositório de vez em quando, da mesma forma:. O seu "clone git" 's será mais rápido
Na minha opinião, se você é provável que muitas vezes modificar esses arquivos grandes, ou se você pretende fazer um monte de git clone
ou git checkout
, então você deve considerar seriamente o uso de outro repositório Git (ou talvez uma outra maneira de acessar esses arquivos ).
Mas se você trabalhar como nós fazemos, e se seus arquivos binários não são muitas vezes modificados, em seguida, o primeiro clone / checkout será longa, mas depois que ele deve ser tão rápido quanto você quiser (considerando seus usuários continuar usando o primeiro repositório clonado eles tinham).
A solução que eu gostaria de propor baseia-se em ramos órfãos e uma ligeira abuso do mecanismo de tag, doravante referidos como * Orphan Etiquetas binário armazenamento (OTABS)
TL; DR 2017/12/01 Se você pode usar LFS do github ou algum outro 3rd party, por todos os meios que você deve. Se não for possível, então continue a ler. Esteja avisado, esta solução é um hack e deve ser tratado como tal.
propriedades desejáveis ??de OTABS
- é um pura git e git única solução - que começa o trabalho feito sem qualquer software 3o partido (como git-anexo) ou infra-estrutura do 3o partido (como LFS do github).
- que armazena os arquivos binários eficientemente , ou seja, ele não inchar a história de seu repositório.
-
git pull
egit fetch
, incluindogit fetch --all
ainda são largura de banda eficiente , ou seja, nem todos os grandes binários são puxados a partir do controle remoto por padrão. - ele funciona em Windows .
- ele armazena tudo em um único git repositório .
- que permite exclusão de binários desatualizados (ao contrário bup).
propriedades indesejáveis ??de OTABS
- torna
git clone
potencialmente ineficiente (mas não necessariamente, dependendo do seu uso). Se você implantar essa solução você pode ter que aconselhar os seus colegas para usogit clone -b master --single-branch <url>
vez degit clone
. Isso ocorre porque clone git por padrão literalmente clones toda repositório, incluindo coisas que você normalmente não querem perder a sua largura de banda, como commits sem referência. Tomado de SO 4.811.434 . - torna largura de banda
git fetch <remote> --tags
ineficiente, mas não necessariamente de armazenamento ineficiente. Você pode sempre pode aconselhar os seus colegas não usá-lo. - você vai ter que usar periodicamente um truque
git gc
para limpar seu repositório de quaisquer arquivos que você não quer mais. - não é tão eficiente quanto bup ou git-BigFiles . Mas é, respectivamente, mais adequado para o que você está tentando fazer e mais off-the-shelf. Que são susceptíveis de ter problemas com centenas de milhares de arquivos pequenos ou com arquivos na faixa de gigabytes, mas ler sobre soluções alternativas.
Adicionando os arquivos binários
Antes de começar a se certificar de que você cometeu todas as suas alterações, a sua árvore de trabalho é até à data e o seu índice não contém quaisquer alterações não confirmadas. Pode ser uma boa idéia para empurrar todas as suas filiais locais para o controle remoto (github etc.) no caso de qualquer desastre deve acontecer.
- Criar um novo ramo órfão.
git checkout --orphan binaryStuff
irá fazer o truque. Isso produz um ramo que é totalmente desconectado de qualquer outro ramo, eo primeiro cometer você vai fazer neste ramo terá nenhum pai, o que irá torná-lo uma raiz cometer. - Limpe seu índice usando
git rm --cached * .gitignore
. - Respire fundo e eliminar toda árvore de trabalho usando
rm -fr * .gitignore
. diretório.git
interna permanecerá intocado, porque o curinga*
não combiná-lo. - Copiar em sua VeryBigBinary.exe, ou o seu li VeryHeavyDirectory /.>
- Adicione-&& cometê-lo.
- Agora torna-se complicado - se você empurrá-lo para o controle remoto como um ramo todos os seus desenvolvedores vai baixá-lo na próxima vez que eles invocam
git fetch
entupimento sua conexão. Você pode evitar isso, empurrando um tag em vez de um ramo. Isso ainda pode impactar armazenamento largura de banda e do sistema de arquivos do seu colega se eles têm o hábito degit fetch <remote> --tags
digitação, mas a ler para uma solução alternativa. Vá em frente egit tag 1.0.0bin
- Empurre a sua tag órfã
git push <remote> 1.0.0bin
. - Apenas para que você nunca empurrar o seu ramo de binário por acidente, você pode excluí-lo
git branch -D binaryStuff
. Seu comprometer não será marcado para coleta de lixo, porque uma tag apontando órfão nele1.0.0bin
é suficiente para mantê-lo vivo.
Verificar se o arquivo binário
- Como faço (ou os meus colegas) obter o VeryBigBinary.exe check-out para a árvore de trabalho atual? Se o seu atual ramo de trabalho é, por exemplo mestre você pode simplesmente
git checkout 1.0.0bin -- VeryBigBinary.exe
. - Isto irá falhar se você não tem o
1.0.0bin
tag órfã baixado, caso em que você vai ter quegit fetch <remote> 1.0.0bin
antemão. - Você pode adicionar o
VeryBigBinary.exe
em.gitignore
do seu mestre, de modo que ninguém em sua equipe vai poluir a principal história do projeto com o binário por acidente.
Completamente Eliminar o arquivo binário
Se você decidir limpar completamente VeryBigBinary.exe do seu repositório local, seu repositório remoto e repositórios do seu colega você pode apenas:
- Excluir a tag órfã na
git push <remote> :refs/tags/1.0.0bin
remoto - Excluir a tag órfã localmente (exclui todas as outras tags sem referência)
git tag -l | xargs git tag -d && git fetch --tags
. Tomado de SO 1.841.341 com ligeira modificação. - Use um git gc truque para apagar o seu agora unreferenced comprometer localmente.
git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@"
. Ele também irá apagar todos os outros commits sem referência. Tomado de SO 1.904.860 - Se possível, repetir o truque git gc no controle remoto. É possível se você é auto-hospedar seu repositório e pode não ser possível com alguns provedores de git, como github ou em alguns ambientes corporativos. Se você está hospedando com um provedor que não lhe dá ssh acesso à remota apenas deixá-lo ser. É possível que a infra-estrutura do seu provedor irá limpar seus unreferenced cometer em seu próprio tempo doce. Se você estiver em um ambiente corporativo você pode aconselhar o seu TI para executar um lixo cron recolhendo seu controle remoto uma vez por semana ou assim. Se eles fazem ou não não terá qualquer impacto sobre sua equipe em termos de largura de banda e armazenamento, contanto que você aconselhar os seus colegas para sempre
git clone -b master --single-branch <url>
vez degit clone
. - Todos seus colegas que querem se livrar de marcas órfãos desatualizados só precisa aplicar etapas 2-3.
- Você pode, em seguida, repita os passos 1-8 de Adicionando os arquivos binários para criar uma nova tag órfã
2.0.0bin
. Se você está preocupado com o seugit fetch <remote> --tags
colegas de digitação você pode realmente nomeá-lo novamente1.0.0bin
. Isso fará com que a próxima vez que buscar todas as marcas do velho1.0.0bin
será unreferenced e marcado para coleta de lixo seguinte (usando o passo 3). Ao tentar substituir uma tag no controle remoto você tem que usar-f
assim:git push -f <remote> <tagname>
Posfácio
-
OTABS não tocar o seu mestre ou quaisquer outros ramos de código-fonte / desenvolvimento. O comprometer hashes, toda a história, e tamanho pequeno destes ramos não é afetado. Se você já inchado seu histórico de código-fonte com arquivos binários que você terá que limpá-lo como um pedaço de trabalho. Este script pode ser útil.
-
Confirmado para trabalhar no Windows com git-bash.
-
É uma boa idéia para aplicar um href="http://blogs.atlassian.com/2014/05/handle-big-repositories-git/" rel="nofollow noreferrer"> conjunto para tornar o armazenamento de arquivos binários mais eficiente. running frequente de
git gc
(sem quaisquer argumentos adicionais) faz otimizar git subjacente armazenamento de seus arquivos usando deltas binários. No entanto, se seus arquivos são improváveis ??para ficar semelhante a partir de comprometer a cometer você pode desligar deltas binários completamente. Além disso, porque não faz sentido para comprimir já compactados ou criptografados arquivos, como .zip, .jpg ou .crypt, git permite desligar compressão do armazenamento subjacente. Infelizmente é uma configuração que afectam o seu código fonte, bem tudo-ou-nada. -
Você pode querer roteiro até partes do OTABS para permitir o uso mais rápido. Em particular, scripting os passos 2-3 de Completamente Excluindo binário arquivos em um gancho git
update
poderia dar uma atraente mas talvez perigosas semântica para git fetch ( "fetch e tudo exclusão que está desatualizado"). -
Você pode querer ignorar o passo 4 de Completamente Excluindo binário arquivos para manter um histórico completo de todas as alterações binários sobre o controle remoto para o custo do inchaço repositório central. repositórios locais vão ficar o tempo mais magra.
-
mundo Em Java, é possível combinar esta solução com
maven --offline
para criar uma compilação desligada reprodutível armazenados inteiramente em seu controle de versão (é mais fácil com o Maven que com Gradle). Em golang mundo é viável para construir sobre esta solução para gerir o seu GOPATH vez dego get
. No mundo python é possível combinar isso com virtualenv para produzir um ambiente de desenvolvimento auto-suficiente, sem depender de servidores PyPI para cada construção a partir do zero. -
Se os seus arquivos binários mudar muito frequentemente, como artefatos de construção, pode ser uma boa idéia para o script uma solução que armazena 5 versões mais recentes dos artefatos no
monday_bin
etiquetas órfãos,tuesday_bin
, ...,friday_bin
, e também uma tag órfão para cada1.7.8bin
2.0.0bin
liberação, etc. Você pode girar aweekday_bin
e excluir os binários antigos diária. Desta forma, você obtém o melhor dos dois mundos: você mantenha o toda história de seu código-fonte, mas apenas o relevantes histórico de suas dependências binárias. Também é muito fácil de obter os arquivos binários para uma determinada tag sem obter o código-fonte inteiro com toda a sua história:.git init && git remote add <name> <url> && git fetch <name> <tag>
deve fazê-lo para você
SVN parece lidar com deltas binários de forma mais eficiente do que o Git.
Eu tive que decidir sobre um sistema de controle de versão para documentação (arquivos JPEG, arquivos PDF e arquivos .odt). Eu apenas testada adicionando um arquivo JPEG e rodando-a 90 graus quatro vezes (para verificar a eficácia dos deltas binários). repositório do Git cresceu 400%. repositório de SVN cresceu apenas 11%.
Portanto, parece que SVN é muito mais eficiente com arquivos binários.
Assim, a minha escolha é Git para código fonte e SVN para arquivos binários como documentação.
git clone --filter
de GIT 2,19 + clones rasas
Esta nova opção pode eventualmente tornar-se a solução final para o problema de arquivo binário, se os devs Git e GitHub e torná-lo o suficiente amigável (o que, sem dúvida, ainda não alcançado para submódulos por exemplo).
Ele permite que a verdade só buscar arquivos e diretórios que você deseja para o servidor, e foi introduzida, juntamente com uma extensão do protocolo remoto.
Com isso, poderíamos primeiro fazer um clone superficial, e, em seguida, automatizar que blobs para buscar com o sistema de compilação para cada tipo de construção.
Já existe mesmo um --filter=blob:limit<size>
que permite limitar o tamanho máximo de blob para buscar.
Eu tenho desde um exemplo detalhado mínimo de como os olhares de recursos como em: Como faço para clonar um subdiretório apenas um repositório git?
Eu estou procurando opiniões de como lidar com grandes arquivos binários em que o meu código fonte (aplicação web) é dependente. Quais são suas experiências / pensamentos sobre isso?
Eu, pessoalmente, ter executado em falhas de sincronização com Git com alguns dos meus anfitriões nuvem uma vez minhas aplicações web dados binários entalhado acima da 3 GB marca . Eu considerei BFT Repo Cleaner no momento, mas me senti como um hack. Desde então, tenho começado a apenas manter arquivos fora do Git competência, em vez aproveitando ferramentas específicas como o Amazon S3 para o gerenciamento de arquivos, versões e back-up.
Alguém tem experiência com múltiplos repositórios Git e gerenciá-los em um projeto?
Sim. temas Hugo são geridos principalmente desta forma. É um pouco kudgy, mas ele começa o trabalho feito.
A minha sugestão é a de escolher a ferramenta certa para o trabalho . Se é para uma empresa e você está gerenciando sua codeline no GitHub pagar o dinheiro e usar Git-LFS. Caso contrário, você pode explorar opções mais criativas, como, criptografado descentralizada usando blockchain .
As opções adicionais a serem considerados incluem Minio e s3cmd .
Tenha um olhar em camlistore . Não é realmente baseado em Git, mas acho que é mais apropriado para o que você tem que fazer.