git - name - Stash cambia a archivos específicos
recover git stash (5)
Tengo un gran proyecto de git que, estúpidamente, importé para eclipse y ejecuté un autoformato. Ahora, cada archivo en el proyecto se muestra como modificado. En lugar de enviar mis archivos formateados, prefiero revertir todos los archivos a los que solo he sido formateado y no he tenido otros cambios. Por ejemplo:
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
# (commit or discard the untracked or modified content in submodules)
# modified: dir/file1.cpp
# modified: dir/file1.h
# modified: dir/file2.cpp
# modified: dir/file2.h
# modified: dir/file3.cpp
# modified: dir/file3.h
# modified: dir/file4.cpp
# modified: dir/file4.h
Sé que file2.cpp
, file2.h
, y file3.cpp
se han modificado con contenido (es decir, no solo con formato). Quiero guardar los cambios en estos tres archivos y luego revisar una revisión anterior, para poder volver a aplicar los cambios a estos archivos después. Preferiría evitar algo como:
$ cp file2.cpp ~/tmp
$ git checkout blahblahblah
$ cp ~/tmp/file2.cpp .
Si hay una forma obvia de hacer esto que no implique el ocultamiento, hágamelo saber. lo que sea que haga el trabajo
Sé que
file2.cpp
,file2.h
, yfile3.cpp
se han modificado con contenido (es decir, no solo con formato).
Quiero guardar los cambios en estos tres archivos y luego revisar una revisión anterior, para poder volver a aplicar los cambios a estos archivos después.
Con Git 2.13 (Q2 2017), git stash tendrá oficialmente una forma de esconder cambios para archivos específicos con
git stash push [--] [<pathspec>...]
Consulte commit 9e14090 , commit 1ada502 , commit df6bba0 (28 de febrero de 2017) y commit 9ca6326 , commit 6f5ccd4 , commit f5727e2 (19 de febrero de 2017) de Thomas Gummerer ( tgummerer
) .
(Combinado por Junio C Hamano - gitster
- in commit 44c3f09 , 10 mar 2017)
Como se documenta ahora :
Para hacer una instantánea rápidamente, puede omitir "push".
En este modo, los argumentos que no son de opción no tienen permitido evitar que un subcomando mal escrito haga un alijo no deseado.
Las dos excepciones a esto sonstash -p
que actúa como alias parastash push -p
y pathspecs, que se permiten después de un guión doble--
para la desambiguación.Cuando se asigna pathspec a ''
git stash push
'', el nuevo stash registra los estados modificados solo para los archivos que coinciden con pathspec .
Las entradas de índice y los archivos del árbol de trabajo se devuelven al estado enHEAD
solo para estos archivos, también, dejando intactos los archivos que no coincidan con el pathspec.
Tenga en cuenta, como lo señaló medmunds en los comentarios , que git stash
usaría rutas relativas a la carpeta raíz del repositorio de git .
Eso es un buen uso para git diff
y git apply
IMO:
git diff file2.cpp file2.h file3.cpp > ../my-changes.patch
git checkout ...
git apply ../my-changes.patch
Después de la diff
, puede inspeccionar el archivo de parche para asegurarse de que todos los cambios estén allí.
Tenga en cuenta que es posible que deba usar la opción --reject
para aplicar, en caso de que el parche no se aplique limpiamente. También vea la página de manual para aplicar .
Puedes add
los archivos con los cambios que deseas mantener, luego stash
el resto de los archivos y eliminar el alijo:
git add file2.cpp file2.h file3.cpp
git stash --keep-index
En este punto, has escondido tus cambios no deseados. Si desea deshacerse de ellos permanentemente, ejecute:
git stash drop
Ahora tienes file2.cpp
, file2.h
, y file3.cpp
para el commit. Si luego quiere esconder estos archivos (y no cometerlos):
git reset
git stash
Ahora estará en su confirmación anterior, con solo esos tres archivos escondidos.
Actualizar:
Git 2.13 y posteriores incluyen una forma más directa de esconder archivos específicos con git stash push
, como lo explica VonC en su respuesta .
También puedes usar git stash -p. De esta manera, puede seleccionar qué trozos se deben agregar al alijo, también se pueden seleccionar archivos completos.
Se te indicarán algunas acciones para cada hunk:
y - stash this hunk
n - do not stash this hunk
q - quit; do not stash this hunk or any of the remaining ones
a - stash this hunk and all later hunks in the file
d - do not stash this hunk or any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help
Una buena opción es usar el modo de almacenamiento interactivo.
git stash --patch
Funciona principalmente como el modo de adición interactiva: se le presentará una serie de diferencias que muestran los cambios que tiene en su árbol de trabajo y debe elegir qué archivos (o solo ciertas partes de un archivo) desea ocultar. , el resto quedará intacto.
Del man git-stash
:
Con --patch, puede seleccionar de forma interactiva trozos de la diferencia entre HEAD y el árbol de trabajo que se va a esconder. La entrada de alijo se construye de tal manera que su estado de índice es el mismo que el estado de índice de su repositorio, y su área de trabajo contiene solo los cambios que seleccionó de manera interactiva. Los cambios seleccionados se retrotraen de su árbol de trabajo. Consulte la sección "Modo interactivo" de git-add (1) para aprender cómo operar el modo --patch.
En su caso, podrá ver fragmentos de solo formato y guardarlos individualmente, sin perder sus cambios significativos.