De otras respuestas aquí, estaba un poco confundido con cómo git rebase -i
podría usarse para eliminar una confirmación, así que espero que esté bien anotar mi caso de prueba aquí (muy similar al OP).
Aquí hay un bash
script que puede pegar para crear un repositorio de prueba en la /tmp
carpeta:
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"
En este punto, tenemos una file.txt
con estos contenidos:
aaaa
bbbb
cccc
dddd
eeee
En este punto, HEAD está en la 5ª confirmación, HEAD ~ 1 sería la 4ª y HEAD ~ 4 sería la primera confirmación (por lo que HEAD ~ 5 no existiría). Digamos que queremos eliminar la tercera confirmación: podemos emitir este comando en el myrepo_git
directorio:
git rebase -i HEAD~4
( Tenga en cuenta que los git rebase -i HEAD~5
resultados con "fatal: se necesitaba una única revisión; HEAD ~ 5" no válido. ) Se abrirá un editor de texto (ver captura de pantalla en la respuesta de @Dennis ) con estos contenidos:
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
# ...
Entonces obtenemos todos los commits desde (pero sin incluir ) nuestro HEAD ~ 4 solicitado. Elimine la línea pick 448c212 3rd git commit
y guarde el archivo; obtendrá esta respuesta de 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
En este punto, abra myrepo_git / folder/file.txt
en un editor de texto; verá que ha sido modificado:
aaaa
bbbb
<<<<<<< HEAD
=======
cccc
dddd
>>>>>>> b50213c... 4th git commit
Básicamente, git
ve que cuando HEAD llegó a la segunda confirmación, había contenido de aaaa
+ bbbb
; y luego tiene un parche de cccc
+ agregado dddd
que no sabe cómo agregar al contenido existente.
Entonces, aquí git
no puede decidir por usted, es usted quien tiene que tomar una decisión: al eliminar la tercera confirmación, mantiene los cambios introducidos por ella (aquí, la línea cccc
), o no lo hace. Si no lo hace, simplemente elimine las líneas adicionales, incluida la cccc
, folder/file.txt
usando un editor de texto, para que se vea así:
aaaa
bbbb
dddd
... y luego guardar folder/file.txt
. Ahora puede emitir los siguientes comandos en el myrepo_git
directorio:
$ 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, entonces para marcar que hemos resuelto el conflicto, debemos hacer git add
lo siguiente folder/file.txt
antes de hacer git rebase --continue
:
$ git add folder/file.txt
$ git rebase --continue
Aquí se abre nuevamente un editor de texto, que muestra la línea 4th git commit
; aquí tenemos la oportunidad de cambiar el mensaje de confirmación (que en este caso podría cambiarse significativamente 4th (and removed 3rd) commit
o similar). Digamos que no quiere, así que salga del editor de texto sin guardar; una vez que hagas eso, obtendrás:
$ git rebase --continue
[detached HEAD b8275fc] 4th git commit
1 file changed, 1 insertion(+)
Successfully rebased and updated refs/heads/master.
En este punto, ahora tiene un historial como este (que también podría inspeccionar con say gitk .
u otras herramientas) del contenido de folder/file.txt
(con, aparentemente, marcas de tiempo sin cambios de los commits originales):
1st git commit | +aaaa
----------------------------------------------
2nd git commit | aaaa
| +bbbb
----------------------------------------------
4th git commit | aaaa
| bbbb
| +dddd
----------------------------------------------
5th git commit | aaaa
| bbbb
| dddd
| +eeee
Y si anteriormente, decidimos mantener la línea cccc
(el contenido del tercer git commit que eliminamos), habríamos tenido:
1st git commit | +aaaa
----------------------------------------------
2nd git commit | aaaa
| +bbbb
----------------------------------------------
4th git commit | aaaa
| bbbb
| +cccc
| +dddd
----------------------------------------------
5th git commit | aaaa
| bbbb
| cccc
| dddd
| +eeee
Bueno, este era el tipo de lectura que esperaba haber encontrado, para comenzar a entender cómo git rebase
funciona en términos de eliminar commits / revisiones; así que espero que pueda ayudar a otros también ...