Ich habe mich gefragt, ob es eine gute "Git-Export" -Lösung gibt, die eine Kopie eines Baums ohne das Repository-Verzeichnis _.git
_ erstellt. Ich kenne mindestens drei Methoden:
git clone
_ gefolgt vom Entfernen des Repository-Verzeichnisses _.git
_.git checkout-index
spielt auf diese Funktionalität an, beginnt aber mit "Einfach den gewünschten Baum in den Index einlesen ...", was ich nicht ganz genau weiß.git-export
ist ein Skript eines Drittanbieters, das im Wesentlichen ein _git clone
_ an einem temporären Ort ausführt, gefolgt von _rsync --exclude='.git'
_ am endgültigen Ziel.Keine dieser Lösungen scheint mir wirklich zufriedenstellend zu sein. Der _svn export
_ am nächsten liegende ist möglicherweise Option 1, da bei beiden das Zielverzeichnis zuerst leer sein muss. Aber Option 2 scheint noch besser zu sein, vorausgesetzt, ich kann herausfinden, was es bedeutet, einen Baum in den Index einzulesen.
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 ziemlich flexibel.
Beachten Sie, dass das Archiv zwar nicht das Verzeichnis .git enthält, jedoch andere verborgene git-spezifische Dateien wie .gitignore, .gitattributes usw. enthält. Wenn Sie sie nicht im Archiv haben möchten, müssen Sie dies sicherstellen Verwenden Sie das export-ignore-Attribut in einer .gitattributes-Datei und schreiben Sie dies 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)
Ich habe herausgefunden, was Option 2 bedeutet. Aus einem Repository können Sie Folgendes ausführen:
git checkout-index -a -f --prefix=/destination/path/
Der Schrägstrich am Ende des Pfades ist wichtig, da sonst die Dateien in/destination mit dem Präfix 'path' abgelegt werden.
Da der Index im Normalfall den Inhalt des Repositorys enthält, ist nichts Besonderes zu tun, um "den gewünschten Baum in den Index einzulesen". Es ist schon da.
Das -a
-Flag 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 -f
-Flag erzwingt das Überschreiben vorhandener Dateien in der Ausgabe, was dieser Befehl normalerweise nicht ausführt.
Dies scheint die Art von "Git-Export" zu sein, nach der ich gesucht habe.
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
Verwenden Sie einfach svn export
.
Soweit ich weiß, erlaubt Github archive --remote
nicht. Obwohl GitHub svn-kompatibel ist und alle Git-Repos svn
verfügbar sind, können Sie svn export
wie gewohnt mit ein paar Anpassungen an Ihrer GitHub-URL verwenden.
Wenn Sie beispielsweise ein gesamtes Repository exportieren möchten, beachten Sie, dass trunk
in der URL master
ersetzt (oder auf was auch immer der Zweig des Projekts HEAD festgelegt 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
Der Zweig HEAD
oder Master ist über trunk
verfügbar:
svn ls https://github.com/jquery/jquery/trunk
Die nicht-HEAD
Zweige sind unter /branches/
zugänglich:
svn ls https://github.com/jquery/jquery/branches/2.1-stable
Alle Tags unter /tags/
auf dieselbe Weise:
svn ls https://github.com/jquery/jquery/tags/2.1.3
Aus dem Git Manual :
Git-checkout-index verwenden, um "einen ganzen Baum zu exportieren"
Die Präfix-Fähigkeit macht es im Grunde trivial, git-checkout-index als "Export als Baum" -Funktion zu verwenden. Lies einfach den gewünschten Baum in den Index und mache:
$ git checkout-index --prefix=git-export-dir/ -a
Ich habe einen einfachen Wrapper um git-checkout-index
geschrieben, den Sie folgendermaßen verwenden können:
git export ~/the/destination/dir
Wenn das Zielverzeichnis bereits vorhanden ist, müssen Sie -f
oder --force
hinzufügen.
Die Installation ist einfach; Legen Sie das Skript einfach irgendwo in Ihrem PATH
ab und vergewissern Sie sich, dass es ausführbar ist.
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 einen .svn-Ordner in jedem Unterverzeichnis ablegt. "Svn export" vermeidet also rekursive Befehlszeilenmagie, während bei Git keine Rekursion erforderlich ist.
Das Äquivalent von
svn export . otherpath
in einem vorhandenen 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)
Wenn Sie Dateien mit .gitattributes
export-ignore
nicht ausschließen, versuchen Sie git 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 bei nicht zusammengeführten Einträgen nicht fehl. Stattdessen werden nicht zusammengeführte Einträge ignoriert.
und
-q
Vermeiden Sie ausführlich
Zusätzlich können Sie einen Zweig, ein Tag oder eine bestimmte Commit-Revision wie in SVN erhalten, indem Sie einfach den 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 -- ./
Der /path/to/checkout/
muss leer sein, Git löscht keine Datei, überschreibt jedoch Dateien mit demselben Namen ohne Vorwarnung
UPDATE: Um das enthauptete Problem zu vermeiden oder das funktionierende Repository bei Verwendung von Checkout für den Export mit Tags, Zweigen oder SHA1 intakt zu lassen, müssen Sie am Ende -- ./
hinzufügen
Der doppelte Bindestrich --
sagt git, dass alles nach den Bindestrichen Pfade oder Dateien sind, und auch in diesem Fall sagt git checkout
, dass das HEAD
nicht geändert werden soll.
Beispiele:
Dieser Befehl ruft genau das libs-Verzeichnis und auch die readme.txt
-Datei von diesem Commit ab
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout fef2e1f2de5f3d4f5e87df7d8 -f -q -- ./libs ./docs/readme.txt
Dies erzeugt (überschreibt) my_file_2_behind_HEAD.txt
zwei Commits hinter dem Kopf 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 einer anderen Filiale zu bekommen
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout myotherbranch -f -q -- ./
Beachten Sie, dass ./
relativ zum Stammverzeichnis des Repositorys ist
Ich benutze Git-Submodule ausgiebig. Dieser arbeitet für mich:
rsync -a ./FROM/ ./TO --exclude='.*'
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 bezieht sich auf drei Eigenschaften, die svn export im Vergleich zu git hat, da svn einem zentralisierten Repository-Ansatz folgt:
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 ein bestimmtes Release erstellen, ist es nützlich, einen stabilen Zweig wie beispielsweise --branch stable
oder --branch release/0.9
zu klonen.
Dadurch wird der gesamte Inhalt ohne die 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 toll :)
So einfach wie das Klonen, dann lösche den .git Ordner:
git clone url_of_your_repo path_to_export && rm -rf path_to_export/.git
Ja, this ist ein sauberer und ordentlicher Befehl zum Archivieren Ihres Codes, ohne dass ein Git in das Archiv aufgenommen wird.
git archive --format Zip --output /full/path/to/zipfile.Zip master
Ich möchte nur darauf hinweisen, dass in dem Fall, dass Sie sind
Dann können Sie einfach cp foo [destination]
anstelle des erwähnten git-archive master foo | -x -C [destination]
verwenden.
Für GitHub-Benutzer funktioniert die git archive --remote
-Methode nicht direkt, da die Export-URL ist kurzlebig . Sie müssen GitHub nach der URL fragen und diese dann herunterladen. curl
macht 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 den Code in ein bestimmtes existierendes Verzeichnis schreiben möchten (anstelle des zufälligen von github):
curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | \
tar xzC /path/you/want --strip 1
Sie können ein Remote-Repo bei jedem Commit als Zip-Datei archivieren.
git archive --format=Zip --output=archive.Zip [email protected]:PROJECTNAME.git HASHOFGITCOMMIT
Wenn Sie etwas wollen, das mit Submodulen funktioniert, ist dies möglicherweise einen Versuch wert.
Hinweis:
Annahmen:
cd MASTER_DIR && tar -zcvf ../DEST_DIR/export.tar.gz --exclude = '. git *'. && cd ../DEST_DIR/ && tar xvfz export.tar.gz && rm export.tar.gz
Bash-Implementierung von Git-Export.
Ich habe die Erstellungs- und Entfernungsprozesse für .empty-Dateien nach ihrer eigenen Funktion unterteilt, 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. Fügte dem Prozess Ausführlichkeit bei, während die Funktion 'Git-Export' effizienter wurde.
EMPTY_FILE = ". Empty";
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-Index-Komponente (n): ... erledigt.
Zurücksetzen von HEAD und Index: ... erfolgt.
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}' files ... done. '
'/tmp/rel-1.0.0/{.git}' files ... done. '
'/tmp/rel-1.0.0/{.gitattributes}' files ... done. '
'/tmp/rel-1.0.0/{*.mno}' files ... done. '
'/tmp/rel-1.0.0/{*~}' files ... done. '
'/tmp/rel-1.0.0/{.*~}' files ... done. '
'/tmp/rel-1.0.0/{*.swp}' files ... done. '
'/tmp/rel-1.0.0/{*.swo}' files ... done. '
'/tmp/rel-1.0.0/{.DS_Store}' files ... done. '
'/tmp/rel-1.0.0/{.settings}' files ... done. '
'/tmp/rel-1.0.0/{.empty}' files ... done. '
getan.
Archivierung ausgecheckter Komponenten: ... erledigt.
-rw-r - r-- 1 Administrator-Rad 25445901 3 Nov 12:57 /tmp/rel-1.0.0.tgz
Ich habe jetzt die "Git-Archiv" -Funktionalität in einen einzelnen Prozess integriert, der die "create_empty" -Funktion und andere Funktionen nutzt.
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;
}
Eigentlich würde ich es vorziehen, ein dist - Ziel in Ihrem Makefile (oder einem anderen Build-System) zu haben, das ein verteilbares Archiv Ihres Codes (.tar.bz2, .Zip, .jar oder was auch immer angebracht ist) exportiert ). Wenn Sie zufällig GNU Autotools oder Perls MakeMaker-Systeme verwenden, gibt es diese meiner Meinung nach automatisch für Sie. Wenn nicht, empfehle ich das Hinzufügen.
ETA (2012-09-06): Wow, harte Ablehnungen. 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 meiner jetzigen Arbeit wird unser Hauptprodukt mit einem Ameisenziel gebaut. Wir sind mitten in der Umstellung der Quellcode-Kontrollsysteme, und das Vorhandensein dieses Ameisenziels bedeutet einen geringeren Aufwand bei der Migration.
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. Leicht modifiziert von hier
Beispiel Commit-Verlauf
A -> B -> C -> D -> E -> F -> G -> H -> ich
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT C~..G | xargs tar -rf myTarFile.tar
-r -> Rekursion in Unterbäume
--no-commit-id -> git diff-tree gibt gegebenenfalls eine Zeile mit der Festschreibungs-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 Bereich von Commits
C ~ -> Dateien aus Commit C einschließen. Nicht nur Dateien seit Commit C.
| xargs tar -rf myTarFile -> gibt tar aus
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
Wie ich die Frage verstehe, geht es eher darum, nur einen bestimmten Status vom Server herunterzuladen, ohne Historie und ohne Daten anderer Zweige, anstatt einen Status aus einem lokalen Repository zu extrahieren (wie es viele Antworten hier tun).
Das geht so:
git clone -b someBranch --depth 1 --single-branch git://somewhere.com/repo.git \
&& rm -rf repo/.git/
--single-branch
ist verfügbar seit Git 1.7.10 (April 2012).--depth
ist (war?) Berichten zufolge fehlerhaft, aber für den Fall eines Exports sollten die genannten Probleme keine Rolle spielen.Auf einfache Weise ist dies eine Funktion für .bash_profile, die das Archiv direkt am aktuellen Speicherort entpackt. Konfigurieren Sie zunächst Ihren üblichen [url: path]. HINWEIS: Mit dieser Funktion vermeiden Sie den Klonvorgang, er wird direkt vom Remote-Repo abgerufen.
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 beim Ausführen des Befehls in .git-Projekten, es springt IMMER zum Basisverzeichnis vorher wie hier gesagt , bis dies behoben ist, bevorzuge ich persönlich 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' -
Ich denke, @ Aredridel s Beitrag war am nächsten, aber dazu gehört noch ein bisschen mehr - also werde ich das hier hinzufügen. Die Sache ist, in svn
, wenn Sie in einem Unterordner eines Repos sind und Sie tun:
/media/disk/repo_svn/subdir$ svn export . /media/disk2/repo_svn_B/subdir
dann exportiert svn
alle Dateien, die sich unter Versionskontrolle befinden (sie könnten auch frisch hinzugekommen sein oder den Status "Geändert" haben) - und wenn Sie andere "Junk" in diesem Verzeichnis haben (und ich zähle nicht .svn
Unterordner hier, aber sichtbare Dinge wie .o
Dateien), es wird nicht exportiert; Es werden nur die vom SVN-Repo registrierten Dateien exportiert. Für mich ist eine nette Sache, dass dieser Export auch Dateien mit lokalen Änderungen enthält, die noch nicht festgeschrieben wurden; und eine andere nette sache ist, dass die zeitstempel der exportierten dateien die gleichen sind wie die originalen. Oder, wie es svn help export
ausdrückt:
- Exportiert einen sauberen Verzeichnisbaum aus der in PATH1 angegebenen Arbeitskopie mit der Revision REV, sofern dieser angegeben ist, andernfalls mit WORKING in PATH2. ... Wenn REV nicht angegeben wird, bleiben alle lokalen Änderungen erhalten. Dateien, die nicht der Versionskontrolle unterliegen, werden nicht kopiert.
Um zu erkennen, dass git
die Zeitstempel nicht beibehält, vergleichen Sie die Ausgabe dieser Befehle (in einem Unterordner eines git
-Repos Ihrer Wahl):
/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 bemerke auf jeden Fall, dass git archive
bewirkt, dass alle Zeitstempel der archivierten Datei gleich sind! git help archive
sagt:
git archive verhält sich bei einer Baum-ID anders als bei 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 im referenzierten Festschreibungsobjekt aufgezeichnete Festschreibungszeit verwendet.
... aber anscheinend setzen beide Fälle die "Änderungszeit für jede Datei"; Dadurch werden die tatsächlichen Zeitstempel dieser Dateien nicht beibehalten!
Um auch die Zeitstempel beizubehalten, ist hier ein bash
Skript, das eigentlich ein "Einzeiler" ist, wenn auch etwas kompliziert.
/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 exportieren (oben, /media/disk/git_svn/subdir
) - und das Ziel, in das Sie exportieren, etwas ungünstig platziert ist, sich jedoch in der Umgebung DEST
befindet Variable. Beachten Sie, dass mit diesem Skript; Sie müssen das Verzeichnis DEST
manuell erstellen, bevor Sie das obige Skript ausführen.
Nach dem Ausführen des Skripts sollten Sie Folgendes vergleichen können:
ls -la /media/disk/git_svn/subdir
ls -la /media/diskC/tmp/subdirB # DEST
... und sehen hoffentlich die gleichen Zeitstempel (für diejenigen Dateien, die unter Versionskontrolle standen).
Hoffe das hilft jemandem,
Prost!
Mit Abstand der einfachste Weg, den ich je gesehen habe (und der 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 über das USB-Laufwerk von meinem Windows-Computer auf einen Linux-Computer kopieren?
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. Verschieben Sie in diesem Fall 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 /var/www/
auschecken möchten. In diesem Fall fügen Sie diesen Befehl in einem .git/hooks/post-receive
-Skript hinzu (hooks/post-receive
in einem leeren Repository, das in dieser Situation besser geeignet ist).
ein Git-Export in ein Zip-Archiv, während ein Präfix (z. B. ein Verzeichnisname) hinzugefügt wird:
git archive master --prefix=directoryWithinZip/ --format=Zip -o out.Zip
Wenn Sie auch Submodule benötigen, sollte dies der Trick sein: https://github.com/meitar/git-archive-all.sh/wiki
ich habe die folgende Utility-Funktion 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
}
Die Option 1 klingt nicht zu effizient. Was ist, wenn auf dem Client kein Platz zum Klonen vorhanden ist und dann den Ordner .git
entfernt?
Heute habe ich versucht, dies zu tun, wobei der Client ein Raspberry Pi ist, der fast keinen Platz mehr hat. Darüber hinaus möchte ich auch einige schwere Ordner aus dem Repository ausschließen.
Option 2 und andere Antworten hier helfen in diesem Szenario nicht. Weder git archive
(da eine .gitattributes
-Datei festgeschrieben werden muss und ich diesen Ausschluss nicht im Repository speichern möchte).
Hier teile ich meine Lösung, ähnlich wie Option 3, aber ohne die Notwendigkeit von git clone
:
tmp=`mktemp`
git ls-tree --name-only -r HEAD > $tmp
rsync -avz --files-from=$tmp --exclude='fonts/*' . raspberry:
Das Ändern der rsync
-Zeile durch eine entsprechende Zeile für die Komprimierung funktioniert auch als git archive
, jedoch mit einer Art Ausschlussoption (wie angefordert hier ).