Sommario
Il messaggio di errore
Impossibile "schiacciare" senza un precedente commit
significa che probabilmente hai tentato di "schiacciare verso il basso". Git annulla sempre un nuovo commit in un vecchio commit o "verso l'alto" come visualizzato nell'elenco todo rebase interattivo, ovvero in un commit su una riga precedente. La modifica del comando sulla prima riga dell'elenco di todo squash
produrrà sempre questo errore in quanto non vi è nulla per cui eseguire il primo commit.
La correzione
Per prima cosa torna da dove hai iniziato
$ git rebase --abort
Di 'che la tua storia è
$ git log --pretty=oneline
a931ac7c808e2471b22b5bd20f0cad046b1c5d0d c
b76d157d507e819d7511132bdb5a80dd421d854f b
df239176e1a2ffac927d8b496ea00d5488481db5 a
Cioè, a è stato il primo commit, quindi b e infine c. Dopo aver commesso c decidiamo di schiacciare b e c insieme:
(Nota: eseguendo il git log
pipe il suo output in un cercapersone, less
per impostazione predefinita sulla maggior parte delle piattaforme. Per uscire dal cercapersone e tornare al prompt dei comandi, premere il q
tasto.)
Running git rebase --interactive HEAD~2
ti dà un editor con
pick b76d157 b
pick a931ac7 c
# Rebase df23917..a931ac7 onto df23917
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
(Notare che questo elenco di cose da fare è nell'ordine inverso rispetto all'output di git log
.)
La modifica di b pick
in squash
comporterà l'errore che hai visto, ma se invece schiacci c in b (il più recente impegna nel più vecchio o "schiaccia verso l'alto") cambiando la lista delle cose da fare in
pick b76d157 b
squash a931ac7 c
e salvando il tuo editor, otterrai un altro editor i cui contenuti sono
# This is a combination of 2 commits.
# The first commit's message is:
b
# This is the 2nd commit message:
c
Quando si salva e si chiude, il contenuto del file modificato diventa un messaggio di commit del nuovo commit combinato:
$ git log --pretty=oneline
18fd73d3ce748f2a58d1b566c03dd9dafe0b6b4f b and c
df239176e1a2ffac927d8b496ea00d5488481db5 a
Nota sulla riscrittura della cronologia
Il rebase interattivo riscrive la storia. Il tentativo di spingere su un telecomando che contiene la cronologia precedente non riuscirà perché non è un avanzamento rapido.
Se il ramo che hai rigenerato è un argomento o ramo di una funzione in cui lavori da solo , non è un grosso problema. Il push su un altro repository richiederà l' --force
opzione, o in alternativa potresti essere in grado, a seconda delle autorizzazioni del repository remoto, di eliminare prima il vecchio ramo e poi di inviare la versione ridisegnata. Esempi di quei comandi che potenzialmente distruggeranno il lavoro non rientrano nell'ambito di questa risposta.
Riscrivere la storia già pubblicata su un ramo in cui si sta lavorando con altre persone senza molto buona ragione, come perdite di una password o altri dati sensibili forze di lavoro sui vostri collaboratori ed è antisociale e sarà infastidire altri sviluppatori. La sezione "Recupero da una ripresa a monte" nella git rebase
documentazione spiega, con maggiore enfasi.
Rebasing (o qualsiasi altra forma di riscrittura) su un ramo su cui altri hanno basato il lavoro è una cattiva idea: chiunque a valle di esso è costretto a riparare manualmente la propria cronologia. Questa sezione spiega come eseguire la correzione dal punto di vista del downstream. La vera soluzione, tuttavia, sarebbe quella di evitare di reinserire l'upstream in primo luogo. ...