Da altre risposte qui, ero un po 'confuso con come git rebase -i
potesse essere usato per rimuovere un commit, quindi spero che sia OK annotare il mio caso di test qui (molto simile al PO).
Ecco uno bash
script che puoi incollare per creare un repository di prova nella /tmp
cartella:
set -x
rm -rf /tmp/myrepo*
cd /tmp
mkdir myrepo_git
cd myrepo_git
git init
git config user.name me
git config user.email me@myself.com
mkdir folder
echo aaaa >> folder/file.txt
git add folder/file.txt
git commit -m "1st git commit"
echo bbbb >> folder/file.txt
git add folder/file.txt
git commit -m "2nd git commit"
echo cccc >> folder/file.txt
git add folder/file.txt
git commit -m "3rd git commit"
echo dddd >> folder/file.txt
git add folder/file.txt
git commit -m "4th git commit"
echo eeee >> folder/file.txt
git add folder/file.txt
git commit -m "5th git commit"
A questo punto, abbiamo un file.txt
con questi contenuti:
aaaa
bbbb
cccc
dddd
eeee
A questo punto, HEAD è al 5 ° commit, HEAD ~ 1 sarebbe il 4 ° e HEAD ~ 4 sarebbe il 1 ° commit (quindi HEAD ~ 5 non esisterebbe). Diciamo che vogliamo rimuovere il 3o commit - possiamo emettere questo comando nella myrepo_git
directory:
git rebase -i HEAD~4
( Si noti che i git rebase -i HEAD~5
risultati con "fatale: necessaria una singola revisione; HEAD upstream non valido ~ 5". ) Un editor di testo (vedi screenshot nella risposta di @Dennis ) si aprirà con questi contenuti:
pick 5978582 2nd git commit
pick 448c212 3rd git commit
pick b50213c 4th git commit
pick a9c8fa1 5th git commit
# Rebase b916e7f..a9c8fa1 onto b916e7f
# ...
Quindi riceviamo tutti i commit dal (ma non incluso ) il nostro HEAD richiesto ~ 4. Elimina la riga pick 448c212 3rd git commit
e salva il file; otterrai questa risposta da git rebase
:
error: could not apply b50213c... 4th git commit
When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".
Could not apply b50213c... 4th git commit
A questo punto apri myrepo_git / folder/file.txt
in un editor di testo; vedrai che è stato modificato:
aaaa
bbbb
<<<<<<< HEAD
=======
cccc
dddd
>>>>>>> b50213c... 4th git commit
Fondamentalmente, git
vede che quando HEAD è arrivato al 2 ° commit, c'era contenuto di aaaa
+ bbbb
; e poi ha una patch di cccc
+ aggiunto dddd
che non sa come aggiungere al contenuto esistente.
Quindi qui git
non puoi decidere per te - sei tu che devi prendere una decisione: rimuovendo il 3o commit, o mantieni le modifiche introdotte da esso (qui, la linea cccc
) - oppure no. Se non lo fai, rimuovi semplicemente le righe extra - incluso il cccc
- folder/file.txt
usando un editor di testo, quindi è così:
aaaa
bbbb
dddd
... e poi salva folder/file.txt
. Ora puoi emettere i seguenti comandi nella myrepo_git
directory:
$ nano folder/file.txt # text editor - edit, save
$ git rebase --continue
folder/file.txt: needs merge
You must edit all merge conflicts and then
mark them as resolved using git add
Ah - così al fine di boa che abbiamo risolto il conflitto, noi dobbiamo git add
la folder/file.txt
, prima di fare git rebase --continue
:
$ git add folder/file.txt
$ git rebase --continue
Qui si apre di nuovo un editor di testo che mostra la riga 4th git commit
: qui abbiamo la possibilità di modificare il messaggio di commit (che in questo caso potrebbe essere significativamente modificato 4th (and removed 3rd) commit
o simile). Diciamo che non vuoi - quindi basta uscire dall'editor di testo senza salvare; una volta fatto, otterrai:
$ git rebase --continue
[detached HEAD b8275fc] 4th git commit
1 file changed, 1 insertion(+)
Successfully rebased and updated refs/heads/master.
A questo punto, ora hai una storia come questa (che potresti anche esaminare con voce gitk .
o altri strumenti) dei contenuti di folder/file.txt
(con, apparentemente, timestamp invariati degli commit originali):
1st git commit | +aaaa
----------------------------------------------
2nd git commit | aaaa
| +bbbb
----------------------------------------------
4th git commit | aaaa
| bbbb
| +dddd
----------------------------------------------
5th git commit | aaaa
| bbbb
| dddd
| +eeee
E se in precedenza, avessimo deciso di mantenere la linea cccc
(i contenuti del terzo commit git che abbiamo rimosso), avremmo avuto:
1st git commit | +aaaa
----------------------------------------------
2nd git commit | aaaa
| +bbbb
----------------------------------------------
4th git commit | aaaa
| bbbb
| +cccc
| +dddd
----------------------------------------------
5th git commit | aaaa
| bbbb
| cccc
| dddd
| +eeee
Bene, questo era il tipo di lettura che speravo di aver trovato, per iniziare a capire come git rebase
funziona in termini di cancellazione di commit / revisioni; quindi spero che possa aiutare anche gli altri ...