Führen Sie einen "Git-Export" durch (wie "SVN-Export")?


2356

Ich habe mich gefragt, ob es eine gute "Git-Export" -Lösung gibt, die eine Kopie eines Baums ohne das .gitRepository-Verzeichnis erstellt. Ich kenne mindestens drei Methoden:

  1. git cloneAnschließend wird das .gitRepository-Verzeichnis entfernt.
  2. git checkout-index spielt auf diese Funktionalität an, beginnt aber mit "Lies einfach den gewünschten Baum in den Index ...", was ich nicht ganz sicher bin, wie ich es machen soll.
  3. git-exportist ein Skript eines Drittanbieters, das im Wesentlichen git cloneeinen temporären Speicherort gefolgt von rsync --exclude='.git'einem endgültigen Ziel ausführt.

Keine dieser Lösungen scheint mir wirklich zufriedenstellend zu sein. Das nächstgelegene ist svn exportmöglicherweise Option 1, da für beide das Zielverzeichnis zuerst leer sein muss. Option 2 scheint jedoch noch besser zu sein, vorausgesetzt, ich kann herausfinden, was es bedeutet, einen Baum in den Index einzulesen.


1
@rnrTom: Siehe Somovs Antwort. (In einem Teerarchiv ist nichts "komprimiert").
Etarion

23
@mrTom git archive --format zip --output "output.zip" master -0gibt Ihnen ein unkomprimiertes Archiv (-0 ist das Flag für unkomprimiert). git-scm.com/docs/git-archive .

7
Ich stimme @mrTom zu und denke nicht, dass das Hauptproblem darin besteht, ob das Archiv komprimiert oder nicht komprimiert ist. Mit SVN kann ich exportein 250-kB-Unterverzeichnis direkt aus dem Remote-Repository (das ansonsten 200 MB groß sein könnte, ohne Revisionen) - und ich werde das Netzwerk nur für eine Download-Übertragung von 250 kB (oder so) erreichen. Mit git, archiveauf dem Server aktiviert werden muss (so kann ich es nicht versuchen) - clone --depth 1vom Server kann noch ein Repo von etwa 25 MB abrufen, wo der .gitUnterordner allein 15MB nimmt. Daher würde ich immer noch sagen, dass die Antwort "Nein" ist.
Sdaau

@mrTom die Antwort ist in der Tat JA Siehe die Antwort des OP - der Befehl istgit checkout-index
Nocache

Hier ist ein schöner und einfacher Weg:git archive -o latest.zip HEAD
Evgeni Sergeev

Antworten:


2397

Der wahrscheinlich einfachste Weg, dies zu erreichen, ist mit git archive. Wenn Sie wirklich nur den erweiterten Baum benötigen, können Sie so etwas tun.

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

Die meiste Zeit, in der ich etwas aus Git "exportieren" muss, möchte ich auf jeden Fall ein komprimiertes Archiv, also mache ich so etwas.

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

ZIP-Archiv:

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

git help archive Für weitere Details ist es sehr flexibel.


Beachten Sie, dass das Archiv zwar kein .git-Verzeichnis enthält, jedoch andere versteckte git-spezifische Dateien wie .gitignore, .gitattributes usw. enthält. Wenn Sie diese nicht im Archiv haben möchten, stellen Sie sicher, dass Sie dies tun Verwenden Sie das Attribut export-ignore in einer .gitattributes-Datei und schreiben Sie es fest, bevor Sie Ihr Archiv erstellen. Weiterlesen...


Hinweis: Wenn Sie den Index exportieren möchten, lautet der Befehl

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

(Siehe Gregs Antwort für weitere Details)


198
ZIP-Archiv:git archive --format zip --output /full/path master
Vadim

221
Beachten Sie, dass das Archiv nicht das Verzeichnis .git enthält, sondern andere versteckte git-spezifische Dateien wie .gitignore, .gitattributes usw. Wenn Sie diese nicht möchten, stellen Sie sicher, dass Sie das Attribut export-ignore verwenden eine .gitattributes-Datei und schreiben Sie diese fest, bevor Sie Ihr Archiv erstellen. Siehe füttern.cloud.geek.nz/2010
02/

54
So folgen Sie dem Hinweis von Streams: Sie können dem Befehl eine Zeichenfolge '--prefix = Something /' hinzufügen, um den Verzeichnisnamen zu steuern, der in die Zip-Datei gepackt wird. Wenn Sie beispielsweise git archive --format zip --output /path/to/file.zip --prefix=newdir/ masterdie Ausgabe verwenden, heißt sie "file.zip". Wenn Sie sie jedoch entpacken, lautet das Verzeichnis der obersten Ebene "newdir". (Wenn Sie das Attribut --prefix weglassen, lautet das Verzeichnis der obersten Ebene 'file'.)
Alan W. Smith

89
Der einfachste Weg: git archive -o latest.zip HEADEs wird ein Zip-Archiv erstellt, das den Inhalt des letzten Commits für den aktuellen Zweig enthält. Beachten Sie, dass das Ausgabeformat durch die Erweiterung der Ausgabedatei abgeleitet wird.
Nacho4d

37
Es unterstützt keine Git-Submodule :(
Umpirsky

320

Ich habe herausgefunden, was Option 2 bedeutet. In einem Repository können Sie Folgendes tun:

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

Der Schrägstrich am Ende des Pfads ist wichtig, andernfalls werden die Dateien in / destination mit dem Präfix 'path' angezeigt.

Da der Index in einer normalen Situation den Inhalt des Repositorys enthält, gibt es nichts Besonderes zu tun, um "den gewünschten Baum in den Index einzulesen". Es ist schon da.

Das -aFlag ist erforderlich, um alle Dateien im Index auszuchecken (ich bin nicht sicher, was es bedeutet, dieses Flag in dieser Situation wegzulassen, da es nicht das tut, was ich will). Das -fFlag erzwingt das Überschreiben vorhandener Dateien in der Ausgabe, was dieser Befehl normalerweise nicht tut.

Dies scheint die Art von "Git-Export" zu sein, nach der ich gesucht habe.


73
... und VERGESSEN SIE DEN SLASH AM ENDE NICHT, sonst haben Sie nicht den gewünschten Effekt;)
conny

1
Der git addBefehl ändert den Inhalt im Index. Was also git statusals "festzuschreiben" angezeigt wird, sind die Unterschiede zwischen HEAD und dem Inhalt des Index.
Greg Hewgill

7
@conny: Lies deinen Kommentar, vergiss ihn und führte den Befehl ohne einen abschließenden Schrägstrich aus. Tipp: Befolgen Sie Connys Rat
Znarkus

35
+1 auf Connys Rat. Versuchen Sie auch nicht, '~ / dest /' zu erstellen, da dadurch ein Verzeichnis mit dem Namen '~' in Ihrem Arbeitsverzeichnis erstellt wird und nicht das, was Sie wirklich wollten.
Ratet

5
@KyleHeironimus - Ihre Warnung zur Verwendung von '~ / dest / `ist wahr, wenn Sie Anführungszeichen um Ihren Präfixpfad verwenden, die die Shell anweisen, keine Tilde-Erweiterung durchzuführen. In Ihrem Arbeitsverzeichnis wird ein Verzeichnis namens ~(nicht '~'!) Erstellt. git checkout-indexDiesbezüglich gibt es nichts Besonderes : Gleiches gilt für mkdir '~/dest'( tu das nicht! ). Ein weiterer guter Grund, um Dateinamen zu vermeiden, die zitiert werden müssen (z. B. die ein Leerzeichen enthalten) :-)
Matt Wallis

254

git archive funktioniert auch mit Remote-Repository.

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

Um einen bestimmten Pfad innerhalb des Repos zu exportieren, fügen Sie so viele Pfade hinzu, wie Sie möchten, als letztes Argument für git, z.

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

6
Dies ist die Option, die mir am besten gefällt. Es hat den zusätzlichen Vorteil, dass es auch auf nackten Repositorys funktioniert.
InnaM

5
Eine verbesserte Version ist: git archive --format=tar --prefix=PROJECT_NAME/ --remote=USER@SERVER:PROJECT_NAME.git master | tar -xf - (stellt sicher, dass sich Ihr Archiv in einem Ordner befindet)
Nick

7
Hinweis : Der Server muss diese Funktion aktivieren.
Jakub Narębski

12
Ich habe versucht: git archive --format=zip --output foo.zip --remote=https://github.com/xxx.git masterUnd wurde fatal: Operation wird vom Protokoll nicht unterstützt. Unerwartetes Ende des Befehlsstroms.
Andyf

7
@andyf GitHub hat seinen eigenen Weg: curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf -per docs
Bischof

62

Geben Sie hier die Bildbeschreibung ein

Eine Sonderfallantwort, wenn das Repository auf GitHub gehostet wird.

Einfach benutzen svn export.

Soweit ich weiß, erlaubt Github das nicht archive --remote. Obwohl GitHub svn-kompatibel ist und auf alle Git-Repos svnzugegriffen werden kann, können svn exportSie sie mit ein paar Anpassungen an Ihrer GitHub-URL wie gewohnt verwenden.

Beachten Sie beispielsweise beim Exportieren eines gesamten Repositorys, wie trunkdie URL ersetzt wird master(oder auf was auch immer der HEAD-Zweig des Projekts eingestellt ist ):

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

Und Sie können eine einzelne Datei oder sogar einen bestimmten Pfad oder Ordner exportieren:

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

Beispiel mit jQuery JavaScript Library

Der HEADZweig oder Master - Zweig zur Verfügung stehen mit trunk:

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

Die Nicht- HEAD Filialen sind zugänglich unter /branches/:

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

Alle Tags unter /tags/auf die gleiche Weise:

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

1
git archivefunktioniert gut mit GitHub, solange Sie das git - Protokoll verwenden, Ersetzen Sie einfach https://mit git://in der URL. Ich weiß nicht, warum GitHub diese versteckte Funktion nicht bewirbt.
Neil Mayhew

1
@NeilMayhew Es funktioniert nicht für mich, ich verstehe fatal: The remote end hung up unexpectedly. Versucht auf zwei verschiedenen Servern mit jQuery Github Repo.
Anthony Hatzopoulos

Du hast recht. Ich hatte vergessen, dass ich git config url.<base>.insteadOfdas Remote-Repository zwischengespeichert habe. Ich habe daher file://in der Realität eine URL verwendet. Ich bezweifle, dass git archivedies jemals mit git://URLs funktionieren könnte, da es git-upload-archiveauf der Remote-Seite ausgeführt werden muss. Es sollte möglich sein, das sshProtokoll zu verwenden, außer dass Github es nicht zulässt ( Invalid command: 'git-upload-archive').
Neil Mayhew

Gibt es eine Möglichkeit, ein lokales Server-Tool zu verwenden, das sich wie Github verhält, wenn ich es auf intern gehosteten Git-Repositorys ausführen möchte?
Kriss

1
upvoted - es ist völlig bizarr, dass Git diese Funktion nicht hat und wir müssen auf svn zurückgreifen
Jason S

40

Aus dem Git-Handbuch :

Verwenden des Git-Checkout-Index zum "Exportieren eines gesamten Baums"

Die Präfix-Fähigkeit macht es grundsätzlich trivial, den Git-Checkout-Index als Funktion "Als Baum exportieren" zu verwenden. Lesen Sie einfach den gewünschten Baum in den Index und gehen Sie wie folgt vor:

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


19
Ich denke, die Verwirrung ist der Ausdruck "lese den gewünschten Baum in den Index".
davetron5000

4
Wenn Sie Verzeichnis foo in der Zweigleiste exportieren möchten, dann wäre dies git read-tree bar:fooUnd danach git checkout-index --prefix=export_dir/ -asollten Sie es vielleicht tungit update-index master
Pascal Rosin

1
@ JohnWeldon Müssen Sie zuerst das Repo klonen? Wenn ja, dann würde ich es nicht akzeptieren, da der Sinn des "svn-Exports" eines Unterverzeichnisses darin besteht, direkt eine Kopie dieses Unterverzeichnisses zu erhalten. Wenn jemand ein 1 GB Git-Repo hat und ich nur ein 10-KB-Unterverzeichnis möchte, ist es verrückt, von mir zu verlangen, dass ich das Ganze klone.
Jason S

3
Außerdem würde ich @ davetron5000 mit dem Kommentar "Lies den gewünschten Baum in den Index ein" wiederholen, von dem ich keine Ahnung habe, was er bedeutet.
Jason S

38

Ich habe einen einfachen Wrapper geschrieben git-checkout-index, den Sie wie folgt verwenden können:

git export ~/the/destination/dir

Wenn das Zielverzeichnis bereits vorhanden ist, müssen Sie -foder hinzufügen--force .

Die Installation ist einfach; Legen Sie das Skript einfach irgendwo in Ihrem ab PATHund stellen Sie sicher, dass es ausführbar ist.

Das Github-Repository für git-export


15
Dieser Wrapper ist nicht plattformunabhängig. es stützt sich auf / bin / sh. Wenn Sie also unter Windows arbeiten, funktioniert diese Lösung wahrscheinlich nicht für Sie.
Shovavnik

18
Ähh, dieses Skript besteht aus 57 Zeilen Dokumentation, Leerzeichen, Setup, Argumentanalyse und nur einer Zeile, die tatsächlich etwas bewirkt ...
Vladimir Panteleev

36

Es scheint, dass dies bei Git weniger ein Problem ist als bei SVN. Git legt nur einen .git-Ordner im Repository-Stammverzeichnis ab, während SVN in jedem Unterverzeichnis einen .svn-Ordner ablegt. "SVN-Export" vermeidet also rekursive Befehlszeilenmagie, während bei Git keine Rekursion erforderlich ist.


26
Ab SVN 1.7 gibt es auch nur einen .svn-Ordner: subversion.apache.org/docs/release-notes/1.7.html#single-db
kostmo

Dadurch werden keine zusätzlichen Build-Dateien entfernt, die durch den SVN-Export gelöscht werden. Das ist also definitiv nicht die Antwort.
Ygoe

28

Das Äquivalent von

svn export . otherpath

in einem bestehenden Repo ist

git archive branchname | (cd otherpath; tar x)

Das Äquivalent von

svn export url otherpath

ist

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

1
danke, das war es, was mir gefehlt hat ... auch um die Zeitstempel des Exports zu überprüfen (sie werden nicht wie in den Dateien beibehalten), verwenden Sie git archive --format=tar --prefix=junk/ HEAD | (tar -t -v --full-time -f -)... Die Archivierung mit Zeitstempeln ist jedoch nicht gerade trivial, also habe ich eine gepostet Beispiel unten .
Sdaau

1
Sie können die C-Option für Teer anstelle der Unterschale wie folgt verwenden: git archive branchname | tar xC otherpath
James Moore

Es wird darauf hingewiesen, dass die COption zum Teer nur GNU-Teer ist.
Aredridel

22

Wenn Sie Dateien mit nicht ausschließen, .gitattributes export-ignoreversuchen Sie esgit checkout

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

-f
Wenn Sie Pfade aus dem Index auschecken, schlagen Sie nicht bei nicht zusammengeführten Einträgen fehl. Stattdessen werden nicht zusammengeführte Einträge ignoriert.

und

-q
Vermeiden Sie ausführlich

Zusätzlich können Sie jeden Zweig oder Tag oder von einer bestimmten Commit-Revision wie in SVN erhalten, indem Sie einfach die SHA1 hinzufügen (SHA1 in Git entspricht der Revisionsnummer in SVN).

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

Das /path/to/checkout/ muss leer sein, Git löscht keine Datei, überschreibt aber gleichnamige Dateien ohne Vorwarnung

UPDATE: Um das enthauptete Problem zu vermeiden oder das funktionierende Repository intakt zu lassen, wenn Sie die Kasse für den Export mit Tags, Zweigen oder SHA1 verwenden, müssen Sie hinzufügen -- ./ am Ende

Der doppelte Strich --teilt git mit, dass alles nach den Bindestrichen Pfade oder Dateien sind, und auch in diesem Fall, dass git checkoutdas nicht geändert werden sollHEAD

Beispiele:

Dieser Befehl ruft nur das libs-Verzeichnis und auch die readme.txtDatei von diesem Commit ab

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

Dadurch werden my_file_2_behind_HEAD.txtzwei Commits hinter dem Kopf erstellt (überschrieben)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

Um den Export eines anderen Zweigs zu erhalten

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

Beachten Sie, dass dies ./relativ zum Stammverzeichnis des Repositorys ist


Unter vielen anderen und positiven Stimmen funktionierte dies am besten für mich, ohne Kompressionen, und funktionierte gut mit nackten Repositories (Gitolite).
Takeshin

1
Beachten Sie, dass die SHA1-
Kaufabwicklung

Bei @ITGabs wird der Ordner ".git" nicht heruntergeladen. Der heruntergeladene Ordner ist also kein Git-Repository, daher wird er technisch nicht "enthauptet"
Fabio Marreco

@FabioMarreco Das Enthauptungsproblem befindet sich im Repository nicht in den exportierten / heruntergeladenen Dateien. Ich aktualisiere die Antwort für weitere Details
user5286776117878

3
Das hat bei mir super funktioniert. Aber zuerst bekam ich die Fehlermeldung "Kein Git-Repository". Dann stellte ich fest, dass "/ path / to / repo /" auf den Ordner .git verweisen musste. Das hat also funktioniert: --git-dir = / path / to / repo /
.git

21

Ich benutze Git-Submodule ausgiebig. Dieser funktioniert für mich:

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

1
Würde das nicht Dateien verpassen, deren Namen mit einem Punkt beginnen, wie z .htaccess.
Greg Hewgill

8
Eine gute Lösung, ich würde --exclude = '. *' In --exclude = '. Git *'
schmunk

18
--exclude-vcs, wenn Sie diesen Takt nehmen würden
plod

Kann ./FROM/ ein Remote-Repo sein?
Resist Design

2
Als FYI rsynclistet meine Kopie das Argument als auf --cvs-exclude. Außerdem kopiert es immer noch .gitattributesund.gitignore
Ryan Ransford

19

Ich habe diese Seite häufig aufgerufen, wenn ich nach einer Möglichkeit gesucht habe, ein Git-Repository zu exportieren. Meine Antwort auf diese Frage berücksichtigt drei Eigenschaften, die svn export im Vergleich zu git beabsichtigt hat, da svn einen zentralisierten Repository-Ansatz verfolgt:

  • Es minimiert den Datenverkehr zu einem Remote-Repository-Speicherort, indem nicht alle Revisionen exportiert werden
  • Es enthält keine Metainformationen im Exportverzeichnis
  • Das Exportieren eines bestimmten Zweigs mit svn erfolgt durch Angabe des entsprechenden Pfads

    git clone --depth 1 --branch master git://git.somewhere destination_path
    rm -rf destination_path/.git
    

Wenn Sie eine bestimmte Version erstellen, ist es nützlich, einen stabilen Zweig wie zum Beispiel --branch stableoder zu klonen --branch release/0.9.


Dies funktioniert nicht, wenn das Ziel vorhanden und nicht leer ist.
Gleichnamiger

2
Die einzig wahre Antwort: Sie entsteht aus den Tiefen. Der git archive | tarAnsatz ist nicht auf POSIX-inkompatible Shell-Umgebungen anwendbar (z. B. AppVeyors CMD- oder PowerShell-basiertes CI), was nicht ideal ist. Der git checkoutAnsatz ändert den Index des Hauptarbeitsbaums, was schrecklich ist. Der git checkout-indexAnsatz erfordert, dass der Index des Hauptarbeitsbaums zuvor geändert wird, was noch schlimmer ist. Der traditionelle git cloneAnsatz klont den gesamten Verlauf des Repositorys, bevor dieser Verlauf gelöscht wird, was verschwenderisch ist. Dies ist die einzig vernünftige Lösung.
Cecil Curry

1
Beachten Sie beim lokalen Exportieren, dass dem file://Protokoll der absolute Pfad des zu klonenden Git-Arbeitsbaums das Präfix vorangestellt werden sollte (z git clone --depth 1 --branch v3.14.15 file:///home/me/src_repo trg_repo. B. ). Andernfalls wird "warning: --depth is ignored in local clones; use file:// instead."eher ein Standard als ein flacher Klon ausgegeben und ausgeführt, wodurch der gesamte Zweck dieser Antwort zunichte gemacht wird. Salud!
Cecil Curry

16

Dadurch werden alle Inhalte abzüglich der .dot-Dateien kopiert. Ich verwende dies, um git-geklonte Projekte ohne das .git-Zeug in das Git-Repo meiner Web-App zu exportieren.

cp -R ./path-to-git-repo / path / to / destination /

Einfache alte Bash funktioniert einfach super :)


Warum nicht einfach auf die Fernbedienung drücken? Noch einfacher als Bash.
Nurettin

2
Was ist mit Dateien, die Teil von Webanwendungen sind und deren Name mit Punkt beginnt? :) Denken Sie an .htaccess
Artur

3
Manchmal möchten Sie auch ignorieren, was drin ist .gitignore, das wird nicht.
fregante

14

So einfach wie Klonen, dann löschen Sie den .git-Ordner:

git clone url_of_your_repo path_to_export && rm -rf path_to_export/.git


4
Ehrlich gesagt - diese Antwort, die auch die Nummer 1 in der Frage ist - werden Sie in 99% der Fälle tun. Die meisten dieser Antworten sind verrückt überkompliziert.
Geoff Nixon

11

Für GitHub-Benutzer git archive --remotefunktioniert die Methode nicht direkt, da die Export-URL kurzlebig ist . Sie müssen GitHub nach der URL fragen und diese URL dann herunterladen. curlmacht das einfach:

curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf -

Dadurch erhalten Sie den exportierten Code in einem lokalen Verzeichnis. Beispiel:

$ curl -L https://api.github.com/repos/jpic/bashworks/tarball | tar xzf -
$ ls jpic-bashworks-34f4441/
break  conf  docs  hack  LICENSE  mlog  module  mpd  mtests  os  README.rst  remote  todo  vcs  vps  wepcrack

Bearbeiten
Wenn Sie möchten, dass der Code in ein bestimmtes, vorhandenes Verzeichnis gestellt wird (und nicht in das zufällige von github):

curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | \
tar xzC /path/you/want --strip 1

11

Ja, dies ist ein sauberer und ordentlicher Befehl zum Archivieren Ihres Codes ohne Git-Aufnahme in das Archiv. Es ist gut, ihn weiterzugeben, ohne sich Gedanken über den Verlauf des Git-Commits zu machen.

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

Das ist großartig, muss nur noch gitignore entfernen und es ist fertig und bereit zum Teilen.
Sogger

Das Entfernen von .gitgnore usw. wird in akzeptierten Antwortkommentaren erwähnt: Verwenden Sie die .gitattributes-Datei, siehe feed.cloud.geek.nz/posts/excluding-files-from-git-archive
Sogger

10

Ich möchte nur darauf hinweisen, dass Sie es sind

  1. Exportieren eines Unterordners des Repositorys (so habe ich die SVN-Exportfunktion verwendet)
  2. Sie können alles aus diesem Ordner in das Bereitstellungsziel kopieren
  3. und da Sie bereits eine Kopie des gesamten Repositorys haben.

Dann können Sie einfach cp foo [destination]anstelle der genannten verwenden git-archive master foo | -x -C [destination].


9

Sie können ein Remote-Repo bei jedem Commit als Zip-Datei archivieren.

git archive --format=zip --output=archive.zip --remote=USERNAME@HOSTNAME:PROJECTNAME.git HASHOFGITCOMMIT

8

Bash-Implementierung von Git-Export.

Ich habe die Prozesse zum Erstellen und Entfernen von .empty-Dateien nach ihrer eigenen Funktion segmentiert, um sie in der Implementierung von 'git-archive' wiederzuverwenden (wird später veröffentlicht).

Ich habe dem Prozess auch die Datei '.gitattributes' hinzugefügt, um unerwünschte Dateien aus dem Zielexportordner zu entfernen. Eingeschlossene Ausführlichkeit in den Prozess, während die Funktion "Git-Export" effizienter wird.

EMPTY_FILE = ". Leer";

function create_empty () {
## Processing path (target-dir):
    TRG_PATH="${1}";
## Component(s):
    EXCLUDE_DIR=".git";
echo -en "\nAdding '${EMPTY_FILE}' files to empty folder(s): ...";
    find ${TRG_PATH} -not -path "*/${EXCLUDE_DIR}/*" -type d -empty -exec touch {}/${EMPTY_FILE} \;
#echo "done.";
## Purging SRC/TRG_DIRs variable(s):
    unset TRG_PATH EMPTY_FILE EXCLUDE_DIR;
    return 0;
  }

declare -a GIT_EXCLUDE;
function load_exclude () {
    SRC_PATH="${1}";
    ITEMS=0; while read LINE; do
#      echo -e "Line [${ITEMS}]: '${LINE%%\ *}'";
      GIT_EXCLUDE[((ITEMS++))]=${LINE%%\ *};
    done < ${SRC_PATH}/.gitattributes;
    GIT_EXCLUDE[${ITEMS}]="${EMPTY_FILE}";
## Purging variable(s):
    unset SRC_PATH ITEMS;
    return 0;
  }

function purge_empty () {
## Processing path (Source/Target-dir):
    SRC_PATH="${1}";
    TRG_PATH="${2}";
echo -e "\nPurging Git-Specific component(s): ... ";
    find ${SRC_PATH} -type f -name ${EMPTY_FILE} -exec /bin/rm '{}' \;
    for xRULE in ${GIT_EXCLUDE[@]}; do
echo -en "    '${TRG_PATH}/{${xRULE}}' files ... ";
      find ${TRG_PATH} -type f -name "${xRULE}" -exec /bin/rm -rf '{}' \;
echo "done.'";
    done;
echo -e "done.\n"
## Purging SRC/TRG_PATHs variable(s):
    unset SRC_PATH; unset TRG_PATH;
    return 0;
  }

function git-export () {
    TRG_DIR="${1}"; SRC_DIR="${2}";
    if [ -z "${SRC_DIR}" ]; then SRC_DIR="${PWD}"; fi
    load_exclude "${SRC_DIR}";
## Dynamically added '.empty' files to the Git-Structure:
    create_empty "${SRC_DIR}";
    GIT_COMMIT="Including '${EMPTY_FILE}' files into Git-Index container."; #echo -e "\n${GIT_COMMIT}";
    git add .; git commit --quiet --all --verbose --message "${GIT_COMMIT}";
    if [ "${?}" -eq 0 ]; then echo " done."; fi
    /bin/rm -rf ${TRG_DIR} && mkdir -p "${TRG_DIR}";
echo -en "\nChecking-Out Index component(s): ... ";
    git checkout-index --prefix=${TRG_DIR}/ -q -f -a
## Reset: --mixed = reset HEAD and index:
    if [ "${?}" -eq 0 ]; then
echo "done."; echo -en "Resetting HEAD and Index: ... ";
        git reset --soft HEAD^;
        if [ "${?}" -eq 0 ]; then
echo "done.";
## Purging Git-specific components and '.empty' files from Target-Dir:
            purge_empty "${SRC_DIR}" "${TRG_DIR}"
          else echo "failed.";
        fi
## Archiving exported-content:
echo -en "Archiving Checked-Out component(s): ... ";
        if [ -f "${TRG_DIR}.tgz" ]; then /bin/rm ${TRG_DIR}.tgz; fi
        cd ${TRG_DIR} && tar -czf ${TRG_DIR}.tgz ./; cd ${SRC_DIR}
echo "done.";
## Listing *.tgz file attributes:
## Warning: Un-TAR this file to a specific directory:
        ls -al ${TRG_DIR}.tgz
      else echo "failed.";
    fi
## Purgin all references to Un-Staged File(s):
   git reset HEAD;
## Purging SRC/TRG_DIRs variable(s):
    unset SRC_DIR; unset TRG_DIR;
    echo "";
    return 0;
  }

Ausgabe:

$ git-export /tmp/rel-1.0.0

Hinzufügen von '.empty'-Dateien zu leeren Ordnern: ... fertig.

Check-Out-Indexkomponente (n): ... fertig.

HEAD und Index zurücksetzen: ... fertig.

Git-spezifische Komponente (n) löschen: ...

'/tmp/rel-1.0.0/{.buildpath}' files ... done. '

'/tmp/rel-1.0.0/{.project}' files ... done. '

'/tmp/rel-1.0.0/{.gitignore}' Dateien ... fertig. '

'/tmp/rel-1.0.0/{.git}' Dateien ... fertig. '

'/tmp/rel-1.0.0/{.gitattributes}' Dateien ... fertig. '

'/tmp/rel-1.0.0/{*.mno}' Dateien ... fertig. '

'/tmp/rel-1.0.0/{*~}' files ... done.

'/tmp/rel-1.0.0/{.*~}' files ... done. '

'/tmp/rel-1.0.0/{*.swp}' Dateien ... fertig. '

'/tmp/rel-1.0.0/{*.swo}' Dateien ... fertig. '

'/tmp/rel-1.0.0/{.DS_Store}' Dateien ... fertig. '

'/tmp/rel-1.0.0/{.settings}' Dateien ... fertig. '

'/tmp/rel-1.0.0/{.empty}' Dateien ... fertig. '

erledigt.

Archivierung Check-Out-Komponente (n): ... fertig.

-rw-r - r-- 1 Administratorrad 25445901 3. November 12:57 /tmp/rel-1.0.0.tgz

Ich habe jetzt die Funktion "Git-Archiv" in einen einzigen Prozess integriert, der die Funktion "create_empty" und andere Funktionen verwendet.

function git-archive () {
    PREFIX="${1}"; ## sudo mkdir -p ${PREFIX}
    REPO_PATH="`echo "${2}"|awk -F: '{print $1}'`";
    RELEASE="`echo "${2}"|awk -F: '{print $2}'`";
    USER_PATH="${PWD}";
echo "$PREFIX $REPO_PATH $RELEASE $USER_PATH";
## Dynamically added '.empty' files to the Git-Structure:
    cd "${REPO_PATH}"; populate_empty .; echo -en "\n";
#    git archive --prefix=git-1.4.0/ -o git-1.4.0.tar.gz v1.4.0
# e.g.: git-archive /var/www/htdocs /repos/domain.name/website:rel-1.0.0 --explode
    OUTPUT_FILE="${USER_PATH}/${RELEASE}.tar.gz";
    git archive --verbose --prefix=${PREFIX}/ -o ${OUTPUT_FILE} ${RELEASE}
    cd "${USER_PATH}";
    if [[ "${3}" =~ [--explode] ]]; then
      if [ -d "./${RELEASE}" ]; then /bin/rm -rf "./${RELEASE}"; fi
      mkdir -p ./${RELEASE}; tar -xzf "${OUTPUT_FILE}" -C ./${RELEASE}
    fi
## Purging SRC/TRG_DIRs variable(s):
    unset PREFIX REPO_PATH RELEASE USER_PATH OUTPUT_FILE;
    return 0;
  }

Verwendung: Git-Archiv [/ var / www / htdocs] /repos/web.domain/website:rel-1.0.0
tocororo

8

Wenn Sie etwas wollen, das mit Submodulen funktioniert, ist dies möglicherweise einen Versuch wert.

Hinweis:

  • MASTER_DIR = eine Kasse, bei der auch Ihre Submodule ausgecheckt sind
  • DEST_DIR = wo dieser Export enden wird
  • Wenn Sie rsync haben, können Sie wahrscheinlich dasselbe mit noch weniger Ballschmerzen tun.

Annahmen:

  • Sie müssen dies aus dem übergeordneten Verzeichnis von MASTER_DIR ausführen (dh aus der MASTER_DIR-CD ..).
  • Es wird angenommen, dass DEST_DIR erstellt wurde. Dies ist ziemlich einfach zu ändern, um die Erstellung eines DEST_DIR einzuschließen, wenn Sie möchten

cd MASTER_DIR && tar -zcvf ../DEST_DIR/export.tar.gz --exclude = '. git *'. && cd ../DEST_DIR/ && tar xvfz export.tar.gz && rm export.tar.gz


6

Meine Präferenz wäre eigentlich, einen dist zu haben Ziel in Ihrem Makefile (oder einem anderen Build-System) zu haben, das ein verteilbares Archiv Ihres Codes exportiert (.tar.bz2, .zip, .jar oder was auch immer angemessen ist). Wenn Sie zufällig GNU-Autotools oder Perls MakeMaker-Systeme verwenden, ist dies meiner Meinung nach automatisch für Sie vorhanden. Wenn nicht, empfehle ich dringend, es hinzuzufügen.

ETA (06.09.2012): Wow, harte Downvotes. Ich glaube immer noch, dass es besser ist, Ihre Distributionen mit Ihren Build-Tools zu erstellen, als mit Ihrem Quellcode-Kontroll-Tool. Ich glaube daran, Artefakte mit Build-Tools zu erstellen. In meinem aktuellen Job wird unser Hauptprodukt mit einem Ameisenziel gebaut. Wir sind gerade dabei, Quellcode-Kontrollsysteme zu wechseln, und das Vorhandensein dieses Ameisenziels bedeutet einen Aufwand weniger bei der Migration.


Das Projekt, an das ich gedacht habe, ist kein Code-Projekt. Es ist eher so wie bei einem Website-Projekt.
Greg Hewgill

Behandelt die Frage nicht.
Andrew Ferrier

1
Ja, eine solche Antwort passt vielleicht nicht zu allen Bedürfnissen, aber die Abstimmungen sind bizarr. Es ist eine absolut gültige Antwort und in vielen Szenarien die einzig richtige Antwort. Es ist sehr zutreffend, dass das Denken an dieses Problem als "VC-Tool-Problem" oft völlig falsch verläuft.
Snogglethorpe

6

Dadurch werden die Dateien in einer Reihe von Commits (C bis G) in eine TAR-Datei kopiert. Hinweis: Dadurch werden nur die Dateien festgeschrieben. Nicht das gesamte Repository. Von hier leicht modifiziert

Beispiel für einen Commit-Verlauf

A -> B -> C -> D -> E -> F -> G -> H -> I.

git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT C~..G | xargs tar -rf myTarFile.tar

git-diff-tree Handbuch Seite

-r -> in Unterbäume zurückgreifen

--no-commit-id -> git diff-tree gibt gegebenenfalls eine Zeile mit der Commit-ID aus. Dieses Flag unterdrückte die Ausgabe der Festschreibungs-ID.

--name-only -> Nur Namen geänderter Dateien anzeigen.

--diff-filter = ACMRT -> Nur diese Dateien auswählen. Eine vollständige Liste der Dateien finden Sie hier

C..G -> Dateien in diesem Commit-Bereich

C ~ -> Dateien aus Commit C einschließen. Nicht nur Dateien seit Commit C.

| xargs tar -rf myTarFile -> gibt an tar aus


5

Nach meinem Verständnis geht es eher darum, nur einen bestimmten Status vom Server herunterzuladen, ohne Verlauf und ohne Daten anderer Zweige, als einen Status aus einem lokalen Repository zu extrahieren (wie es viele Antworten hier tun).

Das kann so gemacht werden:

git clone -b someBranch --depth 1 --single-branch git://somewhere.com/repo.git \
&& rm -rf repo/.git/
  • --single-branch ist seit Git 1.7.10 (April 2012) verfügbar.
  • --depth ist war?) angeblich fehlerhaft, aber für den Fall eines Exports sollten die genannten Probleme keine Rolle spielen.

Hinweis: Ich habe gerade bemerkt, dass es 2 Seiten mit Antworten gibt. Ich habe mir vor dem Posten nur eine angesehen. Es gibt nur eine ähnliche Antwort mit --depth, was impliziert, --single-branchwenn nichts --no-single-branchangegeben ist, was bedeutet, dass dies wahrscheinlich den gleichen Effekt hat. Nicht sicher, kann ein Experte bestätigen?
Ondra Žižka

4

Ich brauchte dies für ein Bereitstellungsskript und konnte keinen der oben genannten Ansätze verwenden. Stattdessen habe ich eine andere Lösung gefunden:

#!/bin/sh
[ $# -eq 2 ] || echo "USAGE $0 REPOSITORY DESTINATION" && exit 1
REPOSITORY=$1
DESTINATION=$2
TMPNAME="/tmp/$(basename $REPOSITORY).$$"
git clone $REPOSITORY $TMPNAME
rm -rf $TMPNAME/.git
mkdir -p $DESTINATION
cp -r $TMPNAME/* $DESTINATION
rm -rf $TMPNAME

Was war das Problem mit einer Lesebaum- / Checkout-Index- oder Archivlösung? Soweit ich das beurteilen kann, haben Sie das Äquivalent von etwas getan, das mkdir -p "$2" && git --git-dir="$1" archive HEAD | tar -x -C "$2"etwas länger ist.
CB Bailey

1
Ich konnte den Lesebaum nicht aus einem Remote-Repository zum Laufen bringen, und die Archivlösung funktioniert nicht mit Github.
Troelskn

Ja, mit Archiv erhalten Sie einen ungültigen Befehl: 'git-upload-archive' ... Fehler und ich habe keine Konfigurationsoption core.gitProxy und die Umgebungsvariable GIT_PROXY_COMMAND gesetzt
tgkprog

4

Auf einfache Weise ist dies eine Funktion für .bash_profile. Sie entpackt das Archiv direkt am aktuellen Speicherort und konfiguriert zuerst Ihren üblichen [url: path]. HINWEIS: Mit dieser Funktion vermeiden Sie den Klonvorgang, der direkt vom Remote-Repo abgerufen wird.

gitss() {
    URL=[url:path]

    TMPFILE="`/bin/tempfile`"
    if [ "$1" = "" ]; then
        echo -e "Use: gitss repo [tree/commit]\n"
        return
    fi
    if [ "$2" = "" ]; then
        TREEISH="HEAD"
    else
        TREEISH="$2"
    fi
    echo "Getting $1/$TREEISH..."
    git archive --format=zip --remote=$URL/$1 $TREEISH > $TMPFILE && unzip $TMPFILE && echo -e "\nDone\n"
    rm $TMPFILE
}

Alias ​​für .gitconfig, gleiche Konfiguration erforderlich (TAKE CARE führt den Befehl in .git-Projekten aus, er springt IMMER wie zuvor beschrieben zum Basisverzeichnis , bis dies behoben ist. Ich persönlich bevorzuge die Funktion

ss = !env GIT_TMPFILE="`/bin/tempfile`" sh -c 'git archive --format=zip --remote=[url:path]/$1 $2 \ > $GIT_TMPFILE && unzip $GIT_TMPFILE && rm $GIT_TMPFILE' -

4

Bei weitem der einfachste Weg, den ich gesehen habe (und auch unter Windows funktioniert), ist git bundle:

git bundle create /some/bundle/path.bundle --all

Weitere Informationen finden Sie in dieser Antwort: Wie kann ich mein Git-Repository von meinem Windows-Computer über ein USB-Laufwerk auf einen Linux-Computer kopieren?


git bundleenthält den .gitOrdner, den das OP nicht möchte; git archivescheint der angemessenere Weg
ssc

Wo ist die Dokumentation zum --allSwitch?
Garret Wilson

4

Ich habe eine andere Lösung, die gut funktioniert, wenn Sie eine lokale Kopie des Repositorys auf dem Computer haben, auf dem Sie den Export erstellen möchten. In diesem Fall wechseln Sie in dieses Repository-Verzeichnis und geben Sie den folgenden Befehl ein:

GIT_WORK_TREE=outputdirectory git checkout -f

Dies ist besonders nützlich, wenn Sie eine Website mit einem Git-Repository verwalten und eine saubere Version in auschecken möchten /var/www/. Fügen Sie in diesem Fall diesen Befehl in ein .git/hooks/post-receiveSkript ein ( hooks/post-receivein ein nacktes Repository, das in dieser Situation besser geeignet ist).


3

Ich denke, @Aredridels Beitrag war am nächsten, aber da steckt noch ein bisschen mehr dahinter - also werde ich dies hier hinzufügen. Die Sache ist, svnwenn Sie sich in einem Unterordner eines Repos befinden und Folgendes tun:

/media/disk/repo_svn/subdir$ svn export . /media/disk2/repo_svn_B/subdir

dann svnwerden alle Dateien exportieren , die unter Revisionskontrolle sind (sie auch frisch hinzugefügt haben könnte, oder Modified - Zustand) - und wenn Sie andere „Junk“ in diesem Verzeichnis haben (und ich bin nicht mitgerechnet .svnUnterordner hier, aber sichtbare Dinge wie .oDateien) wird es nicht exportiert; Es werden nur die vom SVN-Repo registrierten Dateien exportiert. Für mich ist eine schöne Sache, dass dieser Export auch Dateien mit lokalen Änderungen enthält, die noch nicht festgeschrieben wurden. und eine andere schöne Sache ist, dass die Zeitstempel der exportierten Dateien die gleichen sind wie die Originaldateien. Oder wie svn help exportes heißt:

  1. Exportiert einen sauberen Verzeichnisbaum aus der von PATH1 angegebenen Arbeitskopie bei Revision REV, wenn er andernfalls bei WORKING angegeben ist, in PATH2. ... Wenn REV nicht angegeben ist, bleiben alle lokalen Änderungen erhalten. Dateien, die nicht der Versionskontrolle unterliegen, werden nicht kopiert.

gitVergleichen Sie die Ausgabe dieser Befehle (in einem Unterordner eines gitRepos Ihrer Wahl) , um festzustellen, dass die Zeitstempel nicht erhalten bleiben :

/media/disk/git_svn/subdir$ ls -la .

... und:

/media/disk/git_svn/subdir$ git archive --format=tar --prefix=junk/ HEAD | (tar -t -v --full-time -f -)

... und ich git archivestelle auf jeden Fall fest, dass alle Zeitstempel der archivierten Datei gleich sind! git help archivesagt:

Das Git-Archiv verhält sich bei Angabe einer Baum-ID anders als bei Angabe einer Commit-ID oder Tag-ID. Im ersten Fall wird die aktuelle Zeit als Änderungszeit für jede Datei im Archiv verwendet. Im letzteren Fall wird stattdessen die Festschreibungszeit verwendet, die im referenzierten Festschreibungsobjekt aufgezeichnet wurde.

... aber anscheinend setzen beide Fälle die "Änderungszeit jeder Datei"; dabei nicht bleiben die tatsächlichen Zeitstempel dieser Dateien erhalten!

Um auch die Zeitstempel beizubehalten, ist hier ein bashSkript, das eigentlich ein "Einzeiler" ist, wenn auch etwas kompliziert - daher wird es unten in mehreren Zeilen veröffentlicht:

/media/disk/git_svn/subdir$ git archive --format=tar master | (tar tf -) | (\
  DEST="/media/diskC/tmp/subdirB"; \
  CWD="$PWD"; \
  while read line; do \
    DN=$(dirname "$line"); BN=$(basename "$line"); \
    SRD="$CWD"; TGD="$DEST"; \
    if [ "$DN" != "." ]; then \
      SRD="$SRD/$DN" ; TGD="$TGD/$DN" ; \
      if [ ! -d "$TGD" ] ; then \
        CMD="mkdir \"$TGD\"; touch -r \"$SRD\" \"$TGD\""; \
        echo "$CMD"; \
        eval "$CMD"; \
      fi; \
    fi; \
    CMD="cp -a \"$SRD/$BN\" \"$TGD/\""; \
    echo "$CMD"; \
    eval "$CMD"; \
    done \
)

Beachten Sie, dass davon ausgegangen wird, dass Sie den Inhalt in das "aktuelle" Verzeichnis (oben /media/disk/git_svn/subdir) exportieren - und das Ziel, in das Sie exportieren, etwas ungünstig platziert ist, sich jedoch in einer DESTUmgebungsvariablen befindet. Beachten Sie, dass mit diesem Skript; Sie müssen die erstellenDEST Verzeichnis manuell selbst , bevor Sie das obige Skript ausführen.

Nachdem das Skript ausgeführt wurde, sollten Sie in der Lage sein zu vergleichen:

ls -la /media/disk/git_svn/subdir
ls -la /media/diskC/tmp/subdirB   # DEST

... und hoffentlich die gleichen Zeitstempel sehen (für die Dateien, die unter Versionskontrolle standen).

Hoffe das hilft jemandem,
Prost!


3

Ein Git-Export in ein Zip-Archiv beim Hinzufügen eines Präfixes (z. B. Verzeichnisname):

git archive master --prefix=directoryWithinZip/  --format=zip -o out.zip


1

Ich habe die folgende Dienstprogrammfunktion in meiner .bashrc-Datei: Es erstellt ein Archiv des aktuellen Zweigs in einem Git-Repository.

function garchive()
{
  if [[ "x$1" == "x-h" || "x$1" == "x" ]]; then
    cat <<EOF
Usage: garchive <archive-name>
create zip archive of the current branch into <archive-name>
EOF
  else
    local oname=$1
    set -x
    local bname=$(git branch | grep -F "*" | sed -e 's#^*##')
    git archive --format zip --output ${oname} ${bname}
    set +x
  fi
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.