GIT: Zur Kasse in einen bestimmten Ordner

128

Ich möchte etwas Ähnliches verwenden wie:

git checkout -- <path>/<file>

Ich möchte die Datei jedoch in einen von mir ausgewählten Ordner auschecken, anstatt den lokalen Ordner zu überschreiben <path>/<file>.

Irgendeine Idee?

Rafid
quelle
2
Siehe: stackoverflow.com/questions/160608/…
Adam Vandenberg

Antworten:

57

Laut Do ein "Git Export" (wie "SVN Export")?

Sie können dafür verwenden git checkout-index, dies ist ein Befehl auf niedriger Ebene. Wenn Sie alles exportieren möchten, können Sie Folgendes verwenden -a:

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

So zitieren Sie die Manpages:

Das letzte "/" [auf dem Präfix] ist wichtig. Dem exportierten Namen wird buchstäblich nur die angegebene Zeichenfolge vorangestellt.

Wenn Sie ein bestimmtes Verzeichnis exportieren möchten, sind einige Tricks erforderlich. Der Befehl akzeptiert nur Dateien, keine Verzeichnisse. Um es auf Verzeichnisse anzuwenden, verwenden Sie den Befehl 'find' und leiten Sie die Ausgabe an git weiter.

find dirname -print0 | git checkout-index --prefix=/path-to/dest/ -f -z --stdin

Auch von den Manpages:

Intuitivität ist hier nicht das Ziel. Wiederholbarkeit ist.

hasen
quelle
Leider funktioniert dies nicht aus einem Bare-Git-Repository, selbst mit dem --prefix-Set :-( (getestet mit Git 1.9.1)
Apeiros
1
Wenn Sie einen Zweig / ein Commit eines Bare-Git-Repositorys GIT_WORK_TREE=../path/to/place git checkout
auschecken möchten
4
git worktree(siehe unten) imho ist heute die kanonische Antwort und könnte hier hinzugefügt werden.
Geek-Merlin
212

Eine andere Lösung, die etwas sauberer ist - geben Sie einfach einen anderen Arbeitsbaum an.

So checken Sie alles von Ihrem HEAD (nicht Index) in ein bestimmtes Out-Verzeichnis aus:

git --work-tree=/path/to/outputdir checkout HEAD -- .

So checken Sie ein Unterverzeichnis oder eine Datei von Ihrem HEAD in ein bestimmtes Verzeichnis aus:

git --work-tree=/path/to/outputdir checkout HEAD -- subdirname
Adrian Macneil
quelle
4
Kleinere Anmerkung - Sie benötigen einen absoluten Pfad, da keine Shell-Tilde-Erweiterung auftritt, dh --work-tree=/home/thomasg/okcopynicht --work-tree=~/okcopy(möglicherweise funktioniert auch die Verwendung eines relativen Pfads, während Sie im selben Git-Baum sitzen, aber auf diese Weise liegen Wahnsinn und git statusErgebnisse in R'lyehian)
Tom Goodfellow
10
Es funktioniert wie erwartet auch mit alten Commits (z. B. geben Sie einen SHA anstelle von HEAD an), git statuszeigt dann jedoch viele Mods an (vermutlich, weil der Index jetzt mit dem anderen Verzeichnis und nicht mit dem unberührten normalen Arbeitsbaum übereinstimmt). git resetbrachte es wieder in einen guten Zustand.
Tom Goodfellow
2
Das gleiche hier git statuszeigt viele Mods und git resethilft nicht. Ich musste git checkout -f HEADden Zustand meines Repos wiederherstellen.
DUzun
11
Zu Ihrer Information: Sie müssen das Verzeichnis selbst erstellen, sonst erhalten Sie folgende Fehlermeldung:fatal: This operation must be run in a work tree
Timaschew
13
Dies ändert den Index des Hauptarbeitsbaums katastrophal, was normalerweise schlecht ist. Wie @TomGoodfellow vorschlägt, git resetreicht es aus, den Hauptarbeitsbaum wieder in Ordnung zu bringen. Informationen zum sicheren Exportieren von Repository-Unterverzeichnissen in SHA1, Zweigen oder Tags, ohne den Hauptarbeitsbaum zu ändern, finden Sie in der berüchtigten git archiveLösung von Charles Bailey . Um mehrere Zweige gleichzeitig sicher auszuchecken, ist der neue git worktree addUnterbefehl Ihr Freund.
Cecil Curry
25

Für eine einzelne Datei:

git show HEAD:abspath/to/file > file.copy
Tobu
quelle
2
+1 und um das "bestimmte vorherige Commit" (anstelle von HEAD) zu verdeutlichen: Es bezieht sich auf das SHA1 ID, das leicht über gefunden werden kann gitk. Wenn ich diese Datei nur an einen temporären Speicherort "auschecken" muss (dh nicht zurücksetzen muss), würde ich den showUnterbefehl verwenden:git show 82e54378856215ef96c5db1ff1160a741b5dcd70:MyProj/proguard/mapping.txt > myproj_mapping.txt
ef2011
19

Die oben genannten Lösungen haben bei mir nicht funktioniert, da ich eine bestimmte getaggte Version des Baums auschecken musste. So cvs exportsoll es übrigens verwendet werden. git checkout-indexnimmt das Tag-Argument nicht an, da es Dateien aus dem Index auscheckt. git checkout <tag>würde den Index unabhängig vom Arbeitsbaum ändern, so dass ich den ursprünglichen Baum zurücksetzen müsste. Die Lösung, die für mich funktioniert hat, war das Klonen des Repositorys. Der gemeinsam genutzte Klon ist recht schnell und benötigt nicht viel zusätzlichen Platz. Das .gitVerzeichnis kann bei Bedarf entfernt werden.

git clone --shared --no-checkout <repository> <destination>
cd <destination>
git checkout <tag>
rm -rf .git

Neuere Versionen von git sollten git clone --branch <tag>das automatische Auschecken des angegebenen Tags unterstützen:

git clone --shared --branch <tag> <repository> <destination>
rm -rf <destination>/.git
Proski
quelle
3
git --work-tree=/path/to/outputdir checkout <tag> -- .hat bei dir nicht funktioniert?
Warvariuc
1
Nein, das tut es nicht. Die tatsächliche Datei im ursprünglichen Arbeitsverzeichnis bleibt unverändert, aber die bereitgestellte Version geht verloren und wird durch die Version aus dem Tag ersetzt. Es ist besonders schlimm, wenn die bereitgestellte Version eine sorgfältig ausgewählte Reihe von Änderungen enthält, die festgeschrieben werden sollen. Ich möchte nicht, dass der Exportbefehl meinen Index, Punkt, berührt.
Proski
19

Wenn Sie unter Ihrer Funktion arbeiten und nicht zum Master zurückkehren möchten, können Sie Folgendes ausführen:

cd ./myrepo

git worktree add ../myrepo_master master

git worktree remove ../myrepo_master

Es wird ein ../myrepo_masterVerzeichnis mit masterVerzweigungs-Commits erstellt, in dem Sie die Arbeit fortsetzen können

itsnikolay
quelle
1
Beste Antwort - einfach und im Gegensatz zu git --work-tree=/path/to/outputdir checkout HEAD -- .nichts, was nichts mit dem Index zu tun hat, kopiert er einfach den ausgewählten Zweig an den angegebenen Speicherort (mit dem Zusatz einer .git-Datei).
Roger Dueck
Und wie würde ich diese Änderung rückgängig machen?
Scott P.
@ ScottP.just myrepo_masterVerzeichnis entfernen
itsnikolay
1
Dies rückgängig zu machen ist ein Unterbefehl aus dem Arbeitsbaum:git worktree remove ../myrepo_master
Martijn Dashorst
8

Adrians Antwort warf "fatal: Diese Operation muss in einem Arbeitsbaum ausgeführt werden." Folgendes hat bei uns funktioniert.

git worktree add <new-dir> --no-checkout --detach
cd <new-dir>
git checkout <some-ref> -- <existing-dir>

Anmerkungen:

  • --no-checkout Checken Sie nichts in den neuen Arbeitsbaum ein.
  • --detach Erstellen Sie keinen neuen Zweig für den neuen Arbeitsbaum.
  • <some-ref>funktioniert mit jedem ref, zum Beispiel mit HEAD~1.
  • Aufräumen mit git worktree prune.
Shaun Luttin
quelle
+1 für Kommentare zum Aufräumen - alle anderen sind froh, das aktuelle Repo durcheinander zu bringen. Nur dieser hat keine Nebenwirkungen.
Andrew Hill
1

Ergänzung zu @ hasens Antwort . Um die Liste Dateien Kasse , können Sie verwenden , git ls-filesanstatt findwie:

git ls-files -z *.txt | git checkout-index --prefix=/path-to/dest/ -f -z --stdin
snipsnipsnip
quelle
Vielen Dank für die richtige Verwendung -z! Schön, dass Sie ein Skript bereitstellen, das für bestimmte Arten von Injektionsangriffen nicht anfällig ist.
ErikE
0

Ich habe einen Git-Alias ​​definiert, um genau dies zu erreichen (bevor ich diese Frage gefunden habe).

Es ist eine kurze Bash-Funktion, die den aktuellen Pfad speichert, zum Git-Repo wechselt, eine Kasse durchführt und dorthin zurückkehrt, wo es begonnen hat.

git checkto ~ / my_project_git entwickeln

Dies würde beispielsweise den Entwicklungszweig in das Verzeichnis "~ / my_project_git" auschecken.

Dies ist der Alias-Code im Inneren ~/.gitconfig:

[alias]
    checkTo = "!f(){ [ -z \"$1\" ] && echo \"Need to specify branch.\" && \
               exit 1; [ -z \"$2\" ] && echo \"Need to specify target\
               dir\" && exit 2; cDir=\"$(pwd)\"; cd \"$2\"; \
               git checkout \"$1\"; cd \"$cDir\"; };f"
cb0
quelle
0

Ich verwende diesen Alias ​​zum Auschecken eines Zweigs in einem temporären Verzeichnis:

[alias]
    cot = "!TEMP=$(mktemp -d); f() { git worktree prune && git worktree add $TEMP $1 && zsh -c \"cd $TEMP; zsh\";}; f" # checkout branch in temporary directory

Verwendung:

git cot mybranch

Sie werden dann in einer neuen Shell im temporären Verzeichnis abgelegt, in der Sie an der Verzweigung arbeiten können. Sie können sogar Git-Befehle in diesem Verzeichnis verwenden.

Wenn Sie fertig sind, löschen Sie das Verzeichnis und führen Sie Folgendes aus:

git worktree prune

Dies erfolgt auch automatisch im Alias, bevor ein neuer Arbeitsbaum hinzugefügt wird.

fdietze
quelle
0

Verwenden Sie git archive branch-index | tar -x -C your-folder-on-PCdiese Option, um einen Zweig in einen anderen Ordner zu klonen. Ich denke, dann können Sie jede Datei kopieren, die Sie benötigen

dqthe
quelle