Zarządzanie dużymi plikami binarnymi za pomocą Git

Szukam opinii jak radzić sobie z dużymi plikami binarnymi, od których zależy mój kod źródłowy (aplikacja webowa). Obecnie dyskutujemy nad kilkoma alternatywami:

  1. Skopiuj pliki binarne ręcznie.
    • Pro: nie jestem pewien.
    • Contra: jestem zdecydowanie przeciwny temu, ponieważ zwiększa to prawdopodobieństwo błędów przy zakładaniu nowej strony / migracji starej. Tworzy kolejną przeszkodę do pokonania.
  2. zarządzaj nimi wszystkimi za pomocą Git .
    • Pro: usuwa możliwość "zapomnienia" skopiowania ważnego pliku
    • Contra: rozszerza repozytorium i zmniejsza elastyczność w zarządzaniu bazą kodu i kasami, klonami itp. to zajmie trochę czasu.
  3. oddzielne repozytoria.
    • Pro: sprawdzanie / klonowanie kodu źródłowego jest jak zwykle szybkie, a obrazy są odpowiednio archiwizowane we własnym repozytorium.
    • Contra: usuwa prostotę posiadania jedynej i jedynej Repozytorium Git w projekcie. To z pewnością wprowadza inne rzeczy, o których nie myślałem.

Jakie są wasze doświadczenia/myśli na ten temat?

Również: czy ktoś ma doświadczenie z wieloma repozytoriami Git i zarządzaniem nimi w jednym projekcie?

Pliki są obrazami dla programu, który generuje pliki PDF z tymi plikami w nim. Pliki nie zmienią się zbyt często (jak w latach), ale są bardzo istotne dla programu. Program nie będzie działał bez akt.

Author: Peter Mortensen, 2009-02-12

12 answers

Jeśli program nie będzie działał bez plików, wydaje się, że dzielenie ich na oddzielne repo jest złym pomysłem. Mamy duże pakiety testowe, które włamujemy się do osobnego repo, ale są to naprawdę "pomocnicze" pliki.

Jednak może być w stanie zarządzać plikami w osobnym repo, a następnie użyć git-submodule aby wciągnąć je do swojego projektu w rozsądny sposób. Więc, nadal będziesz miał pełną historię wszystkich swoich źródeł, ale, jak rozumiem, będziesz miał tylko jedną istotną rewizję Twoje zdjęcia. Funkcja git-submodule powinna pomóc w utrzymaniu poprawnej wersji kodu w zgodzie z poprawną wersją obrazów.

Oto dobre wprowadzenie do podmodułów z Git Book.

 178
Author: Pat Notz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-09 10:13:09

Odkryłem git-annex Ostatnio, który uważam za świetny. Został zaprojektowany do efektywnego zarządzania dużymi plikami. Używam go do mojego zdjęcia/muzyki (itp.) Kolekcje. Rozwój git-annex jest bardzo aktywny. Zawartość plików może zostać usunięta z repozytorium Git, tylko hierarchia drzewa jest śledzona przez Git (poprzez dowiązania symboliczne). Jednak, aby uzyskać zawartość pliku, potrzebny jest drugi krok po pociągnięciu/pchnięciu, np.:

$ 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

Dostępnych jest wiele poleceń i na stronie znajduje się świetna dokumentacja. Pakiet jest dostępny na Debian .

 312
Author: rafak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-31 15:28:55

Innym rozwiązaniem, od kwietnia 2015 roku jest Git Large File Storage (LFS) (by GitHub).

Używa git-lfs (Zobacz też git-lfs.github.com) i przetestowane z obsługującym go serwerem: LFS-test-server:
Możesz przechowywać metadane tylko w repo git, a duży plik w innym miejscu.

https://cloud.githubusercontent.com/assets/1319791/7051226/c4570828-ddf4-11e4-87eb-8fc165e5ece4.gif

 50
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-09 06:04:57

Spójrz na git bup, który jest rozszerzeniem Git do inteligentnego przechowywania dużych plików binarnych w repozytorium Git.

Chciałbyś mieć go jako podmoduł, ale nie musisz się martwić, że repozytorium stanie się trudne do obsługi. Jednym z ich przykładowych przypadków użycia jest przechowywanie obrazów maszyn wirtualnych w Git.

Nie widziałem lepszych współczynników kompresji, ale moje repozytoria nie mają w sobie zbyt dużych plików binarnych.

Przebieg może się różnić.

 33
Author: sehe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-31 15:27:14

Możesz również użyć git-fat. Podoba mi się, że zależy tylko od stock Pythona i rsync. Obsługuje również zwykły przepływ pracy Git, z następującymi instrukcjami:

git fat init
git fat push
git fat pull
Ponadto należy zameldować się w a .plik gitfat do repozytorium i zmodyfikować swoje .gitattributes określa rozszerzenia plików, którymi chcesz zarządzać git fat.

Dodajesz plik binarny używając zwykłego git add, który z kolei wywołuje git fat na podstawie Twoich gitattributes Zasady.

Wreszcie, ma tę zaletę, że lokalizacja, w której Twoje pliki binarne są faktycznie przechowywane, może być współdzielona między repozytoriami i użytkownikami i obsługuje wszystko, co robi rsync.

UPDATE: nie używaj git - fat, jeśli używasz mostu Git-SVN. Spowoduje to usunięcie plików binarnych z repozytorium Subversion. Jednakże, jeśli używasz czystego repozytorium Git, działa ono pięknie.

 28
Author: Carl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-31 15:31:56

Użyłbym podmodułów (jako Pat Notz) lub dwóch odrębnych repozytoriów. Jeśli zbyt często modyfikujesz swoje pliki binarne, starałbym się zminimalizować wpływ ogromnego repozytorium na czyszczenie historii:

Miałem bardzo podobny problem kilka miesięcy temu: ~21 GB plików MP3, niesklasyfikowane (złe nazwy, złe id3, Nie wiem, czy podoba mi się ten plik MP3, czy nie...) i replikowane na trzech komputerach.

Użyłem zewnętrznego dysku twardego z głównym repozytorium Git i sklonowałem go do każdy komputer. Potem zacząłem je klasyfikować w sposób nawykowy (pchanie, ciągnięcie, łączenie... usuwanie i zmiana nazwy wiele razy).

Na koniec miałem tylko ~6 GB plików MP3 i ~83 GB wkatalog git. Użyłem git-write-tree i git-commit-tree aby utworzyć nowy commit, bez przodków commitów, i uruchomiłem nową gałąź wskazującą na ten commit. "Git log" dla tej gałęzi pokazywał tylko jeden commit.

Potem usunąłem starą gałąź, zachowałem tylko nową gałąź, usunąłem ref-logi i uruchomiłem "git prune": {foldery git ważą tylko ~6 GB...

Możesz od czasu do czasu" wyczyścić "ogromne repozytorium w ten sam sposób: Twoje "git clone" będą szybsze.

 26
Author: Daniel Fanjul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-31 13:39:19

Rozwiązanie, które chciałbym zaproponować, opiera się na gałęziach osieroconych i lekkim nadużyciu mechanizmu znaczników, odtąd określanych jako * Orphan Tags Binary Storage (OTABS)

TL; DR 12-01-2017 jeśli możesz używać LFS Githuba lub innej strony trzeciej, zdecydowanie powinieneś. Jeśli nie możesz, Czytaj dalej. Ostrzegamy, To rozwiązanie jest hack i powinny być traktowane jako takie.

Pożądane właściwości OTABÓW

  • jest to czysta git i Git only rozwiązanie -- wykonuje zadanie bez żadnego oprogramowania firm trzecich (jak git-annex) lub infrastruktury firm trzecich (jak github ' s LFS).
  • przechowuje pliki binarne efektywnie , tzn. nie pobiera historii Twojego repozytorium.
  • git pull i git fetch, w tym git fetch --allsą nadal efektywną przepustowością, tzn. nie wszystkie duże binaria są domyślnie pobierane z pilota.
  • Działa na Windows .
  • it przechowuje wszystko w pojedynczym repozytorium git .
  • pozwala nausuwanie przestarzałych binariów (w przeciwieństwie do bup).

Niepożądane właściwości OTABS

  • sprawia, że git clone jest potencjalnie nieefektywny (ale niekoniecznie, w zależności od użycia). Jeśli wdrożysz To rozwiązanie, być może będziesz musiał doradzić swoim kolegom, aby używali git clone -b master --single-branch <url> zamiast git clone. Dzieje się tak dlatego, że git clone domyślnie dosłownie klonuje całe repozytorium, w tym rzeczy, na które normalnie nie chcesz marnować przepustowości, takie jak niezrealizowane commity. Wzięte z tak 4811434 .
  • To sprawia, że przepustowość jest nieefektywna, ale niekoniecznie nieefektywna pamięć masowa. Zawsze możesz doradzić swoim kolegom, aby z niego nie korzystali.
  • będziesz musiał okresowo używać sztuczki git gc, aby wyczyścić repozytorium z plików, których już nie chcesz.
  • nie jest tak wydajny jak bup czy git-bigfiles . Ale jest odpowiednio bardziej odpowiedni do tego, co próbujesz zrobić i bardziej off-the-shelf. Prawdopodobnie napotkasz problemy z setkami tysięcy małych plików lub z plikami w zakresie gigabajtów, ale czytaj dalej, aby obejść.

Dodawanie plików binarnych

Zanim zaczniesz, upewnij się, że zatwierdziłeś wszystkie zmiany, twoje drzewo robocze jest aktualne, A Indeks nie zawiera żadnych niezatwierdzonych zmian. To może być dobry pomysł, aby wcisnąć wszystkie lokalne gałęzie do Twojego pilota (github itp.) na wypadek, gdyby doszło do katastrofy.

  1. Utwórz nową orphan branch. git checkout --orphan binaryStuff da radę. Spowoduje to powstanie gałęzi, która jest całkowicie odłączona od jakiejkolwiek innej gałęzi, a pierwszy commit, który zrobisz w tej gałęzi, nie będzie miał rodzica, co sprawi, że będzie to commit główny.
  2. Wyczyść indeks za pomocą git rm --cached * .gitignore.
  3. weź głęboki oddech i usuń całe działające drzewo za pomocą rm -fr * .gitignore. Wewnętrzny katalog .git pozostanie nietknięty, ponieważ * symbol wieloznaczny nie pasuje do niego.
  4. Kopia w Twoim VeryBigBinary.exe, lub Twój VeryHeavyDirectory/.
  5. Dodaj i zatwierdź.
  6. teraz staje się to trudne -- jeśli wciśniesz go do pilota jako gałąź, wszyscy twoi Programiści pobierają go następnym razem, gdy wywołają git fetch zapchanie połączenia. Możesz tego uniknąć, naciskając znacznik zamiast gałęzi. Może to nadal wpływać na przepustowość i pamięć systemu plików twojego kolegi, jeśli ma zwyczaj pisania git fetch <remote> --tags, ale Czytaj dalej, aby obejść to rozwiązanie. Śmiało i git tag 1.0.0bin
  7. Push your orphan tag git push <remote> 1.0.0bin.
  8. aby przypadkiem nie popchnąć gałęzi binarnej, możesz ją usunąć git branch -D binaryStuff. Twój commit nie zostanie oznaczony do usunięcia śmieci, ponieważ znacznik sierocy wskazujący na niego 1.0.0bin wystarczy, aby utrzymać go przy życiu.

Sprawdzanie pliku binarnego

  1. Jak ja (lub moi koledzy) uzyskać bardzoexe sprawdził się w bieżącym drzewie roboczym? Jeśli aktualnie działającą gałęzią jest na przykład master, który możesz po prostu git checkout 1.0.0bin -- VeryBigBinary.exe.
  2. to się nie powiedzie, jeśli nie masz pobranego znacznika orphan 1.0.0bin, w którym to przypadku będziesz musiał git fetch <remote> 1.0.0bin wcześniej.
  3. możesz dodać VeryBigBinary.exe do twojego mistrza .gitignore, tak aby nikt z twojego zespołu nie zanieczyścił przez przypadek głównej historii projektu binarnym.

Całkowite usunięcie pliku binarnego

Jeśli zdecydujesz się całkowicie oczyścić VeryBigBinary.exe z Twoje lokalne repozytorium, zdalne repozytorium i repozytoria kolegi możesz po prostu:

  1. Usuń znacznik orphan na pilocie git push <remote> :refs/tags/1.0.0bin
  2. Usuń znacznik orphan lokalnie (usuwa wszystkie inne niezrealizowane znaczniki) git tag -l | xargs git tag -d && git fetch --tags. Wzięte z więc 1841341 z lekką modyfikacją.
  3. użyj sztuczki git gc, aby usunąć lokalny commit. git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@". Usunie również wszystkie inne niezrealizowane commity. Wzięte z więc 1904860
  4. jeśli możliwe, powtórz sztuczkę git gc na pilocie. Jest to możliwe, jeśli samodzielnie hostujesz swoje repozytorium i może nie być możliwe u niektórych dostawców Gita, takich jak github lub w niektórych środowiskach korporacyjnych. Jeśli korzystasz z hostingu u dostawcy, który nie daje Ci dostępu ssh do pilota, po prostu odpuść. Jest możliwe, że infrastruktura Twojego dostawcy wyczyści Twój niezrealizowany commit we własnym słodkim czasie. Jeśli jesteś w środowisku korporacyjnym, możesz doradzić IT, aby uruchomić śmieci pracy cron zbieranie pilota raz w tygodniu lub tak. Niezależnie od tego, czy robią to, czy nie, nie będzie to miało żadnego wpływu na zespół pod względem przepustowości i pamięci masowej, o ile doradzisz współpracownikom, aby zawsze git clone -b master --single-branch <url> zamiast git clone.
  5. wszyscy twoi koledzy, którzy chcą pozbyć się przestarzałych znaczników osieroconych, muszą zastosować kroki 2-3.
  6. możesz następnie powtórzyć kroki 1-8 z dodawania plików binarnych , aby utworzyć nowy znacznik osierocony 2.0.0bin. Jeśli martwisz się, że twoi koledzy piszą git fetch <remote> --tags, to można go nazwać ponownie 1.0.0bin. Spowoduje to, że przy następnym pobraniu wszystkich znaczników Stary 1.0.0bin zostanie nieodferencjonowany i oznaczony do późniejszego zbierania śmieci (za pomocą kroku 3). Gdy próbujesz nadpisać znacznik na pilocie, musisz użyć -f w następujący sposób: git push -f <remote> <tagname>

Afterword

  • OTABS nie dotyka twojego wzorca ani żadnego innego kodu źródłowego/gałęzi programistycznych. Hasze commitów, cała historia i niewielki rozmiar tych gałęzie są nienaruszone. Jeśli masz już nadęty historię kodu źródłowego z plikami binarnymi, będziesz musiał oczyścić ją jako oddzielny kawałek pracy. ten skrypt może się przydać.

  • Potwierdzone do pracy na Windows z git-bash.

  • Dobrym pomysłem jest zastosowanie zestawu standardowych trików w celu zwiększenia wydajności przechowywania plików binarnych. Częste uruchamianie git gc (bez dodatkowych argumentów) sprawia, że git optymalizuje podstawowe przechowywanie Twoje pliki za pomocą binarnych deltas. Jeśli jednak Twoje pliki nie będą podobne od commit do commit, możesz całkowicie wyłączyć delty binarne. Dodatkowo, ponieważ nie ma sensu kompresować już skompresowanych lub zaszyfrowanych plików, jak .zip,jpg lub .crypt, git pozwala na wyłączenie kompresji bazowej pamięci masowej. Niestety jest to ustawienie "wszystko albo nic" wpływające również na Twój kod źródłowy.

  • Możesz chcieć skryptować części OTABS, aby umożliwić dla szybszego użytkowania. W szczególności, scripting kroków 2-3 z całkowite usunięcie plików binarnych do update Git hook może dać przekonującą, ale być może niebezpieczną semantykę git fetch ("fetch and delete everything that is out of date").

  • Możesz pominąć krok 4 całkowitego usuwania plików binarnych, aby zachować pełną historię wszystkich zmian binarnych na zdalnym kosztem centralnego repozytorium. Lokalne repozytoria pozostaną szczupłe z czasem.

  • W Java world możliwe jest połączenie tego rozwiązania z maven --offline, aby utworzyć powtarzalną kompilację offline przechowywaną w całości w twojej kontroli wersji (jest to łatwiejsze z maven niż z gradle). W świecie Golang możliwe jest zbudowanie tego rozwiązania, aby zarządzać swoim GOPATHEM zamiast go get. W świecie Pythona możliwe jest połączenie tego z virtualenv w celu stworzenia samodzielnego środowiska programistycznego bez polegania na serwerach PyPi dla każdej kompilacji z scratch.

  • Jeśli Twoje pliki binarne zmieniają się bardzo często, na przykład artefakty kompilacji, dobrym pomysłem może być skrypt rozwiązania, które przechowuje 5 najnowszych wersji artefaktów w znacznikach osieroconychmonday_bin, tuesday_bin, ..., friday_bin, a także znacznik orphan dla każdego wydania 1.7.8bin 2.0.0bin, itd. Możesz codziennie obracać weekday_bin i usuwać stare pliki binarne. W ten sposób otrzymujesz to, co najlepsze z dwóch światów: zachowujesz całą historię kodu źródłowego, ale tylko odpowiednią historia zależności binarnych. Bardzo łatwo jest również uzyskać pliki binarne dla danego tagu BEZ uzyskania całego kodu źródłowego z całą jego historią: git init && git remote add <name> <url> && git fetch <name> <tag> powinno to zrobić za Ciebie.

 13
Author: Adam Kurkiewicz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:24

Moim zdaniem, jeśli często modyfikujesz te duże pliki, lub jeśli zamierzasz zrobić dużo git clone LUB git checkout, powinieneś poważnie rozważyć użycie innego repozytorium Git (a może innego sposobu dostępu do tych plików).

Ale jeśli pracujesz tak jak my i jeśli Twoje pliki binarne nie są często modyfikowane, to pierwszy klon/kasa będzie długi, ale po tym powinien być tak szybki, jak chcesz (biorąc pod uwagę, że użytkownicy nadal używają pierwszego sklonowanego repozytorium, które mieli).

 13
Author: claf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-31 13:36:29

SVN wydaje się obsługiwać delty binarne bardziej efektywnie niż Git.

Musiałem zdecydować się na system wersjonowania dokumentacji (pliki JPEG, pliki PDF i .pliki odt). Właśnie testowałem dodawanie pliku JPEG i obracanie go o 90 stopni cztery razy (aby sprawdzić skuteczność delt binarnych). Repozytorium Gita wzrosło o 400%. Repozytorium SVN wzrosło tylko o 11%.

Wygląda więc na to, że SVN jest znacznie wydajniejszy z plikami binarnymi.

Więc mój wybór to Git dla kodu źródłowego i SVN dla binarnych pliki takie jak dokumentacja.

 9
Author: Tony Diep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-31 15:24:05

git clone --filter od Git 2.19 + płytkie klony

Ta nowa opcja może ostatecznie stać się ostatecznym rozwiązaniem problemu z plikami binarnymi, jeśli deweloperzy Git i GitHub uczynią ją wystarczająco przyjazną dla użytkownika(co prawdopodobnie {7]} nadal nie zostało osiągnięte dla podmodułów na przykład).

Pozwala na pobieranie tylko plików i katalogów, które chcesz dla serwera, i został wprowadzony wraz z rozszerzeniem protokołu zdalnego.

Z tym, możemy najpierw zrobić shallow klonuje, a następnie automatyzuje, które obiekty BLOB mają być pobierane za pomocą systemu budowania dla każdego typu budowania.

Istnieje nawet --filter=blob:limit<size>, który pozwala ograniczyć maksymalny rozmiar Bloba do pobrania.

Podałem minimalny szczegółowy przykład jak ta funkcja wygląda w: Jak sklonować podkatalog tylko z repozytorium Git?

 5
Author: Ciro Santilli TRUMP BAN IS BAD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-06 14:23:09

Szukam opinii jak obsługiwać duże pliki binarne, od których zależy mój kod źródłowy (aplikacja internetowa). Jakie są wasze doświadczenia/myśli na ten temat?

Osobiście napotkałem awarie synchronizacji z Gitz niektórymi hostami w chmurze, gdy moje aplikacje internetowe zapisały dane binarne powyżej znaku 3 GB. W tym czasie rozważałem Bft Repo Cleaner , ale czułem się jak hack. Od tego czasu zacząłem po prostu przechowywać pliki zamiast tego wykorzystuje Narzędzia specjalne , takie jak Amazon S3 do zarządzania plikami, wersjonowania i tworzenia kopii zapasowych.

Czy ktoś ma doświadczenie z wieloma repozytoriami Git i zarządzaniem nimi w jednym projekcie?

Tak. Hugo themes są przede wszystkim zarządzane w ten sposób. To trochę Kudłaty, ale robi robotę.

Moja sugestia to wybrać odpowiednie narzędzie do pracy . Jeśli chodzi o firmę i zarządzasz Twój kod na GitHub Zapłać pieniądze i użyj Git-LFS. W przeciwnym razie możesz zbadać bardziej kreatywne opcje, takie jak zdecentralizowane, zaszyfrowane przechowywanie plików za pomocą blockchain.

Dodatkowe opcje do rozważenia to Minio i s3cmd.

 2
Author: Josh Habdas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-31 20:27:29

Spójrz na camlistore . Nie jest tak naprawdę oparty na Git, ale uważam, że jest bardziej odpowiedni do tego, co musisz zrobić.

 0
Author: Hernan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-31 20:24:13