So che è una riscrittura della storia che è male yada yada.
Ma come rimuovere permanentemente alcuni commit dalla filiale remota?
So che è una riscrittura della storia che è male yada yada.
Ma come rimuovere permanentemente alcuni commit dalla filiale remota?
Risposte:
Sei il git reset --hard
tuo ramo locale per rimuovere le modifiche dall'albero e dall'indice di lavoro e il git push --force
tuo ramo locale rivisto sul telecomando. ( altra soluzione qui , che consiste nell'eliminare il ramo remoto e reinserirlo)
Questa risposta SO illustra il pericolo di tale comando, soprattutto se le persone dipendono dalla cronologia remota per i propri repository locali.
Devi essere pronto a segnalare alle persone la sezione RECUPERARE DA REVISIONE UPSTREAM della git rebase
pagina man
Con Git 2.23 (agosto 2019, nove anni dopo), useresti il nuovo comando git switch
.
Cioè:
(sostituiscigit switch -C mybranch origin/mybranch~n
n
con il numero di commit da rimuovere)
Ciò ripristinerà l'indice e l'albero di lavoro, come git reset --hard
farebbe.
push --force
via
git gc
non sempre viene eseguito abbastanza spesso sul lato remoto. Ad esempio su GitHub: twitter.com/githubhelp/status/387926738161774592?lang=es
Basta notare di usare il last_working_commit_id
, quando si ripristina un commit non funzionante
git reset --hard <last_working_commit_id>
Quindi non dobbiamo ripristinare commit_id
ciò che non vogliamo.
Quindi certo, dobbiamo spingere al ramo remoto:
git push --force
git reset --hard
dovrebbe fare.
Ci sono tre opzioni mostrate in questo tutorial . In caso di interruzione del collegamento, lascerò qui i passaggi principali.
1 Ripristina il commit completo
git revert dd61ab23
2 Elimina l'ultimo commit
git push <<remote>> +dd61ab23^:<<BRANCH_NAME_HERE>>
oppure, se il ramo è disponibile localmente
git reset HEAD^ --hard
git push <<remote>> -f
dove + dd61 ... è il tuo hash di commit e git interpreta x ^ come il genitore di x, e + come una spinta forzata non anticipata.
3 Elimina il commit da un elenco
git rebase -i dd61ab23^
Questo si aprirà e l'editor mostrerà un elenco di tutti i commit. Elimina quello a cui vuoi sbarazzarti. Termina il rebase e spingi la forza verso il repo.
git rebase --continue
git push <remote_repo> <remote_branch> -f
Se si desidera eliminare, ad esempio, gli ultimi 3
commit, eseguire il comando seguente per rimuovere le modifiche dal file system (albero di lavoro) e commettere la cronologia (indice) sul ramo locale:
git reset --hard HEAD~3
Quindi eseguire il comando seguente (sul computer locale) per forzare il ramo remoto a riscrivere la sua cronologia:
git push --force
Congratulazioni! Tutto fatto!
Alcune note:
È possibile recuperare l'id di commit desiderato eseguendo
git log
Quindi è possibile sostituire HEAD~N
con in <desired-commit-id>
questo modo:
git reset --hard <desired-commit-id>
Se si desidera mantenere le modifiche sul file system e modificare solo l'indice (cronologia commit), utilizzare --soft
flag like git reset --soft HEAD~3
. Quindi hai la possibilità di controllare le ultime modifiche e conservarle o eliminarle tutte o parte di esse. In quest'ultimo caso runnig git status
mostra i file modificati da allora <desired-commit-id>
. Se usi l' --hard
opzione, git status
ti dirà che la tua filiale locale è esattamente la stessa di quella remota. Se non si utilizza --hard
né --soft
, viene utilizzata la modalità predefinita --mixed
. In questa modalità, git help reset
dice:
Reimposta l'indice ma non l'albero di lavoro (ovvero, i file modificati vengono conservati ma non contrassegnati per il commit) e riporta ciò che non è stato aggiornato.
Potrebbe essere troppo tardi, ma ciò che mi ha aiutato è l'opzione "nucleare" che suona bene. Fondamentalmente usando il comandofilter-branch
è possibile rimuovere i file o modificare qualcosa su un gran numero di file in tutta la cronologia di Git.
È meglio spiegato qui .
Semplificazione dalla risposta di pctroll, analogamente sulla base di questo post sul blog .
# look up the commit id in git log or on github, e.g. 42480f3, then do
git checkout master
git checkout your_branch
git revert 42480f3
# a text editor will open, close it with ctrl+x (editor dependent)
git push origin your_branch
# or replace origin with your remote
A volte il modo più semplice per risolvere questo problema è creare un nuovo ramo dal punto in cui sai che il codice è buono. Quindi puoi lasciare da solo la cronologia del ramo errato nel caso in cui tu debba selezionare altri commit da esso in seguito. Questo assicura anche che non hai perso alcuna cronologia di commit.
Dal tuo ramo locale errante:
git log
copia l'hash di commit in cui vuoi che si trovasse il ramo ed esci dal registro git
git checkout theHashYouJustCopied
git checkout -b your_new_awesome_branch
Ora hai una nuova filiale nel modo che preferisci.
Se hai anche bisogno di mantenere un commit specifico dal ramo errato che non si trova sul tuo nuovo ramo, puoi semplicemente selezionare quel commit specifico di cui hai bisogno:
git checkout the_errant_branch
git log
Copia l'hash di commit di un commit che devi inserire nel buon ramo ed uscire dal registro git.
git checkout your_new_awesome_branch
git cherry-pick theHashYouJustCopied
Datti una pacca sulla schiena.