Pytanie Czy "eksport git" (jak "eksport svn")?


Zastanawiam się, czy istnieje dobre rozwiązanie "eksportu git", które tworzy kopię drzewa bez .git katalog repozytorium. Istnieją co najmniej trzy metody, które znam:

  1. git clone a następnie usunięcie .git katalog repozytorium.
  2. git checkout-index nawiązuje do tej funkcji, ale zaczyna się od "Po prostu odczytaj pożądane drzewo w indeksie ...", co nie jest do końca pewne.
  3. git-export jest skryptem strony trzeciej, który zasadniczo robi git clone do tymczasowej lokalizacji, po której następuje rsync --exclude='.git' do ostatecznego miejsca przeznaczenia.

Żadne z tych rozwiązań nie wydaje mi się zadowalające. Najbliższy do svn export może być opcją 1, ponieważ obie te opcje wymagają, aby katalog docelowy był pusty jako pierwszy. Ale opcja 2 wydaje się jeszcze lepsza, zakładając, że mogę dowiedzieć się, co to znaczy odczytać drzewo w indeksie.


2165
2017-10-02 02:21


pochodzenie


@rnrTom: Zobacz odpowiedź Somova. (w archiwum tar nie ma nic "skompresowanego"). - etarion
@mrTom git archive --format zip --output "output.zip" master -0 da ci nieskompresowane archiwum (-0 jest flagą nieskompresowanego). git-scm.com/docs/git-archive.
Zgadzam się z @mrTom i nie sądzę, że archiwum jest skompresowane lub nieskompresowane jest głównym problemem. Z SVN mogę exportpodkatalog o wielkości 250 kB bezpośrednio ze zdalnego repozytorium (które w innym przypadku może mieć 200 MB, z wyłączeniem wersji) - a ja trafię do sieci tylko za 250 kB (lub tak) transfer do pobrania. Z git, archive musi być włączony na serwerze (więc nie mogę tego wypróbować) - clone --depth 1 z serwera nadal może pobrać repo z powiedzmy 25 MB, gdzie .git sam podfolder zajmuje 15 MB. Dlatego nadal powiedziałbym, że odpowiedź brzmi "nie". - sdaau
@mrTom odpowiedź jest w rzeczywistości TAK Zobacz odpowiedź OP - polecenie jest git checkout-index - nocache
Oto ładny i prosty sposób: git archive -o latest.zip HEAD - Evgeni Sergeev


Odpowiedzi:


Prawdopodobnie najprostszym sposobem na osiągnięcie tego jest git archive. Jeśli naprawdę potrzebujesz tylko rozwiniętego drzewa, możesz zrobić coś takiego.

git archive master | tar -x -C /somewhere/else

W większości przypadków, gdy potrzebuję "wyeksportować" coś z git, w każdym razie potrzebuję skompresowanego archiwum, więc robię coś takiego.

git archive master | bzip2 >source-tree.tar.bz2

Archiwum ZIP:

git archive --format zip --output /full/path/to/zipfile.zip master 

git help archive aby uzyskać więcej szczegółów, jest dość elastyczny.


Pamiętaj, że nawet jeśli archiwum nie zawiera katalogu .git, to jednak będzie zawierało inne ukryte pliki git, takie jak .gitignore, .gitattributes, itp. Jeśli nie chcesz ich w archiwum, upewnij się, że użyj atrybutu export-ignore w pliku .gitattributes i zatwierdz to przed zrobieniem archiwum. Czytaj więcej...


Uwaga: Jeśli jesteś zainteresowany eksportowaniem indeksu, polecenie jest

git checkout-index -a -f --prefix=/destination/path/

(Widzieć Odpowiedź Grega po więcej szczegółów)


2198
2017-10-02 18:13



Archiwum ZIP: git archive --format zip --output /full/path master - Stream
Pamiętaj, że archiwum nie będzie zawierało katalogu .git, ale będzie zawierało inne ukryte pliki git, takie jak .gitignore, .gitattributes, itd. Więc jeśli ich nie chcesz, upewnij się, że używasz atrybutu ignorowania eksportu a .gitattributes plik i zatwierdz to przed zrobieniem archiwum. Widzieć feeding.cloud.geek.nz/2010/02/... - mj1531
Aby śledzić notatkę strumieniową: możesz dodać do polecenia polecenie "--prefix = coś /", aby kontrolować nazwę katalogu, który zostanie spakowany wewnątrz zip. Na przykład, jeśli używasz git archive --format zip --output /path/to/file.zip --prefix=newdir/ master dane wyjściowe będą nazywane "file.zip", ale po rozpakowaniu katalogiem najwyższego poziomu będzie "newdir". (Jeśli pominiesz atrybut --prefix, katalog najwyższego poziomu będzie "plikiem".) - Alan W. Smith
Najprostszy sposób: git archive -o latest.zip HEAD Tworzy archiwum Zip, które zawiera zawartość ostatniego zatwierdzenia w bieżącym oddziale. Zauważ, że format wyjściowy jest wywnioskowany przez rozszerzenie pliku wyjściowego. - nacho4d
Nie obsługuje podmodułów git :( - umpirsky


Dowiedziałem się, co oznacza opcja 2. Z repozytorium możesz:

git checkout-index -a -f --prefix=/destination/path/

Ukośnik na końcu ścieżki jest ważny, w przeciwnym razie spowoduje, że pliki będą w / docelowym z prefiksem "ścieżki".

Ponieważ w normalnej sytuacji indeks zawiera zawartość repozytorium, nie ma nic specjalnego do zrobienia, aby "odczytać pożądane drzewo do indeksu". Już tam jest.

The -a flaga jest wymagana do sprawdzenia wszystkich plików w indeksie (nie jestem pewien, co to znaczy, aby pominąć tę flagę w tej sytuacji, ponieważ nie robi to, co chcę). The -f flaga wymusza zastępowanie wszystkich istniejących plików w danych wyjściowych, które zwykle nie są wykonywane.

Wygląda to na rodzaj "eksportu git", którego szukałem.


301
2017-10-02 03:03



... i NIE ZAPOMNIJ SLASH NA KOŃCU, bo inaczej nie uzyskasz pożądanego efektu;) - conny
The git add Polecenie zmienia zawartość w indeksie, więc cokolwiek git status pokazywane jako "do popełnienia" to różnice między HEAD a zawartością indeksu. - Greg Hewgill
@conny: przeczytaj komentarz, zapomniałeś o tym i uruchomiłeś polecenie bez końcowego slasha. wskazówka: wykonaj porady conny -.- - Znarkus
+1 do porady conny'ego. Nie próbuj też tworzyć "~ / dest /", ponieważ tworzy to katalog o nazwie "~" w katalogu roboczym, a nie to, co naprawdę chciałeś. Zgadnij, co się dzieje, gdy bezmyślnie wpisujesz rm -rf ~ - Kyle Heironimus
@ KyleHeironimus - twoje ostrzeżenie o używaniu '~ / dest / `jest prawdziwe, jeśli użyjesz cudzysłowów dookoła swojej prefiksowej ścieżki, która mówi, że powłoka nie wykonuje rozszerzenia tyldy. Dzwonił dir ~ (nie '~' !) zostaną stworzone w waszym roboczym reż. Nie ma w tym nic specjalnego git checkout-index w związku z tym: to samo dotyczy mkdir '~/dest' (nie rób tego!). Kolejny dobry powód, aby unikać nazw plików, które wymagają cytowania (np. Mają w nich miejsce) :-) - Matt Wallis


git archive działa również ze zdalnym repozytorium.

git archive --format=tar \
--remote=ssh://remote_server/remote_repository master | tar -xf -

Aby wyeksportować określoną ścieżkę wewnątrz repo, dodaj tyle ścieżek, ile chcesz, jako ostatni argument do git, np .:

git archive --format=tar \
--remote=ssh://remote_server/remote_repository master path1/ path2/ | tar -xv

241
2017-12-09 18:59



Ten jest opcją, którą lubię najbardziej. Dodatkową zaletą jest to, że działa również na repozytoriach. - innaM
Poprawiona wersja to: git archive --format=tar --prefix=PROJECT_NAME/ --remote=USER@SERVER:PROJECT_NAME.git master | tar -xf -  (zapewnia, że ​​twoje archiwum znajduje się w folderze) - Nick
Uwaga: serwer musi włączyć tę funkcję. - Jakub Narębski
Próbowałem : git archive --format=zip --output foo.zip --remote=https://github.com/xxx.git master I zginęło: operacja nie jest obsługiwana przez protokół. Nieoczekiwany koniec strumienia poleceń. - andyf
@andyfown GitHub ma swój własny sposób: curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf - za docs - bishop


enter image description here

Odpowiedź na specjalny przypadek, jeśli repozytorium jest hostowane na GitHub.

Po prostu użyj svn export.

O ile wiem, Github nie pozwala archive --remote. Chociaż GitHub jest kompatybilny z svn i mają wszystkie repozytorium git svn dostępne, więc możesz po prostu użyć svn export jak zwykle z kilkoma dostosowaniami do adresu URL GitHub.

Na przykład, aby wyeksportować całe repozytorium, zwróć uwagę, jak to zrobić trunkw URL zastępuje master (lub cokolwiek gałąź HEAD projektu jest ustawiona na):

svn export https://github.com/username/repo-name/trunk/

Możesz wyeksportować pojedynczy plik lub nawet określoną ścieżkę lub folder:

svn export https://github.com/username/repo-name/trunk/src/lib/folder

Przykład z jQuery JavaScript Library

The HEAD oddział lub mistrz gałąź będzie dostępna za pomocą trunk:

svn ls https://github.com/jquery/jquery/trunk

Nie-HEAD  gałęzie będą dostępne pod /branches/:

svn ls https://github.com/jquery/jquery/branches/2.1-stable

Wszystko tagi pod /tags/ w tym samym stylu:

svn ls https://github.com/jquery/jquery/tags/2.1.3

48
2017-10-30 17:03



git archive działa dobrze z GitHub, o ile używasz protokołu git, po prostu zamień https:// z git:// w adresie URL. Nie wiem, dlaczego GitHub nie reklamuje tej ukrytej funkcji. - Neil Mayhew
@NeilMayhew To nie działa dla mnie, dostaję fatal: The remote end hung up unexpectedly. Próbowałem na dwóch różnych serwerach z jQuery github repo. - Anthony Hatzopoulos
Masz rację. Zapomniałem, że używam git config url.<base>.insteadOf buforować zdalne repozytorium. Dlatego korzystałem z file:// URL w rzeczywistości. wątpię w to git archive może kiedykolwiek pracować git:// Adresy URL, ponieważ muszą być w stanie uruchomić git-upload-archive na drugim końcu. Powinno być możliwe przy użyciu ssh protokołu, z wyjątkiem tego, że github na to nie pozwala (Invalid command: 'git-upload-archive'). - Neil Mayhew
Jakikolwiek sposób użyć narzędzia serwera lokalnego zachowując się jak github, jeśli chcę to zrobić na wewnętrznie hostowanych repozytoriach git? - kriss
przegłosowane - jest całkowicie dziwne, że Git nie ma tej funkcji i musimy uciekać się do svn - Jason S


Od Instrukcja Git:

Używanie git-checkout-index do "eksportu całego drzewa"

Zdolność prefiksu zasadniczo sprawia, że ​​używanie funkcji git-checkout-index jest banalnie proste jako funkcja "eksportuj jako drzewo". Po prostu odczytaj żądane drzewo w indeksie i wykonaj:

$ git checkout-index --prefix=git-export-dir/ -a


38
2017-10-02 02:27



Myślę, że zamieszanie to fraza "odczytaj pożądane drzewo do indeksu". - davetron5000
Jeśli chcesz wyeksportować katalog foo do paska gałęzi, to byłoby to git read-tree bar:foo I wtedy git checkout-index --prefix=export_dir/ -a po tym może powinieneś zrobić git update-index master - Pascal Rosin
Nie wiem, dlaczego nie jest to zaakceptowana odpowiedź. - John Weldon
@JohnWeldon Czy najpierw trzeba sklonować repo? Jeśli tak, to nie zaakceptowałbym tego, ponieważ cały punkt "eksportu svn" podkatalogu polega na bezpośrednim uzyskaniu kopii tego podkatalogu; jeśli ktoś ma repozytorium Git 1 GB i wszystko, czego chcę, to podkatalog 10kB, to szalone, żebym kazał sklonować całą sprawę. - Jason S
Również powiedziałbym @ davetron5000 z komentarzem "odczytać pożądane drzewo do indeksu", którego nie mam pojęcia, co to znaczy. - Jason S


Napisałem proste opakowanie git-checkout-index które możesz użyć w ten sposób:

git export ~/the/destination/dir

Jeśli katalog docelowy już istnieje, musisz dodać -f lub --force.

Instalacja jest prosta; po prostu upuść skrypt gdzieś w swoim PATHi upewnij się, że jest to plik wykonywalny.

Repozytorium github dla git-export 


37
2017-10-16 17:17



To opakowanie nie jest agnostyczne; opiera się na / bin / sh. Więc jeśli jesteś w systemie Windows, to rozwiązanie prawdopodobnie nie będzie działać dla ciebie. - shovavnik
Uhh, ten skrypt składa się z 57 linii dokumentacji, białych znaków, ustawień, analizy argumentów i tylko jednej linii, która faktycznie robi coś ... - Vladimir Panteleev


Wydaje się, że jest to mniejszy problem z Git niż SVN. Git umieszcza tylko folder .git w katalogu głównym repozytorium, podczas gdy SVN umieszcza folder .svn w każdym podkatalogu. Tak więc "eksport svn" unika rekursywnej magii linii poleceń, podczas gdy rekursja Gita nie jest konieczna.


35
2018-05-12 04:20



Od wersji SVN 1.7 jest tylko jeden folder .svn: subversion.apache.org/docs/release-notes/1.7.html#single-db - kostmo
To nie pozbywa się żadnych dodatkowych plików kompilacji, które usuwa eksport svn. To zdecydowanie nie jest odpowiedź. - ygoe
Unieważniono, ponieważ odpowiedź jest nieprawidłowa. - bahrep


Odpowiednik

svn export . otherpath

wewnątrz istniejącego repo to

git archive branchname | (cd otherpath; tar x)

Odpowiednik

svn export url otherpath

jest

git archive --remote=url branchname | (cd otherpath; tar x)

26
2018-02-23 15:41



dzięki, tego właśnie mi brakowało ... także, aby sprawdzić znaczniki czasu eksportu (nie będą zachowane jak na plikach), użyj git archive --format=tar --prefix=junk/ HEAD | (tar -t -v --full-time -f -) ... Jednak archiwizacja z sygnaturami czasowymi nie jest dokładnie banalna, więc napisałem przykład poniżej. - sdaau
Możesz użyć opcji C dla tar zamiast podpowłoki, na przykład: git archive branchname | tar xC otherpath - James Moore
Głowy w górę, że C opcja tar jest tylko GNU Tar. - aredridel


Używam intensywnie submodułów git. Ten działa dla mnie:

rsync -a ./FROM/ ./TO --exclude='.*'

21
2017-09-13 06:26



Czy nie tęskniłoby za plikami, których nazwy zaczynają się kropką, na przykład .htaccess? - Greg Hewgill
Dobre rozwiązanie, zmienię --exclude = '. *' Na --exclude = '. Git *' - schmunk
--exclude-vcs, jeśli zamierzałeś przyjąć ten takt - plod
Czy ./FROM/ może być zdalnym repo? - Resist Design
Jako FYI, moja kopia rsync wylicza argument jako --cvs-exclude. Dodatkowo nadal kopiuje .gitattributes i .gitignore - Ryan Ransford


Jeśli nie wykluczasz plików za pomocą .gitattributes  export-ignore więc spróbuj git checkout

mkdir /path/to/checkout/
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout -f -q

-fa
  Wyszukując ścieżki z indeksu, nie przestawaj po odłożeniu   wpisy; zamiast tego niezamknięte wpisy są ignorowane.

i

-q
  Unikaj gadatliwego

Dodatkowo możesz uzyskać dowolny Branch lub Tag lub z konkretnej wersji Commit, tak jak w SVN, wystarczy dodać SHA1 (SHA1 w Git jest odpowiednikiem numeru wersji w SVN)

mkdir /path/to/checkout/
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout 2ef2e1f2de5f3d4f5e87df7d8 -f -q -- ./

The /path/to/checkout/ musi być pusty, Git nie usunie żadnego pliku, ale nadpisze pliki o tej samej nazwie bez żadnego ostrzeżenia

AKTUALIZACJA: Aby uniknąć problemu z obciętą głową lub pozostawić nietknięte repozytorium pracujące przy korzystaniu z kasy do eksportu przy użyciu znaczników, oddziałów lub SHA1, musisz dodać -- ./ na końcu

Podwójna kreska -- mówi git, że wszystko za kreskami jest ścieżkami lub plikami, a także w tym przypadku mówi git checkout nie zmieniać HEAD

Przykłady:

To polecenie dostanie tylko katalog libs, a także readme.txt plik z tego właśnie zatwierdzić

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout fef2e1f2de5f3d4f5e87df7d8 -f -q -- ./libs ./docs/readme.txt

Spowoduje to utworzenie (zastąpienie) my_file_2_behind_HEAD.txt dwa razy za głową HEAD^2

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout HEAD^2 -f -q -- ./my_file_2_behind_HEAD.txt

Aby uzyskać eksport innego oddziału

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout myotherbranch -f -q -- ./

Zauważ, że ./ jest względne w stosunku do katalogu głównego repozytorium


20
2017-12-10 17:17



W rzeczywistości, wśród wielu innych i przebojów, działało to najlepiej dla mnie, bez żadnych kompresji, działając dobrze z nagimi repozytoriami (gitolite). - takeshin
Zwróć uwagę, że podczas kasowania SHA1 zostanie utworzony problem "z głową" w repozytorium - user5286776117878
actualy @ITGabs, to nie pobiera folderu ".git". Więc pobrany folder nie jest repozytorium git, więc nie jest technicznie "ścięty" - Fabio Marreco
@FabioMarreco Problem z beatem jest w repozytorium, a nie w eksportowanych / pobranych plikach. Aktualizuję odpowiedź, by uzyskać więcej szczegółów - user5286776117878
To zadziałało dla mnie świetnie. Ale na początku otrzymałem komunikat o błędzie "Nie jest repozytorium git". Następnie odkryłem, że "/ path / to / repo /" musiał wskazywać na folder .git. Tak więc działało to: --git-dir = / path / to / repo / .git - philburk