Come modificare il commit passato per includere un file mancato?


98

Ho eseguito il commit di una modifica e ho dimenticato di aggiungere un file alla serie di modifiche. Dopo altri commit, mi sono reso conto che il file ora manca da un HEAD^4commit.

Come faccio a riscrivere un commit precedente per includere il file mancante?


hai spinto questi 4 commit?
mvp

@mvp no, sono solo nel mio repository git locale.
kolrie

Risposte:


53

Usa git rebase --interactive HEAD~4e imposta l' editopzione per il commit che desideri modificare.

Ricorda che non dovresti modificare i commit inviati al repository remoto in questo modo. In questo caso è meglio aggiungere un nuovo commit con file mancante.


Grazie. È così anche se sono l'unico utente del repository remoto? Non mi permetterebbe di farlo git push -fse sono sicuro che l'upstream non è cambiato?
kolrie

1
Se sei l'unico utente del repository remoto, puoi eseguire il push forzato.
Rafał Rawicki

7
Penso che queste istruzioni non siano abbastanza dettagliate. Dopo averlo provato la prima volta mi è stato detto "Impossibile rebase: il tuo indice contiene modifiche non salvate". Avevo già addeliminato i file mancanti, quindi ho eseguito un commit con "xxx" come messaggio. Poi ho eseguito il comando rebase e ho cambiato il commit "xxx" da "pick" a "edit". Poi ho fatto "git rebase --continue". Ora, quando guardo la cronologia, ho "xxx" come ultimo commit e il commit precedente a cui volevo aggiungerli è invariato! Mi chiedo dove sia stato il mio errore?
Darren Cook,

2
Schiacciare l'ultimo commit non metterà il file in HEAD ~ 4.
Justin

1
git add editedFiles; git commit -m "Blah"; git rebase -i HEAD ~ 5; // poiché ora è stato aggiunto un nuovo commit, quindi dovevamo rebase con 5 invece di 4. ora sposta il commit "Blah" sulla seconda riga e cambialo da "Pick" a "s" (squash) che schiaccerà il commit con HEAD ~ 5 poiché i comandi vengono eseguiti dall'alto verso il basso
zstring

274

Mi rendo conto che le persone possono cercare su Google e venire qui per trovare una risposta più semplice: e se fosse solo l'ultimo commit? (La domanda di OP è per correggere il quarto commit nella storia)

Nel caso in cui ti impegni e ti rendi conto di aver dimenticato di aggiungere immediatamente un file , fai semplicemente:

# edited file-that-i-remember.txt
git add file-that-i-remember.txt
git commit

# realize you forgot a file
git add file-that-i-forgot.txt
git commit --amend --no-edit

Where --no-editmanterrà lo stesso messaggio di commit.

Vai tranquillo!


21
Questa è la risposta.
Adam Bittlingmayer

5
Vale la pena menzionare, se i commit non vengono inviati al telecomando.
Ram Patra

1
Sì, vale la pena menzionarlo qui nei commenti: è da utilizzare prima del push . Grazie per averlo indicato.
Dr Beco

2
Un avviso è che i commit prima e dopo --amendhanno hash diversi
sonlexqt

5
Grazie, ma non può essere: OP richiesto HEAD^4. Va bene così com'è, solo come addendum per riferimento. ;)
Dr Beco

11

Se NON hai spinto questi 4 commit, puoi farlo come segue:

Crea file patch per tutti questi commit:

git format-patch -4

Riavvolgi indietro di 4 commit:

git reset --hard HEAD~4

Aggiungi file mancante:

git add missing-file

Impegnalo con --amend:

git commit --amend

Riapplica tutte le patch salvate:

git am *.patch

Se hai spinto, NON dovresti usare questo metodo. Invece, ammetti il ​​tuo errore e crea un altro commit sopra HEAD che risolve questo problema.


Se vuoi fare questo passo dopo passo è più facile selezionare i commit dopo quello modificato, piuttosto che esportarli come una patch.
Rafał Rawicki

1
Questa è una questione di gusti. Mi piace git format-patch/ git ammolto meglio. Soprattutto ti dà più sicurezza se sbagli qualcosa: il commit salvato come patch in un file fisico è la tua migliore rete di sicurezza.
mvp

La vera fiducia sta infatti nel fatto che quando si opera su un repository git non si rimuove mai nulla. I vecchi commit sono disponibili fino a quando non corri git gc:)
Rafał Rawicki

Questo è banale e ovvio per te e per me. Ma per l'utente che ha appena iniziato e probabilmente non capisce nulla di git, questo fatto non è affatto ovvio.
mvp

2
Queste istruzioni sembravano prolisse, ma erano abbastanza semplici e facili da seguire. Grazie. (Avevo solo aggiungere un ultimo passo: rm *.patch)
Darren Cook

9

Sebbene la risposta accettata sia corretta, manca di istruzioni dettagliate su come eseguire la modifica di un commit durante un processo di rebase.

  • Innanzitutto, avvia un processo di rebase:

    git rebase --interactive HEAD~4
    
  • Sarà presentato un elenco di commit, scegliere un commit che si desidera modificare, cambiando la parola pickper edite salvare il file.

  • Apporta le modifiche necessarie nel tuo codice (ricorda di invocare git addnuovi file)

  • Dopo che tutte le modifiche sono state apportate, emetti git commit --amend: questo modificherà un commit contrassegnato comeedit

  • Invoca git rebase --continueche finirà il processo (se ci sono più commit contrassegnati come edit, i passaggi precedenti devono essere ripetuti)

Note importanti:

  • NON rimuovere le righe contrassegnate come pickche non desideri modificare: lasciale così come sono. L'eliminazione di queste righe comporterà l'eliminazione dei commit correlati

  • GIT ti obbliga a stashprima di ribasare se la tua directory di lavoro non è pulita; puoi comunque git stash pop / git stash applydurante il rebase, al fine di modificare queste modifiche (cioè le modifiche nascoste prima di iniziare il processo di rebase) in un commit contrassegnato comeedit

  • se qualcosa è andato storto e vuoi annullare le modifiche fatte durante il processo di rebase prima che finisse (cioè vuoi tornare al punto prima di iniziare il rebase), usa git rebase --abort- leggi anche: How to abort an interactive rebase if --abort doesn ' non funziona?

  • Come detto nella risposta accettata:

    Ricorda che non dovresti modificare i commit inviati al repository remoto in questo modo. In questo caso è meglio aggiungere un nuovo commit con file mancante.

    La risposta è nel Git Book (paragrafo intitolato " The Perils of Rebasing "):

    Non ribasare commit che esistono al di fuori del tuo repository.

    Se segui questa linea guida, starai bene. Se non lo fai, le persone ti odieranno e sarai disprezzato da amici e familiari.

    Quando ribasate le cose, abbandonate i commit esistenti e ne create di nuovi simili ma diversi. Se sposti i commit da qualche parte e altri li tirano giù e ci basano il lavoro, e poi li riscrivi con git rebase e li sposti di nuovo, i tuoi collaboratori dovranno unire nuovamente il loro lavoro e le cose si complicheranno quando proverai a ritira il loro lavoro nel tuo.

    [...]

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.