Domanda

Qualcuno sa come facilmente annullare un git rebase?

L'unico modo che mi viene in mente è di andare a manualmente:

  • git checkout il commit padre di entrambi i rami
  • quindi creare una temp ramo da lì
  • cherry-pick tutte impegna a mano
  • sostituire il ramo in cui ho ricalcolato il creato manualmente ramo

Nella mia situazione attuale, questo sta andando a lavorare, perché può macchiare facilmente si impegna da entrambi i rami (uno era la mia roba, l'altro era il mio collega di roba).

Tuttavia il mio approccio mi sembra ottimale e inclini all'errore (diciamo che avevo appena riassegnata con 2 dei miei rami).

Tutte le idee?

Chiarimento:Sto parlando di un rebase durante il quale un gruppo di commit sono stati riprodotti.Non solo uno.

È stato utile?

Soluzione

Il modo più semplice sarebbe quello di trovare la testa di commit della succursale, come è stato subito prima che il rebase iniziato nel reflog...

git reflog

e per ripristinare la corrente del ramo (con i soliti essere assolutamente certi che prima del ripristino con il --hard opzione).

Supponiamo che il vecchio commit HEAD@{5} in rif log:

git reset --hard HEAD@{5}

In Windows, potrebbe essere necessario citare il riferimento:

git reset --hard "HEAD@{5}"

È possibile controllare la cronologia del candidato vecchia testa da solo facendo un git log HEAD@{5} (Windows: git log "HEAD@{5}").

Se non hai disabilitato per filiale reflogs si dovrebbe essere in grado di fare semplicemente git reflog branchname@{1} come un rebase si stacca il ramo testa prima di riattaccare il finale di testa.Vorrei ricontrollare questo, anche se, come non ho verificato recentemente.

Per impostazione predefinita, tutti reflogs sono attivati per i non-nudo repository:

[core]
    logAllRefUpdates = true

Altri suggerimenti

In realtà, rebase salva il tuo punto di partenza per ORIG_HEAD quindi, questo è di solito molto semplice:

git reset --hard ORIG_HEAD

Tuttavia, l' reset, rebase e merge tutto salva originale HEAD puntatore ORIG_HEAD quindi, se hai fatto qualsiasi di questi comandi, dato il valore che si sta cercando di annullare quindi dovrete usare il reflog.

La risposta di Charles funziona, ma potresti voler fare questo:

git rebase --abort

per ripulire dopo il reset.

Altrimenti, potresti ricevere il messaggio & # 8220; Interactive rebase already started & # 8221 ;.

git reflog ti mostrerà tutte le modifiche prima e dopo il rebase e ti consentirà di trovare quella giusta su cui reimpostare. Ma sono sorpreso che nessuno abbia menzionato questo altro modo semplicissimo qui:

Rebase lascia il vecchio stato come ORIG_HEAD, quindi puoi ripristinare l'ultimo rebase eseguendo:

git reset --hard ORIG_HEAD

Il ripristino del ramo sull'oggetto commit in sospensione del suo vecchio suggerimento è ovviamente la soluzione migliore, poiché ripristina lo stato precedente senza spendere alcuno sforzo. Ma se ti capita di aver perso quei commit (es. Perché nel frattempo hai raccolto il tuo repository, o questo è un nuovo clone), puoi sempre rifare nuovamente il ramo. La chiave di ciò è l'opzione --onto.

Supponiamo che & # 8217; s abbia avuto un ramo di argomento chiamato in modo fantasioso topic, che si è ramificato master quando la punta di 0deadbeef era il git rebase master commit. Ad un certo punto, mentre sei sul ramo <=>, hai fatto <=>. Ora vuoi annullare questo. Qui & # 8217; s come:

git rebase --onto 0deadbeef master topic

Questo richiederà tutti i commit su <=> che non sono & # 8217; t su <=> e li riprodurrà sopra <=>.

Con <=>, puoi riorganizzare la tua storia praticamente in qualsiasi forma .

Divertiti. : -)

In realtà ho messo un tag di backup sul ramo prima di fare qualsiasi operazione non banale (la maggior parte dei rebase sono banali, ma lo farei se sembra ovunque complesso).

Quindi, ripristinare è facile come git reset --hard BACKUP.

Nel caso in cui hai spostato il tuo ramo nel repository remoto (di solito è di origine) e poi hai effettuato un rebase riuscito (senza unione) (git rebase --abort dà " Nessun rebase in corso ") puoi facilmente ripristinare il ramo utilizzando comando:

  

git reset --hard origin / {branchName}

Esempio:

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is ahead of 'origin/{branchName}' by 135 commits.
  (use "git push" to publish your local commits)

nothing to commit, working directory clean

$ ~/work/projects/{ProjectName} $ git reset --hard origin/{branchName}
HEAD is now at 6df5719 "Commit message".

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is up-to-date with 'origin/{branchName}.

nothing to commit, working directory clean

Nel caso in cui non abbiate completato il rebase e nel mezzo di esso, i seguenti lavori:

git rebase --abort

L'uso di reflog non ha funzionato per me.

Ciò che ha funzionato per me è stato simile a quello descritto qui . Apri il file in .git / logs / refs che prende il nome dal ramo che è stato riformulato e trova la riga che contiene & Quot; rebase finsihed & Quot ;, qualcosa del tipo:

5fce6b51 88552c8f Kris Leech <me@example.com> 1329744625 +0000  rebase finished: refs/heads/integrate onto 9e460878

Verifica il secondo commit elencato sulla riga.

git checkout 88552c8f

Una volta confermato, ciò conteneva le mie modifiche perse, mi sono ramificato e ho emesso un sospiro di sollievo.

git log
git checkout -b lost_changes

Per più commit, ricorda che qualsiasi commit fa riferimento a tutta la cronologia che porta a quel commit. Quindi, nella risposta di Charles, leggi & Quot; il vecchio commit & Quot; come " l'ultimo dei vecchi commette " ;. Se si reimposta su quel commit, riapparirà tutta la cronologia che porta a quel commit. Questo dovrebbe fare quello che vuoi.

Seguendo la soluzione di @Allan e @Zearin, vorrei poter semplicemente fare un commento, ma non ho abbastanza reputazione, quindi ho usato il seguente comando:

Invece di fare git rebase -i --abort (nota il -i ) dovevo semplicemente fare git rebase --abort ( senza il -i ) .

L'uso simultaneo di -i e --abort fa sì che Git mi mostri un elenco di utilizzo / opzioni.

Quindi il mio stato di filiale precedente e attuale con questa soluzione è:

matbhz@myPc /my/project/environment (branch-123|REBASE-i)
$ git rebase --abort

matbhz@myPc /my/project/environment (branch-123)
$

Se hai eseguito correttamente la reimpostazione contro la diramazione remota e non puoi git rebase --abort puoi comunque fare alcuni trucchi per salvare il tuo lavoro e non avere spinte forzate. Supponiamo che il tuo ramo attuale che è stato riformulato per errore sia chiamato your-branch e stia monitorando origin/your-branch

  • git branch -m your-branch-rebased # rinomina ramo corrente
  • git checkout origin/your-branch # checkout all'ultimo stato noto per essere noto
  • git checkout -b your-branch
  • seleziona git log your-branch-rebased, confronta con git log your-branch e definisci i commit mancanti da git cherry-pick COMMIT_HASH
  • your-branch-rebased per ogni commit in remote/your-branch
  • invia le tue modifiche. Tieni presente che due filiali locali sono associate a <=> e devi inviare solo <=>

Diciamo che rinnovo il master nel mio ramo di funzionalità e ricevo 30 nuovi commit che interrompono qualcosa. Ho scoperto che spesso è più semplice rimuovere solo i cattivi commit.

git rebase -i HEAD~31

Reimpostazione interattiva per gli ultimi 31 commit (non fa male se ne scegli troppi).

Prendi semplicemente i commit di cui vuoi sbarazzarti e contrassegnali con " d " invece di " scegli " ;. Ora i commit vengono eliminati in modo efficace annullando il rebase (se rimuovi solo i commit che hai appena ottenuto durante il rebasing).

Se sei su un ramo puoi usare:

git reset --hard @{1}

Non esiste solo un registro di riferimento per HEAD (ottenuto da git reflog), ma ci sono anche reflog per ogni ramo (ottenuto da git reflog <branch>). Quindi, se sei su master, git reflog master elencherà tutte le modifiche a quel ramo. Puoi fare riferimento a tali modifiche con master@{1}, master@{2}, ecc.

git rebase di solito cambia HEAD più volte ma il ramo corrente viene aggiornato una sola volta.

@{1} è semplicemente un scorciatoia per il ramo corrente , quindi è uguale a git reset --hard ORIG_HEAD se sei su git reset.

rebase non funzionerà se hai usato <=> durante un <=> interattivo.

Per i neofiti / chiunque abbia troppa paura di eseguire un hard reset, è possibile effettuare il checkout del commit dal reflog, quindi salvarlo come nuovo branch.

git reflog

Trova il commit appena prima di iniziare la rebasing. Potrebbe essere necessario scorrere ulteriormente verso il basso per trovarlo (premere Invio o PageDown). Prendi nota del numero HEAD e sostituisci 57:

git checkout HEAD@{57}

Rivedi il ramo / commit, se sembra buono crea un nuovo ramo usando questo HEAD:

git checkout -b new_branch_name

git reset --hard origin / {branchName}

è la soluzione corretta per ripristinare tutte le modifiche locali apportate da rebase.

Quello che faccio di solito è git reset #commit_hash

all'ultimo commit in cui penso che rebase non abbia avuto alcun effetto.

quindi git pull

Ora il tuo ramo dovrebbe corrispondere esattamente come i commit master e rebased non dovrebbero esserci.

Ora si può semplicemente scegliere i commit su questo ramo.

Se sbagli qualcosa all'interno di un git rebase, ad es. git rebase --abort, sebbene siano presenti file non impegnati, questi andranno persi e git reflog non saranno di aiuto. Questo è successo a me e dovrai pensare fuori dagli schemi qui. Se sei fortunato come me e usi IntelliJ Webstorm, puoi right-click->local history e tornare a uno stato precedente di file / cartelle, indipendentemente dagli errori che hai fatto con il software di controllo delle versioni. È sempre bene avere un altro fail-safe in esecuzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top