¿Cómo resolver el conflicto de git stash sin comprometerse?

Resuelto Sven asked hace 13 años • 0 respuestas

Como se pregunta en esta pregunta , también quiero saber cómo resolver un conflicto git stash popsin agregar todas las modificaciones a una confirmación (al igual que lo hace "git stash pop" sin conflicto).

Mi enfoque actual es muy desagradable porque lo hago de esta manera:

git stash pop  # -> CONFLICT
git stash drop
# [resolve conflict]
# [add conflict files]
git reset HEAD # <all files that are in commit-mode>

Cómo reproducirse:

mkdir foo; cd foo; git init
echo "1" > one
echo "2" > two
git add -A; git commit -m "first"
echo "1.1" > one
echo "2.1" > two
git stash
echo "2.2" > two
git commit -a -m "second"
echo "Only this file would stay in HEAD without the conflict" > third
git add third
git stash pop
git status

27/06/2016: Se agregó un nuevo archivo llamado 'tercero' al ejemplo para mostrar que soluciones alternativas como la solución de scy solo funcionan para HEAD vacíos pero no solucionan el problema inicial de que el HEAD no tiene el mismo contenido que para un git stash popsin conflicto.

Sven avatar Oct 13 '11 15:10 Sven
Aceptado

Solución limpia

La siguiente solución me parece mucho más clara y también la sugiere el propio Git : intente ejecutarla git statusen el repositorio con un conflicto:

Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

Nota: El restorecomando se introdujo en la versión 2.23.0 de Git . Las versiones anteriores de Git sugerían utilizar el comando git reset HEAD <file>...en lugar de git restore --staged <file>.... También puede utilizar git resetpara eliminar todos los archivos del área de preparación (llamado índice ). El equivalente del comando de restauración es git restore --staged .(el punto es necesario y especifica cualquier archivo). Actualmente, se puede utilizar cualquiera de esos comandos y el resultado es el mismo . Si desea conocer las diferencias entre esos comandos, consulte la documentación .

Entonces, hagamos lo que sugiere Git ( sin realizar ni revertir confirmaciones inútiles ):

  1. Resuelva los conflictos manualmente (o idealmente utilizando alguna herramienta de combinación , ver más abajo).
  2. Úselo git restore --staged .para marcar conflictos como resueltos y retirar todos los archivos del área de preparación. Si desea eliminar solo archivos específicos, use el comando git restore --staged <file>en su lugar. No es necesario ejecutar git addantes.
  3. Finalmente, elimine el alijo con git stash drop, porque Git no lo hace automáticamente en caso de conflicto.

Traducido a los comandos de la línea de comandos:

$ git stash pop

# ...resolve conflict(s)

$ git restore --staged .

$ git stash drop

Explicación del comportamiento predeterminado.

Hay dos formas de marcar los conflictos como resueltos: git addy git restore --staged <file>.... Mientras git restore --staged <file>...marca los conflictos como resueltos y elimina archivos del índice, git addtambién marca los conflictos como resueltos, pero mantiene los archivos en el índice.

Agregar archivos al índice después de resolver un conflicto es intencionado. De esta manera, puede diferenciar los cambios del alijo anterior y los cambios que realizó después de que se resolvió el conflicto. Si no te gusta, siempre puedes utilizar git restore --staged .para eliminar todo del índice.

Fusionar herramientas

Recomiendo encarecidamente utilizar cualquiera de las herramientas de combinación de 3 vías para resolver conflictos, por ejemplo, KDiff3 , Meld , etc., en lugar de hacerlo manualmente. Por lo general, resuelve todos o la mayoría de los conflictos automáticamente. ¡Es un gran ahorro de tiempo!

David Ferenczy Rogožan avatar Dec 09 '2014 15:12 David Ferenczy Rogožan

Supongamos que tiene este escenario en el que guarda sus cambios para poder extraerlos desde el origen. Posiblemente porque sus cambios locales están solo debug: trueen algún archivo de configuración. Ahora tiras y alguien ha introducido una nueva configuración allí, creando un conflicto.

git statusdice:

# On branch master
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#   both modified:      src/js/globals.tpl.js
no changes added to commit (use "git add" and/or "git commit -a")

Bueno. Decidí seguir lo que sugirió Git: resolví el conflicto y comprometí:

vim src/js/globals.tpl.js
# type type type …
git commit -a -m WIP   # (short for "work in progress")

Ahora mi copia de trabajo está en el estado que quiero, pero he creado una confirmación que no quiero tener. ¿Cómo me deshago de ese compromiso sin modificar mi copia de trabajo? Espera, ¡hay un comando popular para eso!

git reset HEAD^

Mi copia de trabajo no ha sido modificada, pero la confirmación WIP desapareció. ¡Eso es exactamente lo que quería! (Tenga en cuenta que no lo estoy usando --softaquí, porque si hay archivos fusionados automáticamente en su alijo, se organizan automáticamente y, por lo tanto, terminaría con estos archivos preparándose nuevamente después reset).

Pero queda una cosa más: la página de manual de git stash popnos recuerda que "la aplicación del estado puede fallar con conflictos; en este caso, no se elimina de la lista oculta. Debe resolver los conflictos manualmente y llamar git stash dropmanualmente después". Eso es exactamente lo que hacemos ahora:

git stash drop

Y hecho.

scy avatar Aug 13 '2013 15:08 scy

En lugar de agregar los cambios que realiza para resolver el conflicto, puede utilizar git reset HEAD filepara resolver el conflicto sin organizar los cambios.

Sin embargo, es posible que tengas que ejecutar este comando dos veces. Una vez para marcar el conflicto como resuelto y otra para eliminar los cambios que se realizaron mediante la rutina de resolución de conflictos.

Es posible que haya un modo de reinicio que haga ambas cosas simultáneamente, aunque ahora no existe.

ComputerDruid avatar Oct 28 '2011 17:10 ComputerDruid
git checkout stash -- .

trabajó para mi.

Nota : esto puede ser peligroso ya que no intenta fusionar los cambios del alijo en su copia de trabajo, sino que los sobrescribe con los archivos escondidos. Entonces puedes perder tus cambios no confirmados.

stevenspiel avatar Sep 09 '2014 18:09 stevenspiel