git reset
se trata de mudarse HEAD
, y generalmente la rama ref .
Pregunta: ¿qué pasa con el árbol de trabajo y el índice?
Cuando se emplea con --soft
, movimientos HEAD
, más a menudo posible actualizar el árbitro rama, y sólo elHEAD
.
Esto difiere de commit --amend
como:
- no crea una nueva confirmación.
- en realidad puede mover HEAD a cualquier confirmación (ya
commit --amend
que solo se trata de no mover HEAD, mientras permite rehacer la confirmación actual)
Acabo de encontrar este ejemplo de combinación:
- una fusión clásica
- una fusión de subárbol
todo en uno (pulpo, ya que hay más de dos ramas fusionadas) cometer fusión.
Tomas "wereHamster" Carnecky explica en su artículo "Subtree Octopus merge" :
- La estrategia de fusión de subárbol se puede usar si desea fusionar un proyecto en un subdirectorio de otro proyecto y, posteriormente, mantener el subproyecto actualizado. Es una alternativa a los submódulos git.
- La estrategia de combinación de pulpo se puede utilizar para combinar tres o más ramas. La estrategia normal puede fusionar solo dos ramas y si intentas fusionar más que eso, git vuelve automáticamente a la estrategia de pulpo.
El problema es que solo puedes elegir una estrategia. Pero quería combinar los dos para obtener un historial limpio en el que todo el repositorio se actualiza atómicamente a una nueva versión.
Tengo un superproyecto, llamémoslo projectA
, y un subproyecto projectB
, que fusioné en un subdirectorio projectA
.
(esa es la parte de combinación de subárbol)
También mantengo algunos compromisos locales.
ProjectA
se actualiza regularmente, projectB
tiene una nueva versión cada dos días o semanas y generalmente depende de una versión particular de projectA
.
Cuando decido actualizar ambos proyectos, no me limito a retirarlos projectA
y projectB
eso crearía dos confirmaciones para lo que debería ser una actualización atómica de todo el proyecto .
En cambio, creo una única confirmación de combinación que combina projectA
, projectB
y mis confirmaciones locales .
La parte difícil aquí es que se trata de una fusión de pulpo (tres cabezas), pero projectB
debe fusionarse con la estrategia de subárbol . Entonces esto es lo que hago:
# Merge projectA with the default strategy:
git merge projectA/master
# Merge projectB with the subtree strategy:
git merge -s subtree projectB/master
Aquí el autor usó un reset --hard
, y luego read-tree
para restaurar lo que las dos primeras fusiones habían hecho en el árbol de trabajo y el índice, pero ahí es donde reset --soft
puede ayudar:
Cómo rehacer esas dos fusiones , que han funcionado, es decir, mi árbol de trabajo e índice son bien, pero sin tener que grabar esos dos commits?
# Move the HEAD, and just the HEAD, two commits back!
git reset --soft HEAD@{2}
Ahora, podemos reanudar la solución de Tomás:
# Pretend that we just did an octopus merge with three heads:
echo $(git rev-parse projectA/master) > .git/MERGE_HEAD
echo $(git rev-parse projectB/master) >> .git/MERGE_HEAD
# And finally do the commit:
git commit
Entonces, cada vez:
- está satisfecho con lo que termina (en términos de árbol de trabajo e índice)
- que está no satisfecho con todas las confirmaciones que se ha tomado en llegar:
git reset --soft
es la respuesta.
git reset --soft
: stackoverflow.com/questions/6869705/…Caso de uso: combine una serie de confirmaciones locales
"Oops. Esos tres commits podrían ser solo uno".
Entonces, deshaga los últimos 3 (o lo que sea) confirmaciones (sin afectar el índice ni el directorio de trabajo). Luego, confirme todos los cambios como uno solo.
P.ej
Ahora todos sus cambios se conservan y están listos para ser confirmados como uno solo.
Respuestas cortas a sus preguntas.
¿Son estos dos comandos realmente iguales (
reset --soft
vscommit --amend
)?¿Alguna razón para usar uno u otro en términos prácticos?
commit --amend
para agregar archivos / rm desde la última confirmación o para cambiar su mensaje.reset --soft <commit>
combinar varias confirmaciones secuenciales en una nueva.Y lo que es más importante, ¿hay otros usos
reset --soft
además de enmendar un commit?fuente
reset --soft
además de enmendar un commit - No"git reset
) son buenos cuando (a) desea reescribir el historial, (b) no le importan las confirmaciones antiguas (para que pueda evitar la irritabilidad de la rebase interactiva) y (c) tener más de un compromiso de cambio (de lo contrario,commit --amend
es más simple).Lo uso para enmendar más que solo el último commit.
Digamos que cometí un error en el compromiso A y luego cometí el compromiso B. Ahora solo puedo enmendar B. Entonces lo hago
git reset --soft HEAD^^
, corrijo y vuelvo a confirmar A y luego vuelvo a confirmar B.Por supuesto, no es muy conveniente para grandes confirmaciones ... pero no deberías realizar grandes confirmaciones de todos modos ;-)
fuente
git commit --fixup HEAD^^
git rebase --autosquash HEAD~X
Funciona bien también.git rebase --interactive HEAD^^
donde elige editar las confirmaciones A y B. De esta manera, se mantienen los mensajes de confirmación de A y B; si es necesario, también puede modificarlos.git reset A
, la marca y añadir cambios,git commit --amend
,git cherry-pick <B-commit-hash>
.Otro uso potencial es como una alternativa al alijo (que a algunas personas no les gusta, ver, por ejemplo, https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-considered-harmful/ ).
Por ejemplo, si estoy trabajando en una sucursal y necesito arreglar algo urgentemente en master, puedo hacer lo siguiente:
luego finalice la compra y haga la corrección. Cuando termine, regreso a mi sucursal y hago
para seguir trabajando donde lo dejé.
fuente
--soft
realidad es innecesario aquí, a menos que realmente te importe que los cambios se realicen de inmediato. Ahora solo usogit reset HEAD~
cuando hago esto. Si tengo algunos cambios por etapas cuando necesito para cambiar ramas, y quiero que siga siendo así, entonces lo hagogit commit -m "staged changes"
, entoncesgit commit -am "unstaged changes"
, más tardegit reset HEAD~
seguido degit reset --soft HEAD~
restaurar completamente el estado de trabajo. Aunque, para ser sincero, hago ambas cosas mucho menos ahora que sé sobregit-worktree
:)Puede usar
git reset --soft
para cambiar la versión que desea tener como padre para los cambios que tiene en su índice y árbol de trabajo. Los casos en que esto es útil son raros. A veces puede decidir que los cambios que tiene en su árbol de trabajo deberían pertenecer a una rama diferente. O puede usar esto como una forma simple de contraer varias confirmaciones en una (similar a squash / fold).Vea esta respuesta de VonC para un ejemplo práctico: ¿ Aplastar los dos primeros commits en Git?
fuente
git reset --soft anotherBranch
y luego me comprometo allí. Pero en realidad no cambias la rama de ckeckout, entonces ¿te comprometerás con Branch u otra rama ?Un posible uso sería cuando desea continuar su trabajo en una máquina diferente. Funcionaría así:
Verifique una nueva sucursal con un nombre similar a un alijo,
Empuja tu rama escondida hacia arriba,
Cambie a su otra máquina.
Tire hacia abajo tanto su alijo como las ramas existentes,
Debería estar en su sucursal actual ahora. Combinar en los cambios de la rama de alijo,
Reinicie su rama existente a 1 antes de su fusión,
Retira tu rama escondida,
También quite su rama oculta del origen,
Continúe trabajando con sus cambios como si los hubiera escondido normalmente.
Creo que, en el futuro, GitHub y compañía. debería ofrecer esta funcionalidad de "escondite remoto" en menos pasos.
fuente
Un uso práctico es si ya se ha comprometido con su repositorio local (es decir, git commit -m), entonces puede revertir esa última confirmación haciendo git reset --soft HEAD ~ 1
También para su conocimiento, si ya ha organizado sus cambios (es decir, con git add.), Entonces puede revertir la puesta en escena haciendo git reset - HEAD mixto o también he usado comúnmente
git reset
Por último, git reset --hard borra todo, incluidos los cambios locales. El ~ después de la cabeza le dice a cuántos compromisos ir desde la parte superior.
fuente
git reset --soft HEAD ~1
me dafatal: Cannot do soft reset with paths.
creo que necesitamos eliminar el espacio después de HEAD para que así seagit reset --soft HEAD~1
Una buena razón para usar '
git reset --soft <sha1>
' es moverseHEAD
en un repositorio desnudo.Si intenta usar la opción
--mixed
o--hard
, obtendrá un error ya que está intentando modificar y trabajar un árbol y / o índice que no existe.Nota: Deberá hacer esto directamente desde el repositorio simple.
Nota de nuevo: deberá asegurarse de que la rama que desea restablecer en el repositorio simple sea la rama activa. De lo contrario, siga la respuesta de VonC sobre cómo actualizar la rama activa en un repositorio simple cuando tenga acceso directo al repositorio.
fuente
SourceTree es una GUI de git que tiene una interfaz bastante conveniente para organizar solo los bits que desea. No tiene nada remotamente similar para modificar una revisión adecuada.
Por
git reset --soft HEAD~1
lo tanto, es mucho más útil quecommit --amend
en este escenario. Puedo deshacer la confirmación, recuperar todos los cambios en el área de preparación y continuar ajustando los bits en escena usando SourceTree.Realmente, me parece que
commit --amend
es el comando más redundante de los dos, pero git es git y no rehuye comandos similares que hacen cosas ligeramente diferentes.fuente
Si bien me gustan las respuestas en este hilo, lo uso
git reset --soft
para un escenario ligeramente diferente, pero muy práctico, sin embargo.Utilizo un IDE para el desarrollo que tiene una buena herramienta de diferencias para mostrar los cambios (en etapas y sin etapas) después de mi última confirmación. Ahora, la mayoría de mis tareas implican múltiples confirmaciones. Por ejemplo, digamos que hago 5 confirmaciones para completar una tarea en particular. Utilizo la herramienta diff en el IDE durante cada confirmación incremental de 1-5 para ver mis cambios desde la última confirmación. Me parece una forma muy útil de revisar mis cambios antes de comprometerme.
Pero al final de mi tarea, cuando quiero ver todos mis cambios juntos (desde antes del primer commit), para hacer una auto revisión de código antes de hacer una solicitud de extracción, solo vería los cambios de mi commit anterior (después del commit 4) y no cambios de todos los commits de mi tarea actual.
Así que
git reset --soft HEAD~4
solía retroceder 4 commits. Esto me permite ver todos los cambios juntos. Cuando estoy seguro de mis cambios, puedo hacerlogit reset HEAD@{1}
y llevarlo a control remoto con confianza.fuente
git add --patch
ygit commit
repetidamente para construir la serie de commit que hubieras construido si supieras lo que estabas haciendo todo el tiempo. Sus primeras confirmaciones son como las notas en su escritorio o el primer borrador de un memo, están ahí para organizar su pensamiento, no para su publicación.git reset @{1}
restaurar su primer borrador de serie, puede crear una serie para publicación a partir degit add -p
ygit commit
.Otro caso de uso es cuando desea reemplazar la otra rama con la suya en una solicitud de extracción, por ejemplo, supongamos que tiene un software con las características A, B, C en desarrollo.
Está desarrollando con la próxima versión y usted:
Función eliminada B
Característica agregada D
En el proceso, desarrolle las revisiones recién agregadas para la característica B.
Puede combinar el desarrollo en el siguiente, pero eso puede ser complicado a veces, pero también puede usar
git reset --soft origin/develop
y crear una confirmación con sus cambios y la rama se puede fusionar sin conflictos y mantener sus cambios.Resulta que
git reset --soft
es un comando útil. Personalmente lo uso mucho para aplastar los compromisos que no tienen "trabajo completado" como "WIP", por lo que cuando abro la solicitud de extracción, todos mis compromisos son comprensibles.fuente