Come copio una versione di un singolo file da un ramo git a un altro?


944

Ho due rami che sono completamente uniti.

Tuttavia, dopo aver completato l'unione, mi rendo conto che un file è stato incasinato dall'unione (qualcun altro ha fatto un formattazione automatica, gah), e sarebbe solo più semplice passare alla nuova versione nell'altro ramo e quindi reinserire il mio cambio di una riga dopo averlo inserito nel mio ramo.

Quindi qual è il modo più semplice per farlo?


3
Si noti che nella risposta accettata, la prima soluzione mette in scena le modifiche e la seconda soluzione no. stackoverflow.com/a/56045704/151841
user151841

Risposte:


1675

Esegui questo dal ramo in cui vuoi che finisca il file:

git checkout otherbranch myfile.txt

Formule generali:

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

Alcune note (dai commenti):

  • Usando l'hash di commit puoi estrarre i file da qualsiasi commit
  • Funziona con file e directory
  • sovrascrive il file myfile.txtemydir
  • I caratteri jolly non funzionano, ma i percorsi relativi lo fanno
  • È possibile specificare più percorsi

un'alternativa:

git show commit_id:path/to/file > path/to/file

13
Sì, lo sarebbe. Ma questa era l'intenzione della domanda.
Ikke,

37
Probabilmente ovvio, ma è necessario utilizzare il nome file completo ... I caratteri jolly non funzionano!
Chris Hart,

6
anche se .. è anche un bel modo: git show commit_id: percorso / to / file> percorso / to / file
milushov

14
remoto: git checkout origin / otherbranch myfile.txt
Roman Rhrn Nesterov

6
L'uso dei caratteri jolly funziona, è sufficiente avvolgerli in ''modo che non vengano interpretati dalla shell.
Wiktor Czajkowski

82

Ho finito con questa domanda con una ricerca simile. Nel mio caso stavo cercando di estrarre un file da un altro ramo nella directory di lavoro corrente che era diversa dalla posizione originale del file. Risposta :

git show TREEISH:path/to/file >path/to/local/file

18
L'intenzione di "git show" è di inviare i dati al terminale in un formato leggibile, che non è garantito per corrispondere esattamente al contenuto del file. Lo stesso è meglio copiare un documento di Word nel suo insieme e non provare a copiare e incollare il suo contenuto in un altro documento.
Gonen,

Volevo solo vederlo in modo da poter confrontare i contenuti con il ramo corrente (controlla un pezzo di codice). Vorrei usare Vim con questo però ... per l'evidenziazione della sintassi, ecc.
Isaaclw,

3
Per confrontare i contenuti prima di fare il checkout, git diff <other branch> <path to file>funziona bene.
Randall,

2
@Gonen: A partire dalla versione 2.21.0 di git, la pagina di manuale "git show" dice "Per le chiazze semplici, mostra i contenuti semplici". Non sono sicuro che ciò significhi che siamo sempre bravi. Sono un po 'diffidente nel cercare un'immagine in quel modo ...
Hibbelig,

52

Che dire dell'utilizzo del comando checkout:

  git diff --stat "$branch"
  git checkout --merge "$branch" "$file"
  git diff --stat "$branch"

8
note merge (2 ° comando) non può funzionare se il file non esiste su entrambi i rami
simpleuser

Hm. Non ho diffstat. È una versione specifica di uno strumento diff, perché non ne ho mai sentito parlare (e dovrei passare ad esso?): D
dudewad,

git diffsupporta un --statargomento che sostanzialmente fa la stessa cosa di diffstat.
hlovdal

Ho dovuto controllare entrambi i rami localmente per farlo funzionare.
UnitasBrooks

18

1) Assicurati di essere nel ramo in cui hai bisogno di una copia del file. ad esempio: voglio un file di succursale secondario nel master, quindi è necessario effettuare il checkout o dovrebbe essere nel mastergit checkout master

2) Ora controlla solo il file specifico che desideri dal ramo secondario al master,

git checkout sub_branch file_path/my_file.ext

qui sub_branchsignifica dove hai quel file seguito dal nome file che devi copiare.


Molto utile e ben spiegato.
Abk,

15

Seguendo la risposta di madlep puoi anche semplicemente copiare una directory da un altro ramo con il BLOB di directory.

git checkout other-branch app/**

Per quanto riguarda la domanda dell'op se hai cambiato solo un file lì dentro funzionerà bene ^ _ ^


1
Si noti che entrambi i rami devono essere correttamente estratti, prima o utilizzati origin/other-branchper fare riferimento al ramo repo. Nozioni di base, ma mi ha morso. (la risposta è ottima - nessuna modifica richiesta)
akauppi

8

Vorrei usare git restore(disponibile da Git 2.23)

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


Perché è meglio di altre opzioni?

git checkout otherbranch -- path/to/myfile.txt- Copia il file nella directory di lavoro ma anche nell'area di gestione temporanea (effetto simile come se si copiasse questo file manualmente ed eseguisse git addsu di esso). git restorenon tocca l'area di stadiazione (a meno che non sia stato indicato --stageddall'opzione).

git show otherbranch:path/to/myfile.txt > path/to/myfile.txtutilizza il reindirizzamento della shell standard. Se usi Powershell, potrebbe esserci un problema con la codifica del testo o potresti ottenere un file rotto se è binario . Con la git restoremodifica dei file è fatto tutto da giteseguibile.

Un altro vantaggio è che puoi ripristinare l'intera cartella con:

git restore --source otherbranch path/to

o con git restore --overlay --source otherbranch path/tose si desidera evitare di eliminare i file. Ad esempio, se sono presenti meno file otherbranchrispetto alla directory di lavoro corrente (e questi file sono tracciati ) senza --overlayopzione git restoreli elimineranno. Ma questo è un buon comportamento predefinito, molto probabilmente vuoi che lo stato della directory sia lo stesso di in otherbranch, non "lo stesso ma con file aggiuntivi nel mio ramo attuale"


Bella risposta. Esiste un git restoremodo per copiare un file dal ramo di origine in un nuovo file sul ramo di destinazione? Con git show posso farlo con il reindirizzamento della shell ( git show otherbranch:path/to/file1.txt > path/to/file2.txt), ma voglio evitare il reindirizzamento della shell per i motivi menzionati.
AdmiralAdama,

1
@AdmiralAdama non proprio. E penso che non ci siano grandi possibilità di ottenerlo git restore(ma chi lo sa;)). Questi problemi di reindirizzamento sono fondamentalmente un problema di Powershell, non sono sicuro che ci siano altre shell che hanno problemi con esso. Di solito torno a "git bash" o anche a "cmd" dove devo usare i git showcomandi " con reindirizzamento". Oppure usa la GUI come GitExtensions dove puoi sfogliare l'albero dei file di commit e fare clic su "Salva con nome" su qualsiasi file.
Mariusz Pawelski

Ah capisco Non uso Powershell, quindi forse il reindirizzamento della shell è np per me. Grazie per le informazioni.
AdmiralAdama,

3

Si noti che nella risposta accettata, la prima opzione mette in scena l'intero file dall'altro ramo (come se git add ...fosse stato eseguito) e che la seconda opzione comporta solo la copia del file, ma non mette in scena le modifiche (come se si fosse appena modificato il file manualmente e presentava differenze eccezionali).

Esci copia il file da un altro ramo senza metterlo in scena

Modifiche messe in scena (ad esempio 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

Modifiche in sospeso (non messe in scena o impegnate):

$ 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")

Ottengo "feature-B non è un file", il nome del ramo viene prima, a proposito di questo -> "> directory / somefile.php" può cambiare la codifica del file?
Tiago Oliveira de Freitas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.