Ripristina il ramo del repository locale in modo che sia esattamente come HEAD del repository remoto


3858

Come reimpostare il mio ramo locale in modo che sia esattamente come il ramo sul repository remoto?

L'ho fatto:

git reset --hard HEAD

Ma quando eseguo un git status,

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
      modified:   java/com/mycompany/TestContacts.java
      modified:   java/com/mycompany/TestParser.java

Potete per favore dirmi perché ho questi "modificati"? Non ho toccato questi file? Se lo facessi, voglio rimuoverli.


8
Secondo l'output del git statustuo secondo comando git reset --hard HEADfallito. Non hai incollato il suo output, però. → Domanda incompleta.
Robert Siemer,

2
Qui si stanno mescolando due problemi: 1) come reimpostare un ramo locale al punto in cui si trova il telecomando e 2) come cancellare l'area di gestione temporanea (e possibilmente la directory di lavoro), in questo modo si git statusdice nothing to commit, working directory clean. - Per favore specificare!
Robert Siemer,

Risposte:


6700

L'impostazione del ramo in modo che corrisponda esattamente al ramo remoto può essere eseguita in due passaggi:

git fetch origin
git reset --hard origin/master

Se vuoi salvare lo stato della tua attuale filiale prima di farlo (per ogni evenienza), puoi fare:

git commit -a -m "Saving my work, just in case"
git branch my-saved-work

Ora il tuo lavoro viene salvato sul ramo "my-save-work" nel caso in cui decidi di volerlo indietro (o desideri guardarlo in un secondo momento o diffonderlo contro il tuo ramo aggiornato).

Si noti che il primo esempio presuppone che il nome del repository remoto sia "origine" e che il ramo denominato "master" nel repository remoto corrisponda al ramo attualmente estratto nel repository locale.

A proposito, questa situazione in cui ti trovi assomiglia moltissimo a un caso comune in cui è stata effettuata una spinta nel ramo attualmente estratto di un repository non nudo. Hai recentemente inserito il tuo repository locale? In caso contrario, non preoccuparti: qualcos'altro deve aver causato la modifica imprevista di questi file. Altrimenti, dovresti essere consapevole che non è consigliabile inserire un repository non bare (e non nel ramo attualmente estratto, in particolare).


4
La ringrazio per la risposta. Hai detto "Nota che il primo esempio presuppone che il nome del repository remoto sia" origine "e che il ramo denominato" master "nel repository remoto corrisponda al ramo nel repository locale." Come posso ricontrollare il nome del mio repository remoto e il nome del mio ramo per essere sicuro prima di eseguire 'git reset --hard'? Grazie ancora.
hap497,

21
Se non hai assegnato un nome esplicito al telecomando, è probabile che il nome sia semplicemente "origine" (impostazione predefinita). Puoi usare "git remote" per ottenere un elenco di tutti i nomi remoti. Puoi quindi usare "git remote <nome>" per vedere quali rami si spingono / tirano tra loro (es. Se il tuo ramo "master" è stato clonato da "master" nel telecomando chiamato "origin", allora otterrai una linea che dice "il master si fonde con il master remoto").
Dan Molding,

6
"non è consigliabile eseguire il push in un repository non bare (e non nel ramo attualmente estratto, in particolare" Why is that?
LeeGee

27
Subito dopo aver recuperato, credo che tu possa fare git reset FETCH_HEAD --hardanche quello, ma è lo stesso significato.
Jean,

6
Non ha rimosso i file che ho aggiunto.
Trismegistos,

417

Ho dovuto fare (la soluzione nella risposta accettata):

git fetch origin
git reset --hard origin/master

Seguito da:

git clean -f

per rimuovere i file locali

Per vedere quali file verranno rimossi (senza rimuoverli effettivamente):

git clean -n -f

89
inoltre, git clean -d -fse sono presenti directory non tracciate.
Garg

54
anchegit clean -fdx
Swapnil Kotwal,

14
Se vuoi una copia esatta del ramo remoto devi seguire con git clean -ffdx. Si noti che thare sono due f.
Trismegisto,

6
L' git clean -fera il pezzo essenziale di cui avevo bisogno. Grazie!
dal

17
fai attenzione usando il comando clean. può eliminare file ignorati da altri rami.
mikoop,

307

Innanzitutto, ripristina il precedente recupero HEADdel ramo upstream corrispondente:

git reset --hard @{u}

Il vantaggio di specificare @{u}o la sua forma dettagliata @{upstream}è che non è necessario specificare esplicitamente il nome del repository remoto e del ramo.

Successivamente, se necessario, rimuovere i file non tracciati, facoltativamente anche con -x:

git clean -df

Infine, se necessario, ottieni le ultime modifiche:

git pull

54
Questa sembra una risposta migliore di quella accettata, perché si reimposta dinamicamente all'attuale ramo a monte piuttosto che sempre a una statica comeorigin/master
Jon z

@Jonz, @{upstream}è molto utile e può essere usato negli alias:alias resetthisbranch="git reset --hard @{upstream}"
Siddhartha,

1
@GangadharJannu git reset --hardrichiede un commit, altrimenti non saprebbe cosa reimpostare. @{u}punta a un commit specifico: il capo del ramo tracciato, dall'ultima volta che hai fatto un git fetch.
Kristoffer Bakkejord,

1
@KristofferBakkejord Grazie per la spiegazione ma anche senza commit hash possiamo fare git reset --hardanche se non si ripristinerà al ramo remoto
Gangadhar JANNU

3
Per chiunque abbia quasi aperto una nuova domanda qui, se si esce da Powershell, utilizzare le virgolette ( git reset --hard "@{u}"). Mi ci è voluto un po 'per capirlo.
MPStoering,

112

git reset --hard HEADin realtà ripristina solo l'ultimo stato impegnato. In questo caso, HEAD si riferisce alla HEAD del tuo ramo.

Se hai diversi commit, questo non funzionerà ..

Ciò che probabilmente si desidera fare è reimpostare il responsabile dell'origine o come viene chiamato il repository remoto. Probabilmente farei qualcosa del genere

git reset --hard origin/HEAD

Stai attento però. I ripristini hardware non possono essere annullati facilmente. È meglio fare come Dan suggerisce e ramificare una copia delle modifiche prima di ripristinare.


2
Nella mia risposta c'era un suggerimento errato che Dan aveva colto in precedenza. L'ho modificato, dal momento che non voglio sviare nessuno. Per quanto riguarda l'origine / master o l'origine / HEAD, mi aspetto che dipenda dal fatto che tu effettivamente esegua o meno un prelievo prima. Se hai appena clonato l'origine e non aveva altri rami, che trovo abbastanza comuni, allora dovrebbe ripristinarlo bene. Ma ovviamente Dan ha ragione.
Mikael Ohlson,

73

Tutti i suggerimenti sopra riportati sono giusti, ma spesso per ripristinare davvero il tuo progetto, devi anche rimuovere anche i file presenti nel tuo .gitignore.

Per ottenere l'equivalente morale della cancellazione della directory del progetto e della ri-clonazione dal telecomando è:

git fetch
git reset --hard
git clean -x -d -f

Attenzione : git clean -x -d -fè irreversibile e potresti perdere file e dati (ad es. Cose che hai ignorato durante l'uso .gitignore).


12
Attenzione: "git clean -x -d -f" è irreversibile e potresti perdere file e dati in
.gitignore

Un po 'più corto: git clean -xdfè uguale a git clean -x -d -f.
Kiryl,

git clean -ffxd per rimuovere tutto ciò che non è nel repository
Trismegistos il

44

Utilizzare i comandi seguenti. Questi comandi rimuoveranno anche tutti i file non tracciati da git locale

git fetch origin
git reset --hard origin/master
git clean -d -f

6
Questa è una risposta più completa perché senza il git clean -d -fnon avremmo ancora alcune cose del vecchio ramo nella directory locale. Grazie uomo.
Flavio,

3
Questo è REALMENTE ciò che lo rende come il telecomando. La pulizia è importante.
David S.

1
git clean -ffxd per rimuovere veramente tutto
Trismegistos

1
Questo è esattamente ciò di cui avevo bisogno. Grazie
AllJs

38

La domanda mescola due problemi qui:

  1. come ripristinare un ramo locale al punto in cui si trova il telecomando
  2. come cancellare l'area di gestione temporanea (e possibilmente la directory di lavoro), così git statusdicenothing to commit, working directory clean.

La risposta unica è:

  1. git fetch --prune (facoltativo) Aggiorna l'istantanea locale del repository remoto. Ulteriori comandi sono solo locali.
    git reset --hard @{upstream}Posiziona il puntatore del ramo locale sul punto in cui si trova l'istantanea del telecomando, nonché imposta l'indice e la directory di lavoro sui file di quel commit.
  2. git clean -d --force Rimuove file e directory non tracciati che impediscono a git di dire "directory di lavoro pulita".

1
La @{upstream}sintassi richiede che sia impostato l'upstream che si verifica di default se si git checkout <branchname>. - Altrimenti sostituirlo con origin/<branchname>.
Robert Siemer,

Aggiungi -xa git cleanper rimuovere tutto ciò che non è presente nel commit (ovvero anche i file ignorati con il meccanismo .gitignore).
Robert Siemer,

22

Questo è qualcosa che devo affrontare regolarmente e ho generalizzato la sceneggiatura fornita da Wolfgang sopra per lavorare con qualsiasi ramo

Ho anche aggiunto un prompt "sei sicuro" e alcuni output di feedback

#!/bin/bash
# reset the current repository
# WF 2012-10-15
# AT 2012-11-09
# see http://stackoverflow.com/questions/1628088/how-to-reset-my-local-repository-to-be-just-like-the-remote-repository-head
timestamp=`date "+%Y-%m-%d-%H_%M_%S"`
branchname=`git rev-parse --symbolic-full-name --abbrev-ref HEAD`
read -p "Reset branch $branchname to origin (y/n)? "
[ "$REPLY" != "y" ] || 
echo "about to auto-commit any changes"
git commit -a -m "auto commit at $timestamp"
if [ $? -eq 0 ]
then
  echo "Creating backup auto-save branch: auto-save-$branchname-at-$timestamp"
  git branch "auto-save-$branchname-at-$timestamp" 
fi
echo "now resetting to origin/$branchname"
git fetch origin
git reset --hard origin/$branchname

3
potresti voler usare "git remote" per ottenere il nome del telecomando. In alcuni casi, non sarà "origine"
Yurik,

17

A condizione che il repository remoto sia origine che ti interessi branch_name:

git fetch origin
git reset --hard origin/<branch_name>

Inoltre, vai a ripristinare il ramo corrente di origina HEAD.

git fetch origin
git reset --hard origin/HEAD

Come funziona:

git fetch origin scarica le ultime dal telecomando senza tentare di unire o rifare nulla.

Quindi git resetreimposta il <branch_name>ramo su ciò che hai appena recuperato. L' --hardopzione modifica tutti i file dell'albero di lavoro in modo che corrispondano ai file in origin/branch_name.


14

L'ho fatto:

git branch -D master
git checkout master

per ripristinare completamente il ramo


si noti che è necessario effettuare il checkout in un altro ramo per poter eliminare il ramo richiesto


5
Dovresti leggere di nuovo la domanda, non c'è nulla sull'influenza del telecomando, ma impostare lo stesso sul telecomando, quindi non dovresti fare nulla con il telecomando, e questo mi ha aiutato nel mio caso e non sopra.
user2846569

Se vuoi impostarlo allo stesso modo del telecomando, dovresti almeno fare un recupero ad un certo punto, non sei d'accordo?
Tim

2
dovresti almeno provare questo o leggere documenti: kernel.org/pub/software/scm/git/docs/git-checkout.html
user2846569

Ben fatto, avevo un file .pck corrotto nel ramo e il resto delle opzioni non funzionava, grazie !!
LuckyBrain,

14

Ecco uno script che automatizza ciò che suggerisce la risposta più popolare ... Vedi https://stackoverflow.com/a/13308579/1497139 per una versione migliorata che supporta i rami

#!/bin/bash
# reset the current repository
# WF 2012-10-15
# see /programming/1628088/how-to-reset-my-local-repository-to-be-just-like-the-remote-repository-head
timestamp=`date "+%Y-%m-%d-%H_%M_%S"`
git commit -a -m "auto commit at $timestamp"
if [ $? -eq 0 ]
then
  git branch "auto-save-at-$timestamp" 
fi
git fetch origin
git reset --hard origin/master

10

Se hai avuto un problema come me, che hai già apportato alcune modifiche, ma ora, per qualsiasi motivo, vuoi sbarazzartene, il modo più veloce è quello di utilizzare in git resetquesto modo:

git reset --hard HEAD~2

Avevo 2 commit non necessari, quindi il numero 2. È possibile modificarlo con il proprio numero di commit da ripristinare.

Quindi rispondi alla tua domanda: se hai 5 commit prima del repository remoto HEAD, dovresti eseguire questo comando:

git reset --hard HEAD~5

Nota che perderai le modifiche apportate, quindi fai attenzione!


7

Le risposte precedenti presuppongono che il ramo da ripristinare sia il ramo corrente (estratto). Nei commenti, OP hap497 ha chiarito che il ramo è effettivamente verificato, ma ciò non è esplicitamente richiesto dalla domanda originale. Poiché esiste almeno una domanda "duplicata", reimposta il ramo completamente allo stato del repository , che non presuppone che il ramo sia stato estratto, ecco un'alternativa:

Se il ramo "mybranch" non è attualmente estratto, per reimpostare la testa del ramo remoto "myremote / mybranch", è possibile utilizzare questo comando di basso livello :

git update-ref refs/heads/mybranch myremote/mybranch

Questo metodo lascia il ramo estratto così com'è e l'albero di lavoro non viene toccato. Sposta semplicemente la testa di mybranch a un altro commit, qualunque sia la seconda argomentazione. Ciò è particolarmente utile se è necessario aggiornare più filiali a nuove testine remote.

Prestare attenzione nel fare ciò, tuttavia, e utilizzare gitko uno strumento simile per ricontrollare l'origine e la destinazione. Se lo fai accidentalmente sul ramo corrente (e git non ti impedirà di farlo), potresti confonderti, perché il nuovo contenuto del ramo non corrisponde all'albero di lavoro, che non è cambiato (per correggere, aggiorna nuovamente il ramo, dove era prima).


7

Questo è quello che uso spesso:

git fetch upstream develop;
git reset --hard upstream/develop;
git clean -d --force;

Si noti che è buona pratica di non apportare modifiche al tuo padrone locale / sviluppare ramo, ma invece cassa ad un altro ramo per ogni cambiamento, con il nome del ramo preposto per il tipo di modifica, ad esempio feat/, chore/, fix/, ecc Così si solo bisogno di estrarre le modifiche, non inviare alcuna modifica dal master. Stessa cosa per altri settori a cui altri contribuiscono. Quindi, quanto sopra dovrebbe essere usato solo se ti è capitato di eseguire il commit delle modifiche in una succursale a cui altri si sono impegnati e che è necessario ripristinare. Altrimenti, in futuro, evitare di spingere verso un ramo verso il quale gli altri spingono, invece fare il checkout e spingere verso quel ramo tramite il ramo estratto.

Se vuoi reimpostare il tuo ramo locale sull'ultimo commit nel ramo a monte, quello che funziona per me finora è:

Controlla i telecomandi, assicurati che l'upstream e l'origine siano quelli che ti aspetti, se non come previsto, quindi utilizza git remote add upstream <insert URL>, ad esempio, il repository GitHub originale da cui hai effettuato la forchetta e / o git remote add origin <insert URL of the forked GitHub repo>.

git remote --verbose

git checkout develop;
git commit -m "Saving work.";
git branch saved-work;
git fetch upstream develop;
git reset --hard upstream/develop;
git clean -d --force

Su GitHub, puoi anche fare il checkout del ramo con lo stesso nome di quello locale, al fine di salvare lì il lavoro, sebbene ciò non sia necessario se origin sviluppo ha le stesse modifiche del ramo del lavoro salvato locale. Sto usando il ramo di sviluppo come esempio, ma può essere qualsiasi nome di ramo esistente.

git add .
git commit -m "Reset to upstream/develop"
git push --force origin develop

Quindi, se è necessario unire queste modifiche con un altro ramo mentre ci sono conflitti, preservando le modifiche in sviluppo, utilizzare:

git merge -s recursive -X theirs develop

Durante l'uso

git merge -s recursive -X ours develop

per preservare le modifiche contrastanti di branch_name. Altrimenti usa un mergetool con git mergetool.

Con tutte le modifiche insieme:

git commit -m "Saving work.";
git branch saved-work;
git checkout develop;
git fetch upstream develop;
git reset --hard upstream/develop;
git clean -d --force;
git add .;
git commit -m "Reset to upstream/develop";
git push --force origin develop;
git checkout branch_name;
git merge develop;

Nota che invece di upstream / sviluppo puoi usare un hash di commit, un altro nome di ramo, ecc. Usa uno strumento CLI come Oh My Zsh per verificare che il tuo ramo sia verde indicando che non c'è nulla da impegnare e che la directory di lavoro sia pulita ( che è confermato o anche verificabile da git status). Si noti che questo può effettivamente aggiungere commit rispetto al monte sviluppare se c'è qualcosa di aggiunto automaticamente da un commit, ad esempio diagrammi UML, intestazioni di licenza, ecc, quindi in questo caso, si potrebbe poi tirare le modifiche su origin developdi upstream develop, se necessario.


6

La risposta

git clean -d -f

era sottovalutato ( -d per rimuovere le directory). Grazie!


E per una cartella repo completa e pulita al 100% senza file extra, esegui git clean -xdf. Questo eliminerà tutti i file di cui git non è a conoscenza e farà corrispondere esattamente la tua cartella a quella che è nella lista degli oggetti di git. Nota che puoi aggiungere -n(es. git clean -nxdf) Per eseguire un "what-if" e ti dirà cosa eliminerà senza fare nulla. ( git clean )
qJake

5

Se vuoi tornare allo HEADstato sia per la directory di lavoro che per l'indice, allora dovresti git reset --hard HEAD, piuttosto che farlo HEAD^. (Questo potrebbe essere stato un refuso, proprio come il trattino singolo contro doppio per--hard .)

Per quanto riguarda la tua domanda specifica sul perché quei file compaiano nello stato come modificati, sembra che tu abbia fatto un soft reset invece di un hard reset. Ciò farà HEADapparire i file modificati nel commit come se fossero stati messi in scena, il che è probabilmente quello che stai vedendo qui.


4

Nessuna quantità di reset e pulizia sembrava avere alcun effetto sui file non tracciati e modificati nel mio repository git locale (ho provato tutte le opzioni sopra). La mia unica soluzione a questo era di rm il repository locale e clonarlo nuovamente dal telecomando.

Fortunatamente non avevo altre filiali a cui tenessi.

xkcd: Git


1

L'unica soluzione che funziona in tutti i casi che ho visto è eliminare e riposare. Forse c'è un altro modo, ma ovviamente in questo modo non c'è alcuna possibilità che il vecchio stato venga lasciato lì, quindi lo preferisco. Bash one-liner che puoi impostare come macro se sbagli spesso cose in git:

REPO_PATH=$(pwd) && GIT_URL=$(git config --get remote.origin.url) && cd .. && rm -rf $REPO_PATH && git clone --recursive $GIT_URL $REPO_PATH && cd $REPO_PATH

* presume che i tuoi file .git non siano corrotti


4
puoi anche reinstallare il tuo sistema operativo se vuoi essere certo!
Sebastian Scholle,

1

Hai dimenticato di creare un ramo di funzionalità e ti sei impegnato direttamente sul master per errore?

È possibile creare subito il ramo delle funzionalità e ripristinare il master senza influire sul worktree (filesystem locale) per evitare di generare build, test e problemi con i blocchi dei file:

git checkout -b feature-branch
git branch -f master origin/master

1

Solo 3 comandi lo faranno funzionare

git fetch origin
git reset --hard origin/HEAD
git clean -f

-3

Se non ti dispiace salvare le modifiche locali, ma desideri comunque aggiornare il repository in modo che corrisponda a origine / HEAD, puoi semplicemente nascondere le modifiche locali e quindi estrarre:

git stash
git pull
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.