¿Cómo eliminar el primer commit en git?

179

Tengo curiosidad acerca de cómo eliminar el primer commit en git.

¿Cuál es la revisión antes de cometer algo? ¿Esta revisión tiene un nombre o etiqueta?

Jian Weihang
fuente
2
Para empezar con git, debes saber que la revisión no tiene sentido. Puede hablar sobre commits o sus SHA relativos. Además, ¿por qué quieres hacer esto? La primera confirmación es sobre qué está construido todo. Podría agrupar algunas confirmaciones juntas, incluida la primera confirmación, que se convierte en la nueva primera confirmación, pero ¿qué significa incluso eliminar la primera confirmación (o eliminar cualquiera excepto la última confirmación)?
Shahbaz
@Shahbaz sí, esa es la mejor manera, mira aquí, por ejemplo: ariejan.net/2011/07/05/git-squash-your-latests-commits-into-one
timaschew
55
Puedes usar git rebase -i --root. Consulte la siguiente respuesta SO para obtener más detalles: stackoverflow.com/questions/2246208/…
MKroehnert
Esta respuesta tiene la solución correcta para eliminar la confirmación de raíz de la rama actual:git filter-branch --parent-filter "sed 's/-p <the_commit>//'" HEAD
Jody Bruchon

Respuestas:

321

Para mí, la forma más segura es usar el update-refcomando:

git update-ref -d HEAD

Eliminará la referencia nombrada HEAD, por lo que restablecerá (suavemente, no perderá su trabajo) todas las confirmaciones de su rama actual .

Si lo que quieres es fusionar el primer commit con el segundo, puedes usar el rebasecomando:

git rebase -i --root

Una última forma podría ser crear una rama huérfana, una rama con el mismo contenido pero sin ningún historial de confirmación, y confirmar su nuevo contenido en ella:

git checkout --orphan <new-branch-name>
tzi
fuente
77
Es una pena que esta no sea la respuesta aceptada. También es una lástima que la mayoría de los éxitos en Google digan "no se puede deshacer la primera confirmación". Esto hizo el truco para mí. ¡Gracias!
danielpops
1
Gracias @danielpops por tu apoyo! Es bueno notar que respondí a esta pregunta 3 años después. Git ha evocado mientras tanto.
tzi
Usé rebase, marqué el segundo commit como "squash", y luego hice un --force push to origin. ¡Gracias!
Philip Atz
1
git update-ref -d HEAD es la forma más segura de eliminar todo el historial, no solo la confirmación inicial.
user1767316
Lo hice y eliminó todos mis archivos que agregué a la primera confirmación. Triste. Al menos no fue mucho
Vyacheslav Tsivina
42

No hay nada antes de la primera confirmación, ya que cada confirmación se refiere a una confirmación principal. Esto hace que la primera confirmación sea especial (una confirmación huérfana), por lo que no hay forma de referirse a un "estado" anterior.

Entonces, si desea corregir la confirmación, puede simplemente git commit --amend: esto modificará la confirmación sin crear otra.

Si solo desea comenzar de nuevo, elimine el .gitrepositorio y haga otro congit init

CharlesB
fuente
77
Esta respuesta es incorrecta: hay una manera de volver al estado anterior al primer commit. Ver la respuesta de tzi a continuación.
David Nelson
2
El --amendtampoco actualizará al autor correctamente si inicialmente estaba mal configurado. Eso es lo que necesitaba, así que utilicé la respuesta aceptada y luego hice una nueva confirmación.
Mark Edington
11
# Check out to a temporary branch:
git checkout --orphan TEMP_BRANCH

# Add all the files:
git add -A

# Commit the changes:
git commit -am "Initial commit"

# Delete the old branch:
git branch -D master

# Rename the temporary branch to master:
git branch -m master

# Finally, force update to our repository:
git push -f origin master
Megha Sahu
fuente
3
No es una respuesta: la pregunta era "cómo eliminar la primera confirmación" y no "cómo eliminar todo excepto la última confirmación".
peterh - Restablecer Monica
1
Estaba buscando exactamente esto. ¡Gracias!
Krzysztof Tomaszewski
6

Es posible que solo desee editar su primera confirmación (ya que siempre hay una primera confirmación en un repositorio de git). Considere usar en git commit --amend --reset-authorlugar de lo habitual git commit --amend.

Max Beikirch
fuente
1
No es una respuesta: la pregunta quería eliminar la primera confirmación y no modificar las propiedades de la última.
peterh - Restablecer Monica
@ peterh-ReinstateMonica Para aclaración: los commits pueden modificarse durante el rebase interactivo para cambiar su contenido por completo, pero - también debe proporcionarse -reset-author para cambiar el autor. Con eso, puede reemplazar completamente el primer compromiso a su gusto. Ver también la respuesta de CharlesB.
Max Beikirch
3

Estaba buscando una manera de deshacer todos los git commits de un repositorio, como si nunca hubieran sucedido.

Rebasar funcionará hasta cierto punto. Sin embargo, el primero (cronológicamente, el git commit más antiguo) siempre será problemático, ya que no tiene un padre, por lo que se producirá un error.

Ninguna de estas respuestas me resolvió del todo. Pero después de muchas búsquedas y pruebas y errores, ¡encontré que esto funcionaba!

git update-ref -d HEAD
git push origin master -f

Espero que esto te ayude. Que tengas un gran día.

kp123
fuente
1
Para que quede claro para cualquiera que lea esta respuesta: esto elimina cada confirmación, pero OP solo quiere eliminar la primera confirmación realizada en un repositorio; no ejecute esto para eliminar la primera confirmación porque eliminará TODAS las confirmaciones.
Jody Bruchon
2

Otra forma de hacerlo es:

  1. Pague a una sucursal que desea mantener (por ejemplo, dev) git checkout dev
  2. Ahora, elimine la rama que desea restablecer git branch -D master
  3. Ahora, crea una rama vacía con el mismo nombre git checkout --orphan master

Por supuesto, todo esto dependerá de su caso de uso, pero si tiene más de una rama, eliminar el .gitdirectorio no tiene sentido.

kumarharsh
fuente
3
Después de hacer esto, debe eliminar la rama en remoto antes de presionar. De lo contrario, cuando intente presionar, tendrá este error:! [rechazado] maestro -> maestro (no avance rápido) - error: no se pudieron enviar algunas referencias a '[email protected]: r1 / r2.git' - sugerencia: se rechazaron las actualizaciones porque la punta de su rama actual es detrás - pista: su contraparte remota. Integre los cambios remotos (por ejemplo, pista: 'git pull ...') antes de presionar nuevamente ... - Si hace un git pull, todas las confirmaciones regresan.
dxvargas
2

Si desea mantener otras ramas, pero, por ejemplo, hacer que la masterrama comience de nuevo sin un historial común para otras ramas, una forma segura de lograr esto es crear un nuevo repositorio e insertar el contenido en el anterior:

cd ..
git init newrepo
cd newrepo
# make some initial commits
git push ../oldrepo master:newmaster

Esto crea una newmasterrama en el antiguo repositorio, con un historial que no es común con ninguna de las otras ramas. Por supuesto, también puede sobrescribir el master, con git push -f.

Si desea destruir todas las ramas y todo el contenido existente, simplemente ejecute

rm -rf .git/
usuario1338062
fuente
1
No es una respuesta: el OP quería eliminar la primera confirmación y no comenzar un nuevo repositorio de git con el árbol de trabajo actual como confirmación inicial.
peterh - Restablecer Monica
@peterh Estoy de acuerdo en git rebase --rootque probablemente OP quería, pero teniendo en cuenta que esta respuesta tiene dos votos a favor, me abstendré de eliminarla en caso de que alguien todavía la encuentre relevante.
user1338062
Creo que esta respuesta es exactamente relevante - si desea eliminar la primera comprometerse en alguna rama, y no es sólo una cometen! (Pero también desea mantener las otras confirmaciones en otras ramas; y también desea hacer esto para que los cambios terminen en Bitbucket o Github, no solo localmente). Creo que esta respuesta es una forma de hacerlo, y Creo que puede ser la única forma aquí de hacer esto. (Eso es porque, también por lo que puedo ver, no hay forma de forzar el empuje de una rama local sin compromisos sobre una rama remota con algunos compromisos)
MikeBeaton
0

Si lo ha confirmado pero no lo ha presionado, simplemente elimine el directorio .git y git initnuevamente ...

Ali Sajid
fuente
@peterh Sí, lo hace. Está suponiendo (creo) que la pregunta del OP se trata de querer eliminar la primera confirmación pero mantener las confirmaciones posteriores. Otra posibilidad (que creo que coincide perfectamente con la pregunta del OP, y para la que esta respuesta es una respuesta) es querer eliminar el primero y solo confirmar desde una rama, volviendo a volver a estar completamente vacío nuevamente.
MikeBeaton
@ MikeBeaton Tienes razón. Elimino mi comentario, pero luego necesito votar para cerrar la pregunta como poco clara. Tenga en cuenta que aunque solo me hicieron este comentario, detrás de mí hay 40000 visitantes, y una parte importante de ellos encontró esta pregunta con google, y no obtuvieron lo que querían.
peterh - Restablece a Monica
Eso parece extremo. ¿Eliminar la pregunta? ¿No podría argumentarse (perfectamente bien) que una respuesta completa a lo que es una pregunta perfectamente razonable es que hay dos enfoques diferentes que deben adoptarse, dependiendo de si ... etc.? (Es decir, yo, por mi parte, habría gustaría saber cómo quitar el primer cometer cuando no es el único cometido, y también cómo quitar el primer compromiso al que es la única confirmación. Desde luego no es obvia, y ciertamente dependerá sobre detalles específicos de implementación, que de hecho resulta que se necesitan enfoques realmente diferentes en cada caso.)
MikeBeaton
0

La respuesta a la pregunta depende de si:

  • Desea eliminar el primer Y SOLO confirmar en una rama (mientras deja otras ramas como estaban), o si

  • Desea eliminar la primera confirmación en alguna rama, mientras 'deja en su lugar' las confirmaciones posteriores (y las otras ramas).

El segundo de estos es relativamente más simple. Esencialmente, debe volver a basar la raíz: la mayoría de las respuestas aquí son sobre formas de hacerlo.

Hacer lo segundo (eliminar el primer y único commit de una rama mientras se dejan otras ramas solas) es más difícil. O, al menos, especialmente más difícil si quieres que suceda y que el cambio se refleje en GitHub o Bitbucket. No hay (por lo que puedo decir) ninguna manera en Git para empujar o forzar empujar una rama sin compromisos. Y tampoco hay (de nuevo, por lo que puedo ver) ninguna forma de crear una nueva rama vacía sin compromisos en GitHub o Bitbucket. Por lo tanto, esencialmente debe crear un nuevo repositorio para crear una rama completamente vacía, y luego volver a agregar las ramas que desee (incluidas las confirmaciones que desee), según la respuesta de @ user1338062.

Así que espero que esta respuesta aclare lo que podría no haber sido obvio: que hay dos enfoques diferentes que deben tomarse, para dos escenarios diferentes (más o menos razonables) que son las dos cosas que es posible que desee hacer, en orden dominar completamente lo que pide el OP.

MikeBeaton
fuente