Come rimuovere le voci del registro di commit selezionate da un repository Git mantenendo le loro modifiche?

Vorrei rimuovere le voci del registro di commit selezionate da un albero di commit lineare, in modo che le voci non vengano visualizzate nel registro di commit.

Il mio albero di commit assomiglia a qualcosa:

R--A--B--C--D--E--HEAD 

Vorrei rimuovere le voci B e C in modo che non vengano visualizzate nel registro di commit, ma le modifiche da A a D devono essere mantenute. Forse introducendo un singolo commit, in modo che B e C diventino BC e l’albero assomigli.

 R--A--BC--D--E--HEAD 

O, idealmente, dopo A arriva direttamente D. D ‘che rappresenta i cambiamenti da A a B, da B a C e da C a D.

 R--A--D'--E--HEAD 

È ansible? se sì, come?

Questo è un progetto abbastanza nuovo, quindi non ha più filiali a partire da ora, quindi nessuna fusione.

git-rebase (1) fa esattamente questo.

 $ git rebase -i HEAD~5 

git awsome-ness [git rebase –interactive] contiene un esempio.

  1. Non utilizzare git-rebase su commit pubblici (remoti).
  2. Assicurati che la tua directory di lavoro sia pulita ( stash il commit o stash le modifiche correnti).
  3. Esegui il comando precedente. Lancia il tuo $EDITOR .
  4. Sostituisci la pick prima di C e D con lo squash . Combinerà C e D in B. Se vuoi eliminare un commit, cancella semplicemente la sua linea.

Se ti sei perso, digita:

 $ git rebase --abort 
 # detach head and move to D commit git checkout  # move HEAD to A, but leave the index and working tree as for D git reset --soft  # Redo the D commit re-using the commit message, but now on top of A git commit -C  # Re-apply everything from the old D onwards onto this new place git rebase --onto HEAD  master 

Ecco un modo per rimuovere uno specifico ID commit conoscendo solo l’ID commit che vorresti rimuovere.

 git rebase --onto commit-id^ commit-id 

Si noti che questo rimuove effettivamente la modifica introdotta dal commit.

Per espandere la risposta di JF Sebastian:

È ansible utilizzare git-rebase per apportare facilmente tutti i tipi di modifiche alla cronologia dei commit.

Dopo aver eseguito git rebase –interactive ottieni quanto segue nel tuo $ EDITOR:

 pick 366eca1 This has a huge file pick d975b30 delete foo pick 121802a delete bar # Rebase 57d0b28..121802a onto 57d0b28 # # 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 

Puoi spostare le linee per cambiare l’ordine dei commit e cancellare le linee per rimuovere quel commit. Oppure puoi aggiungere un comando per combinare (squash) due commit in un singolo commit (il commit precedente è il commit precedente), edit commit (cosa è stato modificato) o reword commit messages.

Penso che scegliere significa semplicemente che vuoi lasciare che commetta da solo.

(Esempio è da qui )

Puoi rimuovere B e C in modo non interattivo nel tuo esempio con:

 git rebase --onto HEAD~5 HEAD~3 HEAD 

o simbolicamente,

 git rebase --onto AC HEAD 

Si noti che le modifiche in B e C non saranno in D; loro saranno andati

Trovo che questo processo sia molto più sicuro e più facile da capire creando un altro ramo da SHA1 di A e selezionando con certezza i cambiamenti desiderati, così posso assicurarmi di essere soddisfatto di come appare questo nuovo ramo. Dopodiché, è facile rimuovere il vecchio ramo e rinominare quello nuovo.

 git checkout  git log #verify looks good git checkout -b rework git cherry-pick  .... git log #verify looks good git branch -D  git branch -m rework  

Un altro modo,

 git rebase -i ad0389efc1a79b1f9c4dd6061dca6edc1d5bb78a (C's hash) and git push origin master -f 

scegli l’hash che vuoi usare come base, e il comando sopra dovrebbe renderlo interattivo in modo da poter schiacciare tutti i messaggi migliori (devi lasciare il più vecchio)

Ho appena raccolto tutte le risposte delle persone: (m nuovo a git plz usarlo solo come riferimento)

git rebase per cancellare qualsiasi commit

log git

 -first check from which commit you want to rebase 

git rebase -i HEAD ~ 1

 -Here i want to rebase on the second last commit- commit count starts from '1') -this will open the command line editor (called vim editor i guess) 

Quindi lo schermo sarà simile a questo:

scegli 0c2236d Aggiunta nuova riga.

Rebase 2a1cd65..0c2236d su 2a1cd65 (1 comando)

#

comandi:

p, pick = usa commit

r, reword = usa commit, ma modifica il messaggio di commit

e, edit = usa commit, ma smetti di modificare

s, squash = usa commit, ma combina in commit precedente

f, fixup = come “squash”, ma scarta questo messaggio di log del commit

x, exec = esegui il comando (il resto della riga) usando la shell

d, drop = rimuovi commit

#

Queste righe possono essere riordinate; sono eseguiti dall’alto verso il basso.

#

Se rimuovi una riga qui CHE COMMITERA SARÀ PERDUTA.

#

Tuttavia, se rimuovi tutto, il rebase verrà annullato.

#

Nota che i commit vuoti sono commentati ~ ~

~
~
~
~
~
~
~
~
~

Qui cambia la prima riga secondo le tue necessità (usando i comandi sopra elencati, ad es. “Rilascia” per rimuovere commit ecc.) Una volta fatto, modifica “: x” per salvare ed uscire dall’editor (questo è solo per l’editor di vim)

E poi

spingere

Se il problema è evidente, è necessario forzare le modifiche a remoto (ITS MOLTO CRITICO: non forzare il push se si lavora in team)

git push -f origin

Puoi usare git cherry-pick per questo. ‘cherry-pick’ applicherà un commit sul ramo il tuo ora.

Quindi fa

 git rebase --hard  

quindi applicare i comandi D ed E.

 git cherry-pick  git cherry-pick  

Questo salterà il commit B e C. Detto questo, potrebbe essere imansible applicare il commit D al ramo senza B, quindi YMMV.