Come impongo “git pull” per sovrascrivere i file locali?

Come posso forzare una sovrascrittura di file locali su un git pull ?

Lo scenario sta seguendo:

  • Un membro del team sta modificando i modelli per un sito web su cui stiamo lavorando
  • Aggiungono alcune immagini alla directory delle immagini (ma dimentica di aggiungerle sotto il controllo del codice sorgente)
  • Stanno inviando le immagini per posta, più tardi, a me
  • Sto aggiungendo le immagini sotto il controllo del codice sorgente e inserendole in GitHub insieme ad altre modifiche
  • Non possono estrarre gli aggiornamenti da GitHub perché Git non vuole sovrascrivere i loro file.

Questo è l’errore che sto ottenendo:

 error: Untracked working tree file 'public/images/icon.gif' would be overwritten by merge 

Come faccio a forzare Git a sovrascriverli? La persona è un designer – di solito risolvo tutti i conflitti a mano, quindi il server ha la versione più recente che devono solo aggiornare sul proprio computer.

Importante: se si verificano modifiche locali, queste verranno perse. Con o senza opzione --hard , qualsiasi commit locale che non è stato premuto verrà perso. [*]

Se si dispone di file non tracciati da Git (ad es. Contenuto utente caricato), questi file non saranno interessati.


Penso che questo sia il modo giusto:

 git fetch --all 

Quindi, hai due opzioni:

 git reset --hard origin/master 

OPPURE Se ti trovi in ​​qualche altro ramo:

 git reset --hard origin/ 

Spiegazione:

git fetch scarica le ultime dal remoto senza tentare di unire o rebase nulla.

Quindi il git reset reimposta il ramo master su ciò che hai appena recuperato. L’opzione --hard cambia tutti i file nell’albero di lavoro in modo che corrispondano ai file in origin/master


Mantieni i commit locali correnti

[*] : Vale la pena notare che è ansible mantenere i commit locali correnti creando un branch dal master prima di resettare:

 git checkout master git branch new-branch-to-save-current-commits git fetch --all git reset --hard origin/master 

Dopodiché, tutti i vecchi commit saranno mantenuti in commit da new-branch-to-save-current-commits .

Modifiche non commesse

Le modifiche non applicate, tuttavia (anche messe in scena), andranno perse. Assicurati di mettere da parte e salvare tutto ciò di cui hai bisogno. Per questo è ansible eseguire quanto segue:

 git stash 

E poi riapplicare queste modifiche senza commit:

 git stash pop 

Prova questo:

 git reset --hard HEAD git pull 

Dovrebbe fare quello che vuoi.

ATTENZIONE: git clean cancella tutti i file / directory non tracciati e non può essere annullato.


A volte basta clean -f non aiuta. Nel caso in cui tu abbia DIRECTORIES non tracciati, anche l’opzione -d ha bisogno di:

 # WARNING: this can't be undone! git reset --hard HEAD git clean -f -d git pull 

ATTENZIONE: git clean cancella tutti i file / directory non tracciati e non può essere annullato.

Prendi in considerazione l’uso del flag -n ( --dry-run ) per primo. Questo ti mostrerà ciò che sarà cancellato senza effettivamente eliminare nulla:

 git clean -n -f -d 

Esempio di output:

 Would remove untracked-file-1.txt Would remove untracked-file-2.txt Would remove untracked/folder ... 

Come Riccio penso che le risposte siano terribili. Ma anche se la risposta di Hedgehog potrebbe essere migliore, non penso che sia così elegante come potrebbe essere. Il modo in cui ho trovato di farlo è utilizzando “fetch” e “merge” con una strategia definita. Il che dovrebbe fare in modo che le modifiche locali vengano mantenute purché non siano uno dei file con cui si tenta di forzare una sovrascrittura.

Prima fai un commit delle tue modifiche

  git add * git commit -a -m "local file server commit message" 

Quindi recuperare le modifiche e sovrascrivere se c’è un conflitto

  git fetch origin master git merge -s recursive -X theirs origin/master 

“-X” è un nome di opzione e “loro” è il valore per tale opzione. Stai scegliendo di utilizzare le “loro” modifiche, invece delle “tue” modifiche se c’è un conflitto.

Invece di fare:

 git fetch --all git reset --hard origin/master 

Consiglierei di fare quanto segue:

 git fetch origin master git reset --hard origin/master 

Non è necessario recuperare tutti i telecomandi e le derivazioni se si intende ripristinare la diramazione origine / master correttamente?

Sembra che il modo migliore sia fare prima:

 git clean 

Per eliminare tutti i file non tracciati e quindi continuare con il solito git pull

Attenzione, facendo questo eliminerai definitivamente i tuoi file se hai qualche directory / * nel tuo file gitignore.

Alcune risposte sembrano essere terribili. Terribile nel senso di ciò che è successo a @Lauri seguendo il suggerimento di David Avsajanishvili.

Piuttosto (git> v1.7.6):

 git stash --include-untracked git pull 

Più tardi puoi pulire la cronologia di scorta.

Manualmente, uno per uno:

 $ git stash list stash@{0}: WIP on : ... stash@{1}: WIP on : ... $ git stash drop stash@{0} $ git stash drop stash@{1} 

Brutalmente, tutto in una volta:

 $ git stash clear 

Certo, se vuoi tornare a ciò che hai nascosto:

 $ git stash list ... $ git stash apply stash@{5} 

Potresti trovare utile questo comando per eliminare le modifiche locali:

 git checkout  -f 

E poi fai una pulizia (rimuove i file non tracciati dall’albero di lavoro):

 git clean -f 

Se si desidera rimuovere le directory non tracciate oltre ai file non tracciati:

 git clean -fd 

Invece di fondersi con git pull , prova questo:

git fetch --all

seguito da:

git reset --hard origin/master .

L’unica cosa che ha funzionato per me è stata:

 git reset --hard HEAD~5 

Questo ti riporterà cinque commit e poi con

 git pull 

L’ho trovato cercando come annullare una fusione Git .

Il problema con tutte queste soluzioni è che sono tutte o troppo complesse, o, un problema ancora più grande, è che rimuovono tutti i file non tracciati dal server web, cosa che non vogliamo visto che ci sono sempre file di configurazione necessari che sono attivi il server e non nel repository Git.

Ecco la soluzione più pulita che stiamo usando:

 # Fetch the newest code git fetch # Delete all files which are being added, so there # are no conflicts with untracked files for file in `git diff HEAD..origin/master --name-status | awk '/^A/ {print $2}'` do rm -f -- "$file" done # Checkout all files which were locally modified for file in `git diff --name-status | awk '/^[CDMRTUX]/ {print $2}'` do git checkout -- "$file" done # Finally pull all the changes # (you could merge as well eg 'merge origin/master') git pull 
  • Il primo comando recupera i dati più recenti.

  • Il secondo comando controlla se ci sono file che vengono aggiunti al repository ed elimina quei file non tracciati dal repository locale che causerebbero conflitti.

  • Il terzo comando controlla tutti i file che sono stati modificati localmente.

  • Infine eseguiamo un pull per aggiornare la versione più recente, ma questa volta senza conflitti, poiché i file non tracciati che sono nel repository non esistono più e tutti i file modificati localmente sono già gli stessi del repository.

Ho avuto lo stesso problema. Nessuno mi ha dato questa soluzione, ma ha funzionato per me.

L’ho risolto da:

  1. Cancellare tutti i file. Lascia solo la directory .git.
  2. git reset --hard HEAD
  3. git pull
  4. git push

Ora funziona.

Prima di tutto, prova il modo standard:

 git reset HEAD --hard # Remove all not committed changes 

Se sopra non ti sarà d’aiuto e non ti preoccuperai dei tuoi file / directory non tracciati (fai il backup prima solo nel caso), prova i seguenti semplici passaggi:

 cd your_git_repo # where 'your_git_repo' is your git repository folder rm -rfv * # WARNING: only run inside your git repository! git pull # pull the sources again 

Questo rimuoverà tutti i file git (es. .Git .git/ dir, dove hai tutti i commit) e lo tiri di nuovo.


Perché git reset HEAD --hard potrebbe fallire in alcuni casi?

  1. Regole personalizzate nel .gitattributes file

    Avere eol=lf regola in .gitattributes potrebbe far sì che git modifichi alcune modifiche ai file convertendo le terminazioni di riga CRLF in LF in alcuni file di testo.

    In questo caso, devi impegnare queste modifiche CRLF / LF (esaminandole in git status ), oppure provare: git config core.autcrlf false in modo temporaneo ignorarle.

  2. Incapacità del file system

    Quando si utilizza il file system che non supporta gli attributi di authorization. Nell’esempio si hanno due repository, uno su Linux / Mac ( ext3 / hfs+ ) e un altro su file system basato su FAT32 / NTFS.

    Come noti, ci sono due diversi tipi di file system, quindi quello che non supporta i permessi Unix fondamentalmente non può resettare i permessi dei file sul sistema che non supporta quel tipo di permessi, quindi non importa quanto --hard tu prova, git rileva sempre alcuni “cambiamenti”.

Ho avuto un problema simile. Dovevo fare questo:

 git reset --hard HEAD git clean -f git pull 

Ho riassunto altre risposte. Puoi eseguire git pull senza errori:

 git fetch --all git reset --hard origin/master git reset --hard HEAD git clean -f -d git pull 

Attenzione : questo script è molto potente, quindi potresti perdere le tue modifiche.

Sulla base delle mie esperienze simili, la soluzione offerta da Strahinja Kustudic sopra è di gran lunga la migliore. Come altri hanno sottolineato, la semplice reimpostazione completa rimuoverà tutti i file non tracciati che potrebbero includere molte cose che non si desidera rimuovere, come i file di configurazione. Ciò che è più sicuro, è quello di rimuovere solo i file che stanno per essere aggiunti, e per questo, è probabile che si voglia anche fare il checkout di tutti i file modificati localmente che stanno per essere aggiornati.

Tenendo a mente, ho aggiornato lo script di Kustudic per fare proprio questo. Ho anche corretto un refuso (mancante nell’originale).

 #/bin/sh # Fetch the newest code git fetch # Delete all files which are being added, # so there are no conflicts with untracked files for file in `git diff HEAD..origin/master --name-status | awk '/^A/ {print $2}'` do echo "Deleting untracked file $file..." rm -vf "$file" done # Checkout all files which have been locally modified for file in `git diff HEAD..origin/master --name-status | awk '/^M/ {print $2}'` do echo "Checking out modified file $file..." git checkout $file done # Finally merge all the changes (you could use merge here as well) git pull 

Bonus:

Parlando di pull / fetch / merge nelle risposte precedenti, mi piacerebbe condividere un trucco interessante e produttivo,

git pull --rebase

Questo comando sopra è il comando più utile nella mia vita Git che ha risparmiato un sacco di tempo.

Prima di spingere il tuo nuovo commit al server, prova questo comando e sincronizzerà automaticamente le ultime modifiche del server (con un fetch + unisci) e posizionerà il tuo commit nella parte superiore del log Git. Non c’è alcun bisogno di preoccuparsi di pull / fusione manuale.

Trova i dettagli in Cosa fa “git pull –rebase”? .

Credo che ci siano due possibili cause di conflitto, che devono essere risolte separatamente, e per quanto posso dire, nessuna delle risposte di cui sopra si occupa di entrambi:

  • I file locali che non sono tracciati devono essere eliminati, manualmente (più sicuro) o come suggerito in altre risposte, da git clean -f -d

  • Anche i commit locali che non sono sul ramo remoto devono essere cancellati. IMO il modo più semplice per ottenere questo è con: git reset --hard origin/master (sostituisci ‘master’ con qualsiasi ramo su cui stai lavorando, ed esegui prima una git fetch origin )

Un modo più semplice sarebbe:

 git checkout --theirs /path/to/file.extension git pull origin master 

Questo sovrascriverà il tuo file locale con il file su git

Sembra che la maggior parte delle risposte qui siano focalizzate sul ramo master ; tuttavia, ci sono momentjs in cui sto lavorando sullo stesso ramo di funzionalità in due luoghi diversi e voglio che un rebase in uno si rifletta nell’altro senza un sacco di salti mortali.

Basato su una combinazione di risposta di RNA e risposta di torek a una domanda simile , ho trovato questo che funziona splendidamente:

 git fetch git reset --hard @{u} 

Esegui questo da un ramo e reimposterà solo il tuo ramo locale alla versione upstream.

Questo può anche essere inserito in un alias git forcepull ( git forcepull ):

git config alias.forcepull "!git fetch ; git reset --hard @{u}"

Oppure, nel tuo file .gitconfig :

 [alias] forcepull = "!git fetch ; git reset --hard @{u}" 

Godere!

Ho avuto lo stesso problema e per qualche ragione, anche un git clean -f -d non lo farebbe. Ecco perché: per qualche ragione, se il tuo file viene ignorato da Git (tramite una voce .gitignore, presumo), si preoccupa ancora di sovrascriverlo con un pull successivo, ma un clean non lo rimuoverà, a meno che tu aggiunga -x .

L’ho appena risolto da solo:

 git checkout -b tmp # "tmp" or pick a better name for your local changes branch git add -A git commit -m 'tmp' git pull git checkout master # Or whatever branch you were on originally git pull git diff tmp 

dove l’ultimo comando fornisce un elenco delle modifiche locali. Continua a modificare il ramo “tmp” finché non è accettabile e quindi unisci di nuovo a master con:

 git checkout master && git merge tmp 

Per la prossima volta, probabilmente puoi gestirlo in un modo più pulito cercando “git stash branch”, anche se lo stash rischia di causare problemi nei primi tentativi, quindi fai il primo esperimento su un progetto non critico …

Ho una strana situazione che né git clean o git reset funziona. Devo rimuovere il file in conflitto da git index usando il seguente script su ogni file non tracciato:

 git rm [file] 

Allora sono in grado di tirare bene.

Questi quattro comandi funzionano per me.

 git reset --hard HEAD git checkout origin/master git branch -D master git checkout -b master 

Per controllare / tirare dopo aver eseguito questi comandi

 git pull origin master 

Ho provato molto ma alla fine ho avuto successo con questi comandi.

Nonostante la domanda iniziale, le risposte migliori possono causare problemi a chi ha un problema simile, ma non vogliono perdere i file locali. Ad esempio, vedi i commenti di Al-Punk e crizCraig.

La seguente versione impegna le modifiche locali a un ramo temporaneo ( tmp ), controlla il ramo originale (che presumo sia il master ) e unisce gli aggiornamenti. Si potrebbe fare questo con la stash , ma ho scoperto che di solito è più semplice usare semplicemente l’approccio branch / merge.

 git checkout -b tmp git add *; git commit -am "my temporary files" git checkout master git fetch origin master git merge -s recursive -X theirs origin master 

dove assumiamo che l’ altro repository sia origin master .

Basta fare

 git fetch origin branchname git checkout -f origin/branchname // This will overwrite ONLY new included files git checkout branchname git merge origin/branchname 

In questo modo si evitano tutti gli effetti collaterali indesiderati, come l’eliminazione di file o directory che si desidera conservare, ecc.

Ripristina l’indice e la testa in origin/master , ma non resetta l’albero di lavoro:

 git reset origin/master 

Conosco un metodo molto più facile e meno doloroso:

 $ git branch -m [branch_to_force_pull] tmp $ git fetch $ git checkout [branch_to_force_pull] $ git branch -D tmp 

Questo è tutto!

Ho letto tutte le risposte ma stavo cercando un singolo comando per farlo. Ecco cosa ho fatto. Aggiunto un alias git a .gitconfig

 [alias] fp = "!f(){ git fetch ${1} ${2} && git reset --hard ${1}/${2};};f" 

Esegui il tuo comando come

 git fp origin master 

equivalente a

 git fetch origin master git reset --hard origin/master 

Requisiti:

  1. Tieni traccia dei cambiamenti locali così nessuno li perde mai.
  2. Rendere il repository locale corrispondente al repository di origine remoto.

Soluzione:

  1. Conserva le modifiche locali.
  2. Scarica con una pulizia di file e directory ignorando .gitignore e hard reset all’origine .

     git stash --include-untracked git fetch --all git clean -fdx git reset --hard origin/master