È necessario ripristinare git branch alla versione di origine


439

Stavo lavorando accidentalmente su un ramo che non avrei dovuto fare per un po ', quindi mi sono ramificato dandogli il nome appropriato. Ora voglio sovrascrivere il ramo che non avrei dovuto essere sulla versione da origin (github). C'è un modo semplice per farlo? Ho provato a eliminare il ramo e quindi a ripristinare il ramo di monitoraggio, ma mi dà solo la versione su cui stavo lavorando di nuovo.



Con Git 2.23 (agosto 2019): git switch -C mybranch origin/mybranch. Vedi la mia risposta modificata di seguito
VonC

Risposte:


815

Se non hai ancora inviato l'origine, puoi reimpostare il ramo sul ramo a monte con:

git checkout mybranch
git reset --hard origin/mybranch

(Assicurati di fare riferimento al tuo ultimo commit in un ramo separato, come menzionato nella tua domanda)

Si noti che subito dopo il ripristino, mybranch@{1} riferisce al vecchio commit, prima del ripristino.

Ma se hai già eseguito il push, vedi " Crea ramo git e ripristina lo stato originale a monte " per altre opzioni.


Con Git 2.23 (agosto 2019) , che sarebbe un comando: git switch.
Vale a dire:git switch -C mybranch origin/mybranch

Esempio

C:\Users\vonc\git\git>git switch -C master origin/master
Reset branch 'master'
Branch 'master' set up to track remote branch 'master' from 'origin'.
Your branch is up to date with 'origin/master'.

Ciò ripristina l'indice e l'albero di lavoro, come git reset --hardfarebbe.


Come commentato da Brad Herman , una reset --hardsarebbe rimuovere ogni nuovo file o ripristinare file modificato TESTA .

In realtà, per essere sicuri di iniziare da una "lavagna pulita", un git clean -f -ddopo il reset assicurerebbe un albero di lavoro esattamente identico al ramo su cui hai appena ripristinato.


Questo post sul blog suggerisce quegli alias ( mastersolo per branch, ma puoi adattarli / estenderli):

[alias]
   resetorigin = !git fetch origin && git reset --hard origin/master && git clean -f -d
   resetupstream = !git fetch upstream && git reset --hard upstream/master && git clean -f -d

Quindi puoi digitare:

git resetupstream

o

git resetorigin

26
questo ELIMINERÀ le modifiche NON STAGNATE / STAGATE (dal --hard)
Peter Ehrlich,

5
Ho usato il git reset --hard origin/mybranchcomando diverse volte quando non mi importava di eventuali modifiche locali e volevo solo una copia pulita che corrispondesse all'origine. Tuttavia, oggi, questo non ha funzionato - avevo ancora una manciata di file nuovi, non messi in scena, e git continuava a promettermi che era su HEAD. La nota su git clean -f -drisolto questo cancellando tutti i nuovi file che non volevo.
Matthew Clark,

@MatthewClark che ci si aspetta: vedi commento sulla stackoverflow.com/q/4327708/6309
VonC

1
Grande! Inoltre molte volte sono git reset --hard HEADtornato a un precedente commit, ignorando qualsiasi modifica
daronwolff,

Questo è possibile anche con sourctree?
Lonzak,

20

Supponendo che questo sia ciò che è successo:

# on branch master
vi buggy.py                 # you edit file
git add buggy.py            # stage file
git commit -m "Fix the bug" # commit
vi tests.py                 # edit another file but do not commit yet

Quindi ti rendi conto di apportare modifiche sul ramo sbagliato.

git checkout -b mybranch    # you create the correct branch and switch to it

Ma master indica ancora il tuo impegno. Vuoi che indichi dove puntava prima.

Soluzione

Il modo più semplice è:

git branch --force master origin/master

Un altro modo è:

git checkout master
git reset --soft origin/master
git checkout mybranch

Nota che l'uso reset --hardcauserà la perdita delle modifiche non impegnate ( tests.pynel mio esempio).


Sembra più sicuro che nella mia risposta;) +1
VonC

8

Ho un repository privato su un server e regolarmente reindirizzare / forzare ad esso, il che rende necessario reimpostare spesso il ramo locale sull'altro mio computer. Ho quindi creato il seguente alias "catchup", che consente di farlo per il ramo corrente. A differenza dell'altra risposta, non esiste un nome di ramo codificato in questo alias.

Tieniti forte.

[alias]
  catchup = "!f(){ echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \"; read -r ans; if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)); else echo \"catchup aborted\"; fi }; f"

Formattato correttamente (non funzionerà con le nuove righe in .gitconfig) è simile al seguente:

"
!f(){
  echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \";
  read -r ans;
  if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then
    git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD));
  else
    echo \"catchup aborted\";
  fi
}; f
"
  • L' \\033[0;33me \\033[0mserve per enfatizzare l'attuale ramo e a monte con il colore.
  • $(git symbolic-ref -q --short HEAD) è il nome della filiale corrente
  • $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)) è l'upstream del ramo corrente.

Poiché il ripristino è una chiamata potenzialmente pericolosa (specialmente con l'opzione --hard, perderai tutte le modifiche non confermate), prima ti dice cosa sta per fare. Ad esempio, se sei sul ramo dev-container con telecomando chiamato qcpp / dev-container e inserisci git catchup, ti verrà richiesto:

resettare dev-container su qcpp / dev-container? (Y / n)

Se poi digiti y o premi semplicemente Invio, eseguirà il ripristino. Se si inserisce qualcos'altro, il ripristino non verrà eseguito.

Se vuoi essere super sicuro e prevenire a livello di programmazione la perdita di modifiche non messe in scena / non impegnate, puoi sfruttare ulteriormente l'alias di cui sopra con i controlli secondo l'indice diff .

Avvertenza obbligatoria: se stai lavorando su un archivio pubblico su cui altre persone hanno basato il lavoro e hai bisogno di questo alias, lo stai facendo in modo sbagliato ™ .


1

Ho provato questo e non ha ripristinato il mio ramo corrente sul mio github remoto più recente. Ho cercato su Google e ho trovato https://itsyndicate.org/blog/how-to-use-git-force-pull-properly/

quale suggerito

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

Volevo ripristinare il mio ramo v8 così ho fatto

git fetch origin v8
git reset --hard origin/v8

e ha funzionato


Bene, è bello che tu menzioni il recupero. L'ho fatto una volta senza e ho ripristinato tutto a 2 anni fa :)
Adam,
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.