Espandendo quello che ho scritto in un commento
La regola generale è che non dovresti riscrivere (cambiare) la storia che hai pubblicato, perché qualcuno potrebbe aver basato il proprio lavoro su di esso. Se riscrivi (cambi) la cronologia, avresti problemi con l'unione delle loro modifiche e con l'aggiornamento per esse.
Quindi la soluzione è quella di creare un nuovo commit che ripristini le modifiche che si desidera eliminare. Puoi farlo usando il comando git revert .
Hai la seguente situazione:
A <- B <- C <- D <- master <- HEAD
(le frecce qui si riferiscono alla direzione del puntatore: il riferimento "parent" nel caso di commit, il commit superiore nel caso della testa del ramo (riferimento ramo) e il nome del ramo nel caso del riferimento HEAD).
Quello che devi creare è il seguente:
A <- B <- C <- D <- [(BCD) ^ - 1] <- master <- HEAD
dove "[(BCD) ^ - 1]" indica il commit che ripristina le modifiche nei commit B, C, D. La matematica ci dice che (BCD) ^ - 1 = D ^ -1 C ^ -1 B ^ -1, quindi puoi ottenere la situazione richiesta usando i seguenti comandi:
$ git revert --no-commit D
$ git revert --no-commit C
$ git revert --no-commit B
$ git commit -m "the commit message"
Una soluzione alternativa sarebbe quella di verificare il contenuto del commit A e commettere questo stato:
$ git checkout -f A -- .
$ git commit -a
Quindi avresti la seguente situazione:
A <- B <- C <- D <- A '<- master <- HEAD
Il commit A 'ha gli stessi contenuti del commit A, ma è un commit diverso (messaggio di commit, genitori, data di commit).
La soluzione di Jeff Ferland, modificata da Charles Bailey si basa sulla stessa idea, ma utilizza git reset :
$ git reset --hard A
$ git reset --soft @{1} # (or ORIG_HEAD), which is D
$ git commit
git push -f HEAD~4:master
(supponendo che il ramo remoto sia master). Sì, puoi eseguire qualsiasi commit in questo modo.