Wie kopiere ich eine Version einer einzelnen Datei von einem Git-Zweig in einen anderen?

944

Ich habe zwei Zweige, die vollständig zusammengeführt sind.

Nachdem die Zusammenführung abgeschlossen ist, stelle ich jedoch fest, dass eine Datei durch die Zusammenführung durcheinander gebracht wurde (jemand anderes hat ein automatisches Format durchgeführt, gah), und es wäre einfach einfacher, auf die neue Version im anderen Zweig zu wechseln, und Fügen Sie dann meinen einzeiligen Wechsel erneut ein, nachdem Sie ihn in meinen Zweig übernommen haben.

Also, was ist der einfachste Weg in Git, dies zu tun?

Madlep
quelle
3
Bitte beachten Sie, dass in der akzeptierten Antwort die Änderungen durch die erste Lösung gestuft werden und durch die zweite Lösung nicht. stackoverflow.com/a/56045704/151841
user151841

Antworten:

1674

Führen Sie dies in dem Zweig aus, in dem die Datei enden soll:

git checkout otherbranch myfile.txt

Allgemeine Formeln:

git checkout <commit_hash> <relative_path_to_file_or_dir>
git checkout <remote_name>/<branch_name> <file_or_dir>

Einige Anmerkungen (aus Kommentaren):

  • Mit dem Commit-Hash können Sie Dateien aus jedem Commit ziehen
  • Dies funktioniert für Dateien und Verzeichnisse
  • überschreibt die Datei myfile.txtundmydir
  • Platzhalter funktionieren nicht, relative Pfade jedoch
  • Es können mehrere Pfade angegeben werden

eine Alternative:

git show commit_id:path/to/file > path/to/file
Madlep
quelle
13
Ja es würde. Aber das war die Absicht der Frage.
Ikke
37
Wahrscheinlich offensichtlich, aber Sie müssen den vollständigen Dateinamen verwenden ... Platzhalter funktionieren nicht!
Chris Hart
6
obwohl .. es ist auch schön so: git show commit_id: pfad / zu / datei> pfad / zu / datei
milushov
14
remote: git checkout origin / otherbranch myfile.txt
Roman Rhrn Nesterov
6
Die Verwendung von Platzhaltern funktioniert, Sie müssen sie nur umschließen, ''damit sie nicht von der Shell interpretiert werden.
Wiktor Czajkowski
82

Bei dieser Frage bin ich auf eine ähnliche Suche gestoßen. In meinem Fall wollte ich eine Datei aus einem anderen Zweig in das aktuelle Arbeitsverzeichnis extrahieren, das sich vom ursprünglichen Speicherort der Datei unterscheidet. Antwort :

git show TREEISH:path/to/file >path/to/local/file
lkraav
quelle
18
Die Absicht von 'git show' ist es, Daten in lesbarem Format an das Terminal auszugeben, was nicht garantiert ist, dass es genau mit dem Inhalt der Datei übereinstimmt. Genauso wie es besser ist, ein Word-Dokument als Ganzes zu kopieren und nicht zu versuchen, seinen Inhalt zu kopieren und in ein anderes Dokument einzufügen.
Gonen
Ich wollte es nur anzeigen, um den Inhalt mit dem aktuellen Zweig zu vergleichen (überprüfen Sie einen Code). Ich möchte vim damit verwenden ... für Syntax-Hervorhebungen usw.
isaaclw
3
Das Vergleichen von Inhalten vor dem Auschecken git diff <other branch> <path to file>funktioniert gut.
Randall
2
@Gonen: Ab Git-Version 2.21.0 wird auf der Handbuchseite "git show" "Für einfache Blobs wird der einfache Inhalt angezeigt" angezeigt. Ich bin mir nicht sicher, ob das bedeutet, dass wir immer gut sind. Ich bin ein bisschen vorsichtig, ein Bild auf diese Weise zu holen ...
Hibbelig
52

Was ist mit dem Checkout-Befehl:

  git diff --stat "$branch"
  git checkout --merge "$branch" "$file"
  git diff --stat "$branch"
RzR
quelle
8
note merge (2. Befehl) kann nicht funktionieren, wenn die Datei nicht in beiden Zweigen vorhanden ist
simpleuser
Hm. Ich habe kein Diffstat. Ist das eine bestimmte Version eines Diff-Tools, weil ich noch nie davon gehört habe (und sollte ich darauf
umsteigen
git diffunterstützt ein --statArgument, das im Grunde dasselbe tut wie diffstat.
Hlovdal
Ich musste beide Filialen vor Ort auschecken lassen, damit dies funktioniert.
UnitasBrooks
18

1) Stellen Sie sicher, dass Sie sich in einem Zweig befinden, in dem Sie eine Kopie der Datei benötigen. Zum Beispiel: Ich möchte eine Unterverzweigungsdatei im Master, also müssen Sie auschecken oder sollten im Master seingit checkout master

2) Jetzt checken Sie nur eine bestimmte Datei aus, die Sie vom Unterzweig in den Master haben möchten.

git checkout sub_branch file_path/my_file.ext

Hier sub_branchbedeutet, wo Sie diese Datei haben, gefolgt von dem Dateinamen, den Sie kopieren müssen.

Mohideen bin Mohammed
quelle
Sehr praktisch und gut erklärt.
Abk
15

Nach der Antwort von madlep können Sie mit dem Verzeichnis-Blob auch einfach ein Verzeichnis aus einem anderen Zweig kopieren.

git checkout other-branch app/**

Was die Frage der Operation betrifft, wenn Sie dort nur eine Datei geändert haben, funktioniert dies einwandfrei ^ _ ^

6ft Dan
quelle
1
Beachten Sie, dass beide Zweige zuerst richtig gezogen werden müssen oder origin/other-branchfür den Verweis auf den Repo-Zweig verwendet werden müssen. Grundlagen, aber mich gebissen. (Die Antwort ist großartig - keine Bearbeitung erforderlich)
Akauppi
8

Ich würde verwenden git restore(verfügbar seit Git 2.23)

git restore --source otherbranch path/to/myfile.txt


Warum ist es besser als andere Optionen?

git checkout otherbranch -- path/to/myfile.txt- Es kopiert die Datei in das Arbeitsverzeichnis, aber auch in den Staging-Bereich (ähnlicher Effekt, als würden Sie diese Datei manuell kopieren und darauf ausführen git add). git restoreBerührt den Staging-Bereich nicht (es sei denn, Sie werden dazu aufgefordert --staged).

git show otherbranch:path/to/myfile.txt > path/to/myfile.txtVerwendet die Standard-Shell-Umleitung. Wenn Sie Powershell verwenden, liegt möglicherweise ein Problem mit der Textbindung vor, oder Sie können eine fehlerhafte Datei erhalten, wenn diese binär ist . Beim git restoreÄndern von Dateien erfolgt alles per gitausführbarer Datei.

Ein weiterer Vorteil ist, dass Sie den gesamten Ordner wiederherstellen können mit:

git restore --source otherbranch path/to

oder mit, git restore --overlay --source otherbranch path/towenn Sie das Löschen von Dateien vermeiden möchten. Wenn beispielsweise weniger Dateien otherbranchals im aktuellen Arbeitsverzeichnis vorhanden sind (und diese Dateien nachverfolgt werden ), werden diese ohne --overlayOption git restoregelöscht. Aber dies ist ein gutes Standardverhalten. Sie möchten höchstwahrscheinlich, dass der Status des Verzeichnisses der gleiche ist wie in otherbranch, nicht "der gleiche, aber mit zusätzlichen Dateien in meinem aktuellen Zweig".

Mariusz Pawelski
quelle
Gute Antwort. Gibt es eine git restoreMöglichkeit, eine Datei aus dem Quellzweig in eine neue Datei im Zielzweig zu kopieren ? Mit git show kann ich dies mit der Shell-Umleitung ( git show otherbranch:path/to/file1.txt > path/to/file2.txt) tun , aber ich möchte die Shell-Umleitung aus den von Ihnen genannten Gründen vermeiden.
AdmiralAdama
1
@AdmiralAdama nicht wirklich. Und ich denke, es gibt keine große Chance, es zu bekommen git restore(aber wer weiß;)). Diese Umleitungsprobleme sind im Grunde genommen ein Powershell-Problem, nicht sicher, ob es eine andere Shell gibt, die ein Problem damit hat. Normalerweise gehe ich zurück zu "git bash" oder sogar "cmd", wo ich " git showwith redirection" -Befehle verwenden muss. Oder verwenden Sie eine grafische Benutzeroberfläche wie GitExtensions, in der Sie den Dateibaum des Commits durchsuchen und in einer beliebigen Datei auf "Speichern unter" klicken können.
Mariusz Pawelski
Ah ich sehe. Ich benutze Powershell nicht, daher ist die Shell-Umleitung für mich vielleicht np. Danke für die Information.
AdmiralAdama
3

Bitte beachten Sie, dass in der akzeptierten Antwort die erste Option die gesamte Datei aus dem anderen Zweig (wie ausgeführt) inszeniertgit add ... und dass die zweite Option nur zum Kopieren der Datei führt, die Änderungen jedoch nicht inszeniert (als ob Sie dies getan hätten) habe die Datei einfach manuell bearbeitet und hatte herausragende Unterschiede).

Git-Kopierdatei aus einem anderen Zweig, ohne sie zu inszenieren

Änderungen inszeniert (zB git add filename):

$ git checkout directory/somefile.php feature-B

$ git status
On branch feature-A
Your branch is up-to-date with 'origin/feature-A'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   directory/somefile.php

Ausstehende Änderungen (nicht inszeniert oder festgeschrieben):

$ git show feature-B:directory/somefile.php > directory/somefile.php

$ git status
On branch feature-A
Your branch is up-to-date with 'origin/feature-A'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   directory/somefile.php

no changes added to commit (use "git add" and/or "git commit -a")
user151841
quelle
Ich bekomme "Feature-B ist keine Datei", der Filialname steht an erster Stelle, über dieses -> "> Verzeichnis / somefile.php" Kann dies die Codierung der Datei ändern?
Tiago Oliveira de Freitas