Git: Come aggiornare / estrarre un singolo file dal master di origine remoto?


363

Lo scenario:

  1. Apporto alcune modifiche in un singolo file localmente ed eseguo git add, git commitegit push
  2. Il file viene inviato al repository principale di origine remoto
  3. Ho un altro repository locale che viene distribuito tramite Capistrano con il metodo "remote_cache" da quel repository remoto
  4. Ora non voglio distribuire l'intera applicazione, ma solo aggiornare / checkout quel singolo file.

Questo è in qualche modo possibile con Git? Non sono riuscito a trovare nulla che potesse funzionare, né sono riuscito a capirlo. Con SVN l'ho appena fatto svn up filee voilà.


19
Potresti voler considerare di cambiare la risposta accettata a quella che risponde effettivamente alla tua domanda. ;)
passi

6
Dopo più di 6 anni, credo che possiamo tranquillamente presumere che ciò non accadrà @steps ...
Félix Gagnon-Grenier

Con Git 2.23 (agosto 2019), lo è git restore -s origin/master -- path/to/file. Vedi la mia risposta qui sotto .
VonC,

Risposte:


915

È possibile farlo (nel repository distribuito)

git fetch
git checkout origin/master -- path/to/file

Il recupero scaricherà tutte le modifiche recenti, ma non le inserirà nel tuo attuale codice estratto (area di lavoro).

Il checkout aggiornerà l'albero di lavoro con il file specifico delle modifiche scaricate ( origin/master).

Almeno questo funziona per me per quelle piccole piccole correzioni di errori di battitura, in cui è strano creare un ramo ecc. Solo per cambiare una parola in un file.


1
Super utile, ha funzionato alla grande. Avevo bisogno di ottenere un file composer.json ed eseguire un aggiornamento prima di aggiornare il resto del sito in produzione. Se avessi messo manualmente i file composer.json / lock sul posto, quando ho fatto un pull, sarebbe in conflitto dicendo che i file esistevano già. In questo modo, git ha riconosciuto i file senza lamentele.
David,

6
Questa è la risposta che stavo cercando.
javadba,

20
@Mymozaaa Il doppio trattino indica che ciò che segue è un nome di file. Serve a impedire a git di interpretare il nome del tuo file come ramo nel caso sfortunato che ne hai due con lo stesso nome.
Joel Mellon,

Il problema è che stai ancora recuperando, e se si tratta di un repository di grandi dimensioni, sarà un'operazione costosa. Temo che l'unica alternativa sia installare gitweb sul telecomando e quindi accedervi per recuperare il file o simili.
Christian Goetze,

piccola domanda, dopo averlo fatto, vado su una macchina diversa, quindi eseguo le tue azioni sopra elencate, ma poi le git statusvedo come Changes to be committed:- ovvero, devo impegnarle di nuovo? (solo notando che volevo aggiornare un singolo file non toccato ma il repository stesso viene toccato in un'altra macchina)
Ricky Levi,

42

Il seguente codice ha funzionato per me:

     git fetch
     git checkout <branch from which file needs to be fetched> <filepath> 

19
git archive --format=zip --remote=ssh://<user>@<host>/repos/<repo name> <tag or HEAD> <filename> > <output file name>.zip

1
Questa è una buona soluzione per i repository clonati su ssh, ma sembra che questo non sia supportato su https: git archive --remote=https://github.com/git/git.git master:git/contrib/completion git-completion.bash | tar -x mi dà un messaggio di errore:fatal: Operation not supported by protocol.
Alderath

1
è stato bello combinato con tar: s --to-stdout,git archive --remote="gitolite3@<host>:<repo>" <tag> <file> | tar xf - --to-stdout
Puggan Se

19

Con Git 2.23 (agosto 2019) e il nuovo comando (ancora sperimentale) git restore, visto in " Come ripristinare tutti i file dalla directory di lavoro ma non dall'area di gestione temporanea? ", Sarebbe:

git fetch
git restore -s origin/master -- path/to/file

L'idea è: git restoresi occupa solo di file, non di file e rami git checkout.
Vedi " Confuso dagit checkout ": ecco dove git switchentra)


codersam aggiunge nei commenti :

nel mio caso volevo ottenere i dati dal mio monte (da cui ho biforcato).
Quindi appena cambiato in:

git restore -s upstream/master -- path/to/file

2
Che sollievo che finalmente esiste questo comando ... Cosa stavano facendo prima le persone git-cluefull? Stavo ripristinando tutto e copiando i singoli file di cui avevo bisogno, ma è stato doloroso.
Mike Wise,

Questo ha funzionato per me, ma nel mio caso volevo ottenere i dati dal mio upstream (da cui ho biforcato). Quindi appena cambiato ingit restore -s upstream/master -- path/to/file
coderSam

@coderSam Di te per questo feedback. Ho incluso il tuo commento nella risposta per una maggiore visibilità.
VonC

8

Quello che puoi fare è:

  1. Aggiorna il tuo repository git locale:

    git fetch

  2. Costruisci una filiale locale e verifica su di essa:

    git branch pouet && git checkout pouet

  3. Applica il commit desiderato su questo ramo:

    git cherry-pick abcdefabcdef

    (abcdefabcdef è lo sha1 del commit che si desidera applicare)


4
A parte questo, il tuo secondo passo può anche essere fatto in un comando come git checkout -b pouet.
Greg Hewgill,

4
'pouet' è il nome del ramo migliore per questo esempio.
Hussard il

2

O git stash (se hai delle modifiche) sul ramo in cui ti trovi, controlla master, ottieni le ultime modifiche, prendi quel file sul desktop (o sull'intera app). Dai un'occhiata alla filiale in cui ti trovavi. Git stash si applica nuovamente allo stato in cui ti trovavi, quindi correggi le modifiche manualmente o trascinalo sostituendo il file.

In questo modo non è così bello ma sicuramente funziona se non riuscite a capire nient'altro.


-10

Penso di aver trovato un trucco semplice.

Elimina il file che hai sul repository locale (il file che vuoi aggiornare dall'ultimo commit nel server remoto)

E poi fai un git pull

Poiché il file viene eliminato, non si verificheranno conflitti


Ciò rimuove tutte le eventuali modifiche apportate a quel file localmente e rimuove anche tutti gli altri file, che è specificamente ciò che l'OP non vuole fare.
legrojan,

Invece di aggiornare il ramo remoto, rimuovere local è una pessima idea.
c0der512,
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.