2011-12-13 13 views
27
git mv file1 file2 

git status 
# On branch master 
# Changes to be committed: 
# (use "git reset HEAD <file>..." to unstage) 
# 
# renamed: file1 -> file2 

git stash 
git stash pop 

# On branch master 
# Changes to be committed: 
# (use "git reset HEAD <file>..." to unstage) 
# 
# new file: file2 
# 
# Changes not staged for commit: 
# (use "git add/rm <file>..." to update what will be committed) 
# (use "git checkout -- <file>..." to discard changes in working directory) 
# 
# deleted: file1 

Como puede ver, git pierde la relación renombrada después de un escondite/pop. ¿Hay alguna manera de recuperar esta relación, o tener escondido saber que los archivos se movieron? A menudo guardo para ver cuál es el estado de mi sistema como precambios, pero perderlo me causa problemas. No sé cómo solucionarlo más que borrar el nuevo archivo, volver a hacer un git mv y reemplazar el contenido del nuevo archivo.git stash y pop muestra que el archivo ya no está marcado como movido?

+1

Nota: que wo Debería ser interesante intentarlo de nuevo con Git 2.12 (Q1 2017). Ver http: // stackoverflow.com/a/41307892/6309 – VonC

Respuesta

26

Si no lo ha hecho estallar su escondite, hacer:

git stash pop --index 

Esto preserva correctamente movido (pero no comprometidos) las relaciones entre archivos en un alijo. De acuerdo con git help stash:

Si se usa la opción --index, entonces intenta restablecer no solo los cambios del árbol de trabajo, sino también los del índice. Sin embargo, esto puede fallar, cuando tiene conflictos (que están almacenados en el índice, por lo que ya no puede aplicar los cambios como estaban originalmente).

Si que ya ha metimos su escondite y desea volver a crear la relación movido, hacer:

git rm --cached file1 

Esto elimina el archivo indiferente "viejo" del índice:

Utilice esta opción para unstage y quitar caminos sólo desde el índice

+2

No sé si esta es una respuesta mejor que @ –

+2

de @ Jefromi 'git stash pop --index' es mejor si recuerda hacerlo la primera vez. Pero si anteriormente olvidó mostrar el índice, 'git rm --cached file1' lo llevará de vuelta a donde se cambie el nombre del archivo2 independientemente. –

+0

Es un poco annyoing. ¿Por qué git siempre tiene estas pequeñas debilidades que parecen estar allí para atraparte? – Steve

18

Respuesta corta: git rm --cached file1

Todo git mv realmente hace es cambiar el nombre del archivo (en el sistema de archivos) y luego añadir una eliminación de archivos y la creación del índice (área de ensayo). No está especialmente marcado. Posteriormente, otra maquinaria se da cuenta de que se trataba de un cambio de nombre, al ver que el contenido que antes se llamaba archivo1 se llama ahora archivo2.

Dado que los comandos git stash modifican el índice, pueden perturbar las cosas. Tenga en cuenta que ahora tiene la creación en etapas, ¡pero no la eliminación! (Normalmente, git-stash deja todo fuera de escena después de un pop, pero en este caso creo que no tiene más remedio que colocar el nuevo archivo en el índice, para evitar que no tenga idea de cuál conservar. Puede evitar esto alguna vez ocurriendo con git stash pop --index, pero eso explota si los cambios escondidos no se pueden aplicar limpiamente, por lo que no es el predeterminado.) git status ya no puede mostrarlo como un cambio de nombre, porque el cambio de nombre se divide efectivamente entre el índice y el trabajo árbol, y ninguna sección puede reclamarlo por completo.

Simplemente ejecute git rm --cached file1 para organizar la eliminación (es decir, elimine el archivo 1 del índice) y se mostrará nuevamente como un cambio de nombre. También puede ejecutar git add -u para agregar cambios automáticamente, siempre que no tenga otros cambios que no desee representar.

Tenga en cuenta que esto significa que en la práctica no tiene que preocuparse: cuando coloca correctamente todo en preparación para comprometerse (por ejemplo, con git add -u), el "problema" se soluciona solo.

Cuestiones relacionadas