¿Por qué no se puede aplicar el alijo al directorio de trabajo?


96

No puedo volver a aplicar el alijo al directorio de trabajo.

Pequeña historia:

Primero intenté impulsar algunos cambios comprometidos, pero decía: "no, no puedes, tira primero" ... OK, entonces, sacaré cosas de GitHub y luego presionaré mis cambios. Cuando traté de tirar, decía que tenía cambios que se sobrescribirían y que debería guardar mis cambios. OK, guardé los cambios ... hice el tirón y empujé los cambios comprometidos. Pero ahora, no puedo restaurar los cambios no confirmados en los que estaba trabajando.

Este es el error:

MyPath/File.cs already exists, no checkout
Could not restore untracked files from stash

Seguro que todavía no entiendo todos los conceptos de git, me confunden un poco ... quizás hice algo mal.

Sería genial si alguien pudiera ayudarme a resolver esto ... He estado buscando en Google y todo durante más de una hora y aún no he encontrado una solución.

Se agradece mucho la ayuda. ¡Gracias!

Respuestas:


74

Parece que su alijo incluía un archivo sin seguimiento que posteriormente se agregó al repositorio. Cuando intentas comprobarlo, git se niega con razón porque estaría sobrescribiendo un archivo existente.

Para solucionarlo, puede hacer algo como eliminar ese archivo (está bien, todavía está en el repositorio), aplicar su alijo y luego reemplazar la versión guardada del archivo con la versión en repositorio según corresponda.

Editar: También es posible que el archivo solo se haya creado en el árbol de trabajo sin haber sido agregado al repositorio. En este caso, no elimine simplemente el archivo local, más bien:

  1. muévelo a otro lugar
  2. aplicar el alijo
  3. fusionar manualmente las dos versiones de archivo (árbol de trabajo vs. movido).

2
¿Hay alguna forma en que pueda evitar tener que esconder cosas en el futuro? Vengo de SVN, y se ve tan adelante ... simplemente actualizas, resuelves conflictos y luego te comprometes. Git no puede ser tan difícil, que necesito agregar 2 pasos en el ciclo. ¡Gracias de nuevo!
Miguel Angelo

2
@Miguel: El escondite no es un obstáculo. Es una herramienta adicional proporcionada por Git que le permite mejorar su flujo de trabajo y evitar conflictos y confirmaciones no limpias. git-scm.com/docs/git-stash
Koraktor

8
Si bien la respuesta es válida, realmente no estoy seguro de que git sea "correcto" en esto. Los archivos están en el repositorio, por lo que no hay peligro de pérdida de datos. ¿Por qué no aplicar los cambios? Vea este hilo - git.661346.n2.nabble.com/stash-refuses-to-pop-td7453780.html
studgeek

5
Creo que esta respuesta no es la más útil. git stashdebería ayudar a respaldar rápidamente los cambios locales. Eliminar manualmente un conjunto de archivos para restaurarlo interrumpe el flujo. El git stash branchenfoque en la otra respuesta suena mejor, pero aún mucho más manual de lo deseado.
bentolor

Esta respuesta funcionó mejor para mí cuando me encontraba en la misma situación. Después de hacer estallar el alijo, pasé por una fusión como esperaba desde el principio.
Billy Lazzaro

58

La forma más segura y fácil probablemente sería guardar cosas nuevamente:

git stash -u             # This will stash everything, including unstaged files
git stash pop stash@{1}  # This will apply your original stash

Luego, si está satisfecho con el resultado, puede llamar

git stash drop

para eliminar su escondite "seguro".


2
¡Gracias por esto, me salvó de mucho dolor y sufrimiento!
danjarvis

9
stash pop se aplicará y soltará su alijo original. Solo para que sea seguro usarlo en applylugar de pop.
Hilbrand Bouwkamp

2
De hecho, popes una combinación de applyy drop, pero solo lo hará dropsi se applytrabaja sin conflictos. Pero eso sí, applysuele ser más seguro.
Koraktor

2
Esto supone que no hay otros cambios en el directorio de trabajo que desee conservar. Para esta pregunta en particular, él insinúa (pero no dice explícitamente) que está en un estado limpio, pero quería señalar eso para otros que vienen aquí con cambios locales.
studgeek

1
Esto solo resuelve el problema si no se han cometido los problemas conflictivos . Recibes exactamente el mismo mensaje cuando se han comprometido (por ejemplo, con un pago limpio) y luego esto no cambiará nada ...
Jasper

56

Como lo menciona @bentolo, puede eliminar manualmente los archivos de los que se queja, cambiar de rama y luego volver a agregarlos manualmente. Pero personalmente prefiero quedarme "dentro de git".

La mejor forma de hacerlo es convertir el alijo en una rama. Una vez que es una rama, puede trabajar normalmente en git usando las técnicas / herramientas normales relacionadas con las ramas que conoce y ama. En realidad, esta es una técnica general útil para trabajar con escondites incluso cuando no tiene el error enumerado. Funciona bien porque un alijo realmente es un compromiso bajo las sábanas (ver PD).

Convertir un alijo en una rama

Lo siguiente crea una rama basada en HEAD cuando se creó el alijo y luego aplica el alijo (no lo confirma).

git stash branch STASHBRANCH

Trabajar con la "rama de alijo"

Lo que haga a continuación depende de la relación entre el alijo y dónde se encuentra ahora su rama de destino (que llamaré ORIGINALBRANCH).

Opción 1 - Rebasear la rama de alijo normalmente (muchos cambios desde el alijo)

Si ha realizado muchos cambios en su SUCURSAL ORIGINAL, probablemente sea mejor tratar STASHBRANCH como cualquier sucursal local. Confirme sus cambios en STASHBRANCH, vuelva a basarlo en ORIGINALBRANCH, luego cambie a ORIGINALBRANCH y vuelva a colocar / fusionar los cambios de STASHBRANCH sobre él. Si hay conflictos, trátelos normalmente (una de las ventajas de este enfoque es que puede ver y resolver los conflictos).

Opción 2: restablecer la rama original para que coincida con el alijo (cambios limitados desde el alijo)

Si simplemente guardó algunos cambios por etapas, luego se comprometió, y todo lo que quiere hacer es obtener los cambios adicionales que no estaban almacenados cuando los guardó, puede hacer lo siguiente. Volverá a su rama e índice originales sin cambiar su copia de trabajo. El resultado final serán sus cambios adicionales de alijo en su copia de trabajo.

git symbolic-ref HEAD refs/heads/ORIGINALBRANCH
git reset

Antecedentes

Las reservas son confirmaciones como ramas / etiquetas (no parches)

PD: Es tentador pensar en un alijo como un parche (al igual que es tentador pensar en un compromiso como un parche), pero un alijo es en realidad un compromiso contra el HEAD cuando se creó. Cuando aplica / pop, está haciendo algo similar a seleccionarlo en su rama actual. Tenga en cuenta que las ramas y etiquetas son en realidad solo referencias a confirmaciones, por lo que, en muchos sentidos, los alijos, ramas y etiquetas son solo formas diferentes de señalar una confirmación (y su historial).

A veces es necesario incluso cuando no ha realizado cambios en el directorio de trabajo

PPS, es posible que necesite esta técnica después de usar alijo con --patch y / o --include-untracked. Incluso sin cambiar los directorios de trabajo, esas opciones a veces pueden crear un alijo que no se puede volver a aplicar. Debo admitir que no entiendo completamente por qué. Consulte http://git.661346.n2.nabble.com/stash-refuses-to-pop-td7453780.html para una discusión.


5
Esta respuesta debe marcarse como solución, ya que proporciona los consejos más útiles sobre cómo resolver un 'escondite bloqueado' de manera más efectiva. Tal vez mejorarlo mencionando la 'solución de eliminación simple' primero y la solución de rama como segunda opción.
bentolor

8
"git stash branch STASHBRANCH" no parece funcionar si se enfrenta a este escenario (aparece exactamente el mismo mensaje de error que con pop). Es posible que tenga que hacer algunos restablecimientos de git de antemano.

+1 Me metí en un lío de espaguetis con confirmaciones y cambios y escondite, etc. Esto me sacó de esto al colocar el alijo en una rama gracias studgeek
RobbZ

Gracias por la aclaración sobre cómo los escondites no son parches y cómo están atados a la CABEZA (en el momento de guardarlos). Eso tiene mucho sentido. - Entonces ... supongo que hay casos en los que es más flexible / portátil / conveniente crear un parche en lugar de un alijo (como mencionaste: cuando hay muchos cambios), para que se pueda aplicar en cualquier lugar (y es solo es cuestión de resolver conflictos). Quizás git stash show -pestá ayudando allí para hacer alijo -> * parche *.
Kamafeather

39

La solución: debe eliminar el archivo en cuestión, luego intentar guardar el pop / aplicar nuevamente y debería pasar. No elimine otros archivos, solo los mencionados por el error.

El problema: Git apesta a veces. Cuando se ejecuta git stash -u, incluye archivos sin seguimiento (¡genial!) Pero no elimina esos archivos sin seguimiento y no sabe cómo aplicar los archivos sin seguimiento escondidos encima de los sobrantes (¡no genial!), Lo que realmente hace que la -uopción sea bastante inútil.


3
Habría aceptado esta respuesta si fuera mi pregunta. Gracias @qwertzguy, su respuesta resolvió mi problema,
Kobus Myburgh

Me encontré con el mismo problema, git stash pop no se aplicaría hasta que elimine los archivos en cuestión; luego me encontré con un conflicto con un archivo que hizo que se rechazara el alijo. Pero en lugar de eliminar los archivos sin seguimiento, los dejó atrás .. Así que tenga en cuenta que en el futuro manténgase alejado degit stash -u
notzippy

Mal consejo si necesita partes de ambas versiones de los archivos afectados.
Walf

2
"no elimina los archivos sin seguimiento" ... y no los incluye git stash show. Esta respuesta hizo que se encendiera la bombilla.
jscs

2
más uno para Git apesta a veces.
Harish

29

Para aplicar las diferencias de código en el alijo como un parche, use el siguiente comando:

git stash show --patch | patch -p1

11
Por lo general, es mejor explicar una solución en lugar de simplemente publicar algunas filas de código anónimo. Puede leer Cómo escribo una buena respuesta y también Explicar respuestas totalmente basadas en código .
Massimiliano Kraus

Esto funciona para mí, ya que el parche de git stash show --patchno contiene los archivos sin seguimiento.
Steven Shaw

Esta respuesta me ayudó mucho ya que no pude sacar mi alijo debido a muchos cambios en mi repositorio desde que se envió el alijo.
Erik Finnman

1

Esto me ha sucedido en numerosas ocasiones, guardo archivos sin git stash -useguimiento con los que se terminan agregando al repositorio y ya no puedo aplicar los cambios guardados.

No pude encontrar una manera de forzar el git stash pop/applyreemplazo de los archivos, así que primero elimino las copias locales de los archivos sin seguimiento que estaban escondidos ( tenga cuidado, ya que eliminará los cambios que no se han confirmado ) y luego aplico los cambios escondidos :

rm `git ls-tree -r stash@{0}^3 --name-only`
git stash apply

Finalmente, utilizo git status, git diffy otras herramientas, para verificar y agregar partes de los archivos eliminados si falta algo.


Si tiene cambios no confirmados que desea conservar, primero puede crear una confirmación temporal:

git add --all
git commit -m "dummy"
rm `git ls-tree -r stash@{0}^3 --name-only`
git stash apply

Use las herramientas que más le convengan para fusionar los cambios previamente confirmados en los archivos locales y elimine la confirmación ficticia:

git reset HEAD~1

0

Mi operación pop bloqueada de manera similar se debió a que los archivos restantes ignorados (consulte el archivo .gitignore). El estado de Git me mostró rastreado y no rastreado, pero mis actividades no limpiaron los archivos ignorados.

Detalles: había usado git stash save -a, comprobado el maestro para compilar y ver el comportamiento original, luego intenté volver a colocarlo todo para continuar editando. Cuando revisé mi rama e intenté hacer estallar, mis archivos ignorados todavía estaban allí desde antes de guardar el alijo. Esto se debe a que la extracción del maestro solo afectó los archivos comprometidos, no borró los archivos ignorados. Entonces, el mensaje emergente falló, esencialmente diciendo que no quería restaurar mis archivos ignorados escondidos encima de los archivos que todavía estaban allí. Es lamentable que no haya podido encontrar la manera de iniciar una sesión de fusión con ellos.

En última instancia, solía git clean -f -d -xeliminar los archivos ignorados. Curiosamente, de mis ~ 30, todavía quedan 4 archivos después de la limpieza (enterrados en subdirectorios). Tendré que averiguar en qué categoría están, que tenían que eliminarse manualmente.

Entonces mi pop tuvo éxito.



-1

Otra solucion:

cd to/root/your/project

# Show what git will be remove
git clean -n

# If all is good
git clean -f

# If not all is good, see
git clean --help

# Finish
git stash pop

El error mencionado en la pregunta es causado por un archivo que existe tanto en la pila como en el directorio de trabajo. La limpieza solo lo soluciona si no se rastrea este archivo, lo que ciertamente no es siempre el caso (y no el caso del OP, ya que obtuvo el archivo de una extracción).
Xavier Poinas

-1

Con Git 2.14.x / 2.15 (Q3 2017), la solución de qwertzguy de 2014 ya no será necesaria.

Antes del tercer trimestre de 2017, tenía que eliminar el archivo en cuestión y luego intentar guardar el pop / aplicar nuevamente.
Con la próxima versión de Git, no tendrá que hacer eso.

Ver commit bbffd87 (11 de agosto de 2017) de Nicolas Morey-Chaisemartin ( nmorey) .
(Combinado por Junio ​​C Hamano - gitster- en el compromiso 0ca2f32 , 23 de agosto de 2017)

stash: limpiar archivos sin seguimiento antes de restablecer

Si se llama git stash -ua un repositorio que contiene un archivo que ya no se ignora debido a una modificación actual del gitignorearchivo, este archivo se guarda pero no se elimina del árbol de trabajo.
Esto se debe a que git-stashprimero se hace una reset --hardque borra la .gitignoremodificación del archivo y luego se llama git clean, dejando el archivo intacto.
Esto hace git stash popque falle debido a que el archivo existe .

Este parche simplemente cambia el orden entre limpieza y restablecimiento y agrega una prueba para este caso de uso.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.