So erhalten Sie nur eine Datei aus einem anderen Zweig

1265

Ich benutze Git und arbeite am Master-Zweig. Dieser Zweig hat eine Datei namens app.js.

Ich habe eine experimentNiederlassung, in der ich eine Reihe von Änderungen und Tonnen von Commits vorgenommen habe. Jetzt möchte ich alle Änderungen, die vorgenommen wurden, nur von app.jsvon experimentzu masterZweig bringen.

Wie mache ich das?

Ich möchte noch einmal keine Zusammenführung. Ich möchte nur alle Änderungen app.jsvon experimentZweig zu masterZweig einbringen .

Nick Vanderbilt
quelle
1
Ausgenommene Antworten und andere ab heute antworten, wie man den Inhalt einer Datei kopiert. Das wollte ich selbst, als ich diese fand. Wenn jedoch genau gelesen, wollte Nick Änderungen bringen, nicht Volltext, und die Datei masterkann abweichen experiment, z. B. kann Änderungen enthalten, die aus anderen Zweigen zusammengeführt wurden, die in der Datei verloren gehen würden, wird nur kopiert. PS hingegen will er nicht zusammenführen, aber soweit ich weiß, bezieht sich der git mergeBegriff nur auf die Verzweigung, nicht auf eine bestimmte Datei, also kein Widerspruch hier.
Alexei Martianov

Antworten:

1603
git checkout master               # first get back to master
git checkout experiment -- app.js # then copy the version of app.js 
                                  # from branch "experiment"

Siehe auch git, wie Sie Änderungen an einer Datei rückgängig machen können.


Update August 2019, Git 2.23

Mit den neuen git switchund git restoreBefehlen wäre das:

git switch master
git restore -s experiment -- app.js

Standardmäßig wird nur der Arbeitsbaum wiederhergestellt.
Wenn Sie den Index ebenfalls aktualisieren möchten (dh den Dateiinhalt wiederherstellen und mit einem Befehl zum Index hinzufügen möchten ):

git restore -s experiment --staged --worktree -- app.js
# shorter:
git restore -s experiment -WS -- app.js

Wie Jakub Narębski in den Kommentaren erwähnt:

git show experiment:path/to/app.js > path/to/app.js

funktioniert auch, außer dass, wie in der SO-Frage " Wie rufe ich eine einzelne Datei aus einer bestimmten Revision in Git ab?" ich " beschrieben, den vollständigen Pfad aus dem Stammverzeichnis des Repos verwenden müssen.
Daher der Pfad / zu / app.js, den Jakub in seinem Beispiel verwendet.

Wie Frosty im Kommentar erwähnt:

Sie erhalten nur den neuesten Status von app.js.

Aber für git checkoutoder git showkönnen Sie tatsächlich auf jede gewünschte Revision verweisen, wie in der SO-Frage " Git Checkout-Revision einer Datei in Git GUI " dargestellt:

$ git show $REVISION:$FILENAME
$ git checkout $REVISION -- $FILENAME

wäre das gleiche ist $ FILENAME ist ein vollständiger Pfad einer versionierten Datei.

$REVISIONkann wie folgt sein git rev-parse:

experiment@{yesterday}:app.js # app.js as it was yesterday 
experiment^:app.js            # app.js on the first commit parent
experiment@{2}:app.js         # app.js two commits ago

und so weiter.

schmijos fügt in den Kommentaren hinzu :

Sie können dies auch aus einem Vorrat heraus tun:

git checkout stash -- app.js

Dies ist sehr nützlich, wenn Sie an zwei Zweigen arbeiten und keine Festschreibung vornehmen möchten.

VonC
quelle
13
Ein Hinweis: Sie erhalten nur den neuesten Status von app.js. Sie erhalten keinen Verlauf, der vom Experimentzweig übertragen wurde.
Frosty
2
@ThomasReggi Sie sollten in der Lage sein, eine Datei von einem beliebigen Zweig in einen beliebigen aktuellen Zweig zu importieren (auschecken). Wenn Sie dies nicht können, kann dies eine gute Frage sein, die bestimmte Details wie die genaue Fehlermeldung und die verwendete Version von Git und OS enthält.
VonC
2
In einem Unterverzeichnis können Sie auch verwenden experiment:./app.js. (Sie müssen nicht den vollständigen Pfad angeben.) Ich habe dies dank der sehr hilfreichen Fehlermeldung gelernt, die git mir gegeben hat: "Meinten Sie 'mybranch: full / path / to / my / file.xsl' aka 'mybranch: ./file.xsl '? " Ja, habe ich! Ich glaube nicht, dass mich eine fatale Fehlermeldung jemals so begeistert hat.
Evan Lenz
1
@TomaszGandor Ja, ich erwähne das in stackoverflow.com/a/21066489/6309 , wo git show den Index nicht ändern würde, aber git checkout den Index ändert.
VonC
1
@FriedBrice Siehe meine Antwort: In diesen Tagen wäre esgit restore -s new-feature path/to/app.js
VonC
360

Alles ist viel einfacher, verwenden Sie dafür die Git-Kaufabwicklung.

Angenommen, you're on masterVerzweigung, um app.js from new-featureVerzweigung zu erhalten, tun Sie:

git checkout new-feature path/to/app.js

// note that there is no leading slash in the path!

Dadurch erhalten Sie den Inhalt der gewünschten Datei. Sie können wie immer einen Teil von sha1 anstelle des Zweignamens für neue Funktionen verwenden , um die Datei so wie sie in diesem bestimmten Commit war.

Hinweis : new-featureMuss ein lokaler Zweig sein, kein entfernter.

Dmitry Avtonomov
quelle
77
Ich finde es hilfreich, immer den Ursprung anzugeben, git checkout origin/source_branch path/to/filedenn wenn Sie es versäumt haben, den Quellzweig Ihres lokalen Repos zu aktualisieren, erhalten Sie möglicherweise eine alte Version der Datei ... Fragen Sie mich, woher ich das weiß. ;)
talyric
3
@Mymozaaa die Frage erwähnte keine Fernbedienungen, daher die Annahme, dass es sich um ein rein lokales Repo handelt
Dmitry Avtonomov
1
Bringt dieser Befehl den Verlauf der Datei oder nur die letzte Version der Datei?
user1366265
1
@ user1366265 Mit diesem Befehl wird die Datei so platziert, wie sie in dem von Ihnen angegebenen Commit oder dem Kopf des von Ihnen angegebenen Zweigs war. Es gibt keinen "Verlauf einer Datei", alle Verlaufsinformationen werden nur in Zweigen gespeichert.
Dmitry Avtonomov
3
Dies scheint die ausgecheckte Datei automatisch zu inszenieren. Ist es möglich, dasselbe ohne Inszenierung zu tun?
bluenote10
44
git checkout branch_name file_name

Beispiel:

git checkout master App.java

Dies funktioniert nicht, wenn Ihr Filialname einen Punkt enthält.

git checkout "fix.june" alive.html
error: pathspec 'fix.june' did not match any file(s) known to git.
Sarath
quelle
@PhilipRego Diese Antwort ist richtig. Ich vermute, dass es in Ihrer Filiale eine andere Groß- oder Kleinschreibung oder Zeichensetzung gibt, oder Sie haben nur eine entfernte Filiale und keine lokale. Siehe das Git Checkout-Dokument: git-scm.com/docs/git-checkout#Documentation/…
Bret
@Bret Ich habe festgestellt, dass es nicht funktioniert, wenn der Filialname einen Punkt hat. Ich schlug eine
Philip Rego
Dies ist die beste Antwort. Ich wünschte, diese Antwort wäre am höchsten bewertet. Der derzeit höchste ist sehr verwirrend und nicht einfach
Russell Lego
41

Ergänzend zu den Antworten von VonC und chhh.

git show experiment:path/to/relative/app.js > app.js
# If your current working directory is relative than just use
git show experiment:app.js > app.js

oder

git checkout experiment -- app.js
AlexLordThorsen
quelle
2
Cool! Ich hasse es, lange Wege anzugeben. Ist der doppelte Bindestrich ( --) zwischen dem Filialnamen und den Pfaden optional? Ist es nur zu verhindern, dass Pfade, die mit einem Bindestrich beginnen würden, als Optionen / Schalter behandelt werden?
Tomasz Gandor
Ehrlich gesagt weiß ich es nicht. Ich habe nicht einmal bemerkt, dass ich den Doppelstrich vergessen hatte, bis Sie darauf hingewiesen haben.
AlexLordThorsen
6
@TomaszGandor Das --ist optional, aber es ist nützlicher, Konflikte mit Zweigstellennamen zu vermeiden. Bedeutet zum Beispiel git checkout -- foo"Datei foo von HEAD auschecken" (dh lokale Änderungen in foo überschreiben , dh eine Teilmenge von git reset --hard), git checkout fookönnte aber dies bedeuten oder "gehen wir zum Zweig foo ".
Alois Mahdal
8

Oder wenn Sie alle Dateien aus einem anderen Zweig möchten:

git checkout <branch name> -- .
Narr
quelle
24
Die erste Quest enthält "nur eine Datei".
Greatvovan
1
Dies ersetzt vorhandene Dateien, anstatt sie zusammenzuführen
Amare
3
Dies .macht einen großen Unterschied: Anstatt in einen anderen Zweig zu wechseln, werden alle Dateien von dort kopiert, während Sie weiterhin auf dem aktuellen Zweig bleiben. Sie erhalten Inhalte aus anderen Branchen, ohne darauf einzugehen.
Xeverous
4

Überprüfen Sie die Datei auf Github und ziehen Sie sie von dort

Dies ist ein pragmatischer Ansatz, der das OP nicht direkt beantwortet, aber einige haben sich als nützlich erwiesen:

Wenn sich der betreffende Zweig auf GitHub befindet, können Sie mit einem der vielen von GitHub angebotenen Tools zum gewünschten Zweig und zur gewünschten Datei navigieren, dann auf "Raw" klicken, um den Nur-Text anzuzeigen, und den Text (optional) kopieren und einfügen als erwünscht.

Ich mag diesen Ansatz, weil Sie damit die Remote-Datei in ihrer Gesamtheit betrachten können, bevor Sie sie auf Ihren lokalen Computer ziehen.

furchtloser Dummkopf
quelle
2
Das Kopieren und Einfügen der Rohdatei kann jedoch zu unerwünschten Zeichenänderungen in Ihrem Git-Diff führen. Es ist sicherer, die Datei direkt in Ihrem Projekt zu speichern, um sicherzustellen, dass keine Änderungen vorgenommen werden.
Philip Rego
0

Wenn Sie die Datei von einem bestimmten Commit (einem beliebigen Zweig) erhalten möchten, sagen Sie 06f8251f

git checkout 06f8251f path_to_file

Zum Beispiel in Windows:

git checkout 06f8251f C: \ A \ B \ C \ D \ file.h.

arupjbasu
quelle
1
Vielen Dank, dass Sie sich die Zeit genommen haben, um zu antworten! Dies beantwortet jedoch nicht die Frage, und eine gute Antwort, die sehr detailliert ist, wurde bereits vor 9 Jahren veröffentlicht. Es besteht keine Notwendigkeit, die Frage zu beantworten.
Nathan
Dies ist ein gültiges praktisches Szenario. Die Antwort bezieht sich korrekt auf den Zweig, aber wie sieht es mit einem bestimmten Commit des Zweigs aus?
Arupjbasu
0

Eine andere Möglichkeit besteht darin, einen Patch mit den Unterschieden zu erstellen und ihn beispielsweise im Hauptzweig anzuwenden. Angenommen, das letzte Commit, bevor Sie mit der Arbeit an app.js begonnen haben, ist 00000aaaaa, und das Commit mit der gewünschten Version ist 00000bbbbb

Das führen Sie im Experimentzweig aus:

git diff 00000aaaaa 00000bbbbb app.js > ~/app_changes.git

Dadurch wird eine Datei mit allen Unterschieden zwischen diesen beiden Commits für app.js erstellt, die Sie anwenden können, wo immer Sie möchten. Sie können diese Datei überall außerhalb des Projekts aufbewahren

Dann rennst du im Master einfach:

git apply ~/app_changes.git

Jetzt sehen Sie die Änderungen in den Projekten so, als hätten Sie sie manuell vorgenommen.

Santi
quelle
-3
git checkout master               -go to the master branch first
git checkout <your-branch> -- <your-file> --copy your file data from your branch.

git show <your-branch>:path/to/<your-file> 

Hoffe das wird dir helfen. Bitte lassen Sie es mich wissen, wenn Sie Fragen haben.

Rohit Saini
quelle