Aggiungi la modifica a un commit precedente con Magit


44

Ho 2 commit, A quindi B, pronto per essere spinto. Mi rendo conto di aver dimenticato di aggiungere qualcosa in A.

Come posso aggiungere questa modifica ad A usando Magit? Non so nemmeno quale parte della documentazione di Git dovrei guardare.

Risposte:


69

Facciamo finta per un momento di voler aggiungere qualcosa al HEADcommit, ovvero "il secondo commit B" nel tuo esempio.

Il popup di commit su cpresenta un " aAmend" vincolante . La pressione di quel tasto "modifica" le modifiche temporanee al HEADcommit. Poiché i commit non sono modificabili in Git, questo sostituirà effettivamente il vecchio commit con un nuovo commit. Verrà visualizzato un buffer con il vecchio messaggio di commit, in modo da poterlo modificare nel caso in cui la modifica aggiunta richieda anche la modifica del messaggio. Come sempre, premere C-c C-cal termine della modifica del messaggio. Ciò equivale all'esecuzione git commit --amendsulla riga di comando.

  • a Modifica : HEADconsente di aggiungere le modifiche graduali e di modificarne il messaggio di commit

Poiché spesso accade che devi solo modificare la modifica o il messaggio, Magit offre due varianti aggiuntive:

  • e Estendi : consente di aggiungere le modifiche gestite HEADsenza modificare il messaggio di commit
  • w Reword : modifica il messaggio HEADsenza aggiungervi le modifiche temporanee

Quando si desidera modificare un commit che non lo è HEAD, allora quanto sopra non funzionerà. Questi comandi "modificano" sempre (ovvero sostituiscono) il HEADcommit. Git non fornisce un singolo comando per modificare un commit diverso da quello, HEADquindi questo è un po 'più coinvolto.

Magit vuol fornire un tale comando, ma perché ci sono situazioni in cui è preferibile farlo in più passaggi, si discuterà quella prima.

La modifica di un commit diverso da HEADpuò essere suddivisa in tre passaggi:

  1. Fai temporaneamente questo altro commit ( A) il HEAD.
  2. Modificare il HEAD(come descritto sopra), con conseguente commit A'.
  3. Di 'a Git di riapplicare gli commit che sono seguiti A, ma per di più A'.

Questo può essere fatto usando un rebase interattivo. Digitare rper mostrare il popup rebase. Quindi digitare mper richiamare la variante rebase "modifica un commit". Viene visualizzato un buffer con commit recenti. Passa al commit che desideri modificare e digita C-c C-cper selezionarlo. Git quindi riavvolge la cronologia a quel commit e mostra le informazioni sul rebase in corso nel buffer di stato.

Modificare HEADcome descritto sopra. Quindi dì a Git che hai finito digitando r r. Se A'e Bconflitto allora rebase si fermerà a Be devi risolvere il conflitto. Al termine, premere r rper continuare.

Se sai che le tue modifiche Aporteranno a conflitti con B, procedi come descritto sopra, altrimenti usa il seguente approccio.


Git consente di creare "commit di correzione" usando git commit --fixup A. Ciò crea un nuovo commit, che registra le modifiche che "avrebbero dovuto essere apportate in un altro commit". Quel commit diventa il nuovo HEAD. Esiste anche una --squashvariante. Per informazioni sulle differenze, consultare la git-commitpagina man.

Per combinare effettivamente il Acommit e il nuovo commit A'e quindi riapplicarlo B, devi usare rebase. Magit fornisce un comodo comando per farlo r f.

La principale differenza rispetto all'approccio di cui sopra è che qui creiamo prima un nuovo commit e poi ci riordiniamo per combinarlo con il "target" e riapplicare B. Sopra abbiamo iniziato con il rifacimento invece di impegnarci.

Nel Magit sia la --fixupe le --squashvarianti sono disponibili presso il commit a comparsa, su fe s. Ma Magit fornisce anche varianti "istantanee" dei comandi fixup e squash su Fe S. Queste varianti creano un nuovo commit come le varianti "non istantanee", ma poi combinano istantaneamente il commit fixup con il commit target usando rebase, senza che tu debba invocare un altro comando.

"Instant fixup" ( c F) è essenzialmente la stessa cosa di "extension HEAD" ( c e), tranne per il fatto che funziona per qualsiasi commit, non solo HEAD.


Ulteriori letture:


Cristallino! Grazie, fantastico pacchetto BTW.
Mathieu Marques,

1
Bene, penso che ci siano alcune parti molli nella seconda metà della mia risposta. Ma per evitare quelli dovrei raddoppiare la lunghezza di questa già lunga risposta, quindi sono contento che questo
funzioni

Grazie per questa risposta tarsius, questo funziona davvero per me.
anquegi,

La chiarezza della prima metà di questa spiegazione rende frustrante leggere la seconda metà, che è molto più difficile da seguire!
Lyn Headley,

git-commitla pagina man reindirizza a git-rebase(1)chi ha queste righe: Il messaggio di commit suggerito per il commit piegato è la concatenazione dei messaggi di commit del primo commit e di quelli con il comando "squash", ma omette i messaggi di commit di commit con il "fixup" comando. IOW, usa fixup se vuoi solo correggere il codice nel commit precedente, usa squash se vuoi anche correggere il messaggio di commit.
Yasushi Shoji,

3

git commit --amend –C HEADè il comando Git che vuoi cercare e con Magit puoi fare ammenda C-c C-a.


Sto usando Magit più recente, C-c C-aè di una versione precedente (penso). Inoltre, non vedo traccia di "modifica" nel buffer della guida ( ?).
Mathieu Marques,

Vedi la risposta di Rémi per l'equivalente di magit 2.x.
npostavs,

3

Quindi un flusso di lavoro è:

  • fai il tuo cambiamento
  • c (commit) f (fixup - seleziona commit il tuo fix)

Poi

  • r (rebase) -a (autosquash, può essere predefinito) i (interattivo)

L'autosquash sposta automaticamente tutto! Fixup si impegna nel posto giusto e li imposta per essere schiacciati sulla base.


L'unica cosa che ho fatto che non hai detto è stata quella di metterti in scena tra il tuo primo proiettile e il secondo. Colpire imi dà Cannot rebase: Your index contains uncommitted changes. Please commit or stash them.. Tranne il fatto che non ho alcuna modifica non impegnata. : /
Mathieu Marques,

Ho provato di nuovo dopo aver tirato, Proceed despite merge in rebase range? [c]ontinue, [s]elect other, [a]bort. Sta cercando di dirmi che il mio fixup potrebbe fare la cacca sulla prossima fusione?
Mathieu Marques,

@MathieuMarques: "Tranne per il fatto che non ho cambiamenti senza commit" - git pensa che tu lo faccia. Nota che il messaggio suggerisce modifiche graduali, non non graduali. Ri merge in rebase:, vedi BUGS sotto git help rebase. Suggerisco di fare il fixup prima di tirare a monte.
npostavs,

1

Per ottenere l'ultimo commit, è "c a". La correzione è per l'ammissione di alcuni commit più vecchi.


Qual è il caso, ho commesso A e poi B. Post aggiornato per chiarezza.
Mathieu Marques,
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.