Come ottenere solo un file da un altro ramo


1267

Sto usando Git e sto lavorando su Master Branch. Questo ramo ha un file chiamato app.js.

Ho una experimentfiliale in cui ho apportato un sacco di cambiamenti e tonnellate di impegni. Ora voglio portare tutte le modifiche apportate solo a app.jsda experimenta masterbranch.

Come lo faccio?

Ancora una volta non voglio una fusione. Voglio solo portare tutte le modifiche app.jsda un experimentramo all'altro master.



1
Tranne la risposta e gli altri oggi rispondono come copiare il contenuto del file, è quello che volevo da solo quando l'ho trovato. Tuttavia, se letto esattamente, Nick voleva apportare modifiche, non il testo completo, e il file in masterpotrebbe divergere experiment, ad esempio può contenere modifiche unite da altri rami che andrebbero perse nel file e appena copiate. PS d'altra parte non vuole unire, ma per quanto ne so il git mergetermine è solo per ramo, non per file specifico, quindi nessuna contraddizione qui.
Alexei Martianov,

Risposte:


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

Vedi anche git come annullare le modifiche di un file?


Aggiornamento agosto 2019, Git 2.23

Con il nuovo git switche i git restorecomandi, sarebbe:

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

Per impostazione predefinita, viene ripristinato solo l'albero di lavoro.
Se si desidera aggiornare anche l'indice (che significa ripristinare il contenuto del file e aggiungerlo all'indice in un solo comando):

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

Come Jakub Narębski menziona nei commenti:

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

funziona anche, tranne che, come dettagliato nella domanda SO " Come recuperare un singolo file dalla revisione specifica in Git? ", è necessario utilizzare il percorso completo dalla directory principale del repository.
Da qui il percorso / to / app.js utilizzato da Jakub nel suo esempio.

Come menziona Frosty nel commento:

otterrai solo lo stato più recente di app.js

Ma, per git checkouto git show, puoi effettivamente fare riferimento a qualsiasi revisione tu voglia, come illustrato nella domanda SO " revisione di git checkout di un file in git gui ":

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

sarebbe lo stesso è $ FILENAME è un percorso completo di un file con versione.

$REVISIONpuò essere come mostrato in 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

e così via.

schmijos aggiunge nei commenti :

puoi anche farlo da una scorta:

git checkout stash -- app.js

Questo è molto utile se stai lavorando su due rami e non vuoi impegnarti.


13
Una nota: otterrai solo lo stato più recente di app.js, non otterrai alcuna cronologia riportata dal ramo dell'esperimento.
Frosty

2
@ThomasReggi dovresti essere in grado di importare (checkout) un file da qualsiasi ramo a qualsiasi ramo corrente. In caso contrario, può essere una buona domanda da porre qui, con dettagli specifici come il messaggio di errore esatto e la versione di Git e OS utilizzata.
VonC,

2
In una sottodirectory, puoi anche usare experiment:./app.js. (Non è necessario specificare il percorso completo.) L'ho imparato grazie al messaggio di errore molto utile che git mi ha dato: "Intendevi 'mybranch: full / path / to / my / file.xsl' aka 'mybranch: ./file.xsl '?" Si l'ho fatto! Non credo di essere mai stato così felice di un messaggio di errore fatale.
Evan Lenz,

1
@TomaszGandor Sì, lo menziono in stackoverflow.com/a/21066489/6309 , dove git show non modifica l'indice, ma git checkout modifica l'indice.
VonC,

1
@FriedBrice Vedi la mia risposta: in questi giorni, sarebbegit restore -s new-feature path/to/app.js
VonC

360

Tutto è molto più semplice, usa git checkout per questo.

Supponiamo che you're on masterbranch, per ottenere app.js from new-featurebranch, faccia:

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

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

Questo ti porterà il contenuto del file desiderato. Come sempre, puoi usare parte di sha1 anziché il nome del ramo di nuova funzionalità per ottenere il file com'era in quel particolare commit.

Nota : new-featuredeve essere una filiale locale , non remota.


77
Trovo utile specificare sempre l'origine git checkout origin/source_branch path/to/fileperché se hai trascurato di aggiornare il ramo di origine del tuo repository locale, potresti ottenere una vecchia versione del file ... Chiedimi come lo so. ;)
talirico

3
@Mymozaaa la domanda non ha menzionato i telecomandi, quindi l'ipotesi che si tratti di un repository puramente locale
Dmitry Avtonomov

1
Questo comando porterà la cronologia del file o solo l'ultima versione del file?
user1366265,

1
@utente1366265 questo comando inserirà il file com'era nel commit specifico specificato o nell'intestazione del ramo specificato. Non esiste una "cronologia di un file", tutte le informazioni sulla cronologia sono memorizzate solo in rami.
Dmitry Avtonomov

3
Questo sembra mettere in scena automaticamente il file estratto. È possibile fare lo stesso senza messa in scena?
bluenote10

44
git checkout branch_name file_name

Esempio:

git checkout master App.java

Questo non funzionerà se il nome della tua filiale contiene un punto.

git checkout "fix.june" alive.html
error: pathspec 'fix.june' did not match any file(s) known to git.

@PhilipRego Questa risposta è corretta. Immagino che ci siano diverse maiuscole o punteggiatura nel tuo ramo, oppure hai solo un ramo remoto e non uno locale. Vedi il documento di checkout git: git-scm.com/docs/git-checkout#Documentation/…
Bret

@Bret Ho scoperto che non funziona quando il nome del ramo ha un punto. Ho suggerito una modifica
Philip Rego,

Questa è la migliore risposta Vorrei che questa risposta fosse la più votata. L'attuale più alto è molto confuso e non semplice
Russell Lego,

41

Supplemento alle risposte di VonC e 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

o

git checkout experiment -- app.js

2
Freddo! Odio specificare percorsi lunghi. Il doppio trattino ( --) tra il nome del ramo e i percorsi è facoltativo? È solo per evitare che i percorsi, che inizierebbero con un trattino, vengano trattati come opzioni / opzioni?
Tomasz Gandor,

Onestamente non lo so. Non ho nemmeno notato che avevo dimenticato il doppio trattino fino a quando non lo hai sottolineato.
AlexLordThorsen,

6
@TomaszGandor --È facoltativo, ma è più utile per evitare conflitti con i nomi delle filiali. Ad esempio, git checkout -- foosignifica "estrarre il file foo da HEAD" (ovvero sovrascrivere le modifiche locali in foo , ovvero un sottoinsieme di git reset --hard), ma git checkout foopotrebbe significare che o "andiamo al ramo foo ".
Alois Mahdal,

8

O se vuoi tutti i file da un altro ramo:

git checkout <branch name> -- .

24
La queston iniziale contiene "solo un file".
greatvovan,

1
questo sostituisce i file esistenti anziché unirli
Amare,

3
Questo .fa una differenza enorme: invece di spostarsi su un altro ramo, copia tutti i file da lì, lasciandoti comunque su quello corrente. Ottieni contenuti da un altro ramo senza entrarci.
Xeverous,

4

Rivedi il file su github e estrailo da lì

Questo è un approccio pragmatico che non risponde direttamente al PO, ma alcuni hanno trovato utile:

Se il ramo in questione si trova su GitHub, puoi accedere al ramo e al file desiderati utilizzando uno dei numerosi strumenti offerti da GitHub, quindi fai clic su "Raw" per visualizzare il testo normale e (facoltativamente) copiare e incollare il testo come desiderato.

Mi piace questo approccio perché ti permette di guardare il file remoto nella sua interezza prima di inserirlo nel tuo computer locale.


2
Tuttavia, è probabile che copiare e incollare il file non elaborato causi modifiche indesiderate al carattere nel tuo git diff. È più sicuro salvare il file direttamente nel progetto per garantire che non vengano apportate modifiche.
Philip Rego,

0

Se si desidera il file da un determinato commit (qualsiasi ramo), dire 06f8251f

git checkout 06f8251f percorso_file_file

ad esempio, in windows:

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


1
Grazie per il tempo dedicato a rispondere! Ma questo non risponde alla domanda e una buona risposta molto dettagliata è già stata pubblicata 9 anni fa. Non è necessario rispondere alla domanda.
Nathan,

Questo è uno scenario pratico valido. La risposta si occupa correttamente del ramo, ma che dire di un particolare commit del ramo.
Arupjbasu,

0

Un altro modo è quello di creare una patch con le differenze e applicarla nel ramo master Ad esempio. Supponiamo che l'ultimo commit prima di iniziare a lavorare su app.js sia 00000aaaaa e il commit che contenga la versione desiderata sia 00000bbbbb

Lo esegui sul ramo dell'esperimento:

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

Questo creerà un file con tutte le differenze tra quei due commit per app.js che puoi applicare ovunque tu voglia. Puoi conservare quel file ovunque al di fuori del progetto

Quindi, in master, esegui semplicemente:

git apply ~/app_changes.git

ora vedrai i cambiamenti nei progetti come se li avessi fatti manualmente.


-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> 

Spero che questo ti possa aiutare. Per favore fatemi sapere se avete qualche domanda.

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.