Pregunta ¿Extrae solo un archivo de varios archivos que han cambiado con Git?


¿Cómo puedo esconder solo uno de los múltiples archivos modificados en mi sucursal?


2437
2018-06-14 20:52


origen


Respuestas:


Advertencia

Como se señala en los comentarios, esto pone todo en el alijo, tanto en etapas como sin escena. El --keep-index simplemente deja el índice solo después de que se completa el alijo. Esto puede provocar conflictos de combinación cuando más tarde extrae el alijo.


Esto esconderá todo lo que no ha agregado previamente. Sólo git add las cosas que quieres conservar, luego ejecútalas.

git stash --keep-index

Por ejemplo, si desea dividir un compromiso anterior en más de un conjunto de cambios, puede usar este procedimiento:

  1. git rebase -i <last good commit>
  2. Marque algunos cambios como edit.
  3. git reset HEAD^
  4. git add <files you want to keep in this change>
  5. git stash --keep-index
  6. Repare las cosas según sea necesario. No olvides git add algún cambio.
  7. git commit
  8. git stash pop
  9. Repita, desde # 5, según sea necesario.
  10. git rebase --continue

1216
2017-11-30 21:28



También puedes usar git stash save -p "my commit message". De esta forma puede seleccionar qué partes se deben agregar a los escondites, también se pueden seleccionar archivos completos.

Se le indicará con algunas acciones para cada trozo:

   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

2612
2017-07-31 11:59



Dado que git es fundamentalmente sobre la gestión de un repositorio todo contenido e índice (y no uno o varios archivos), git stash ofertas, no es sorprendente, con el directorio de trabajo.

En realidad, desde Git 2.13 (Q2 2017), puede esconder archivos individuales, con:

git stash push [--] [<pathspec>...]

Ver "Stash cambia a archivos específicos" para más.


La respuesta original (a continuación, junio de 2010) fue sobre la selección manual de lo que quiere esconder.

Casebash comentarios:

Este el stash --patch solución original) es bueno, pero a menudo he modificado una gran cantidad de archivos, por lo que usar parches es molesto

Bukzores responder (upvoted, noviembre de 2011) sugiere una solución más práctica, basada en
git add + git stash --keep-index.
Ve y repite su respuesta, que debería ser la oficial (en lugar de la mía).

Acerca de esa opción, chhh señala un flujo de trabajo alternativo en los comentarios:

debieras "git reset --soft"después de ese alijo para recuperar tu escenificación clara:
  Para llegar al estado original, que es un área de transición clara y con solo algunas modificaciones seleccionadas sin etapas, se puede restablecer suavemente el índice para obtener (sin cometer nada como tú, bukzor).


(Respuesta original en junio de 2010: almacenamiento manual)

Todavía, git stash save --patch podría permitirle lograr el escondite parcial que busca:

Con --patch, puedes seleccionar hunks de forma interactiva en la diferencia entre HEAD y el árbol de trabajo que se esconderá.
  La entrada oculta se construye de modo que su estado de índice sea el mismo que el estado de índice de su repositorio, y su árbol de trabajo contiene solo los cambios que seleccionó de forma interactiva. Los cambios seleccionados se deshacen de su árbol de trabajo.

Sin embargo, eso guardará el índice completo (que puede no ser el que desee, ya que podría incluir otros archivos ya indexados), y un árbol de trabajo parcial (que podría parecerse al que desea esconder).

git stash --patch --no-keep-index

podría ser un mejor ajuste.


Si --patchno funciona, un proceso manual podría:

Para uno o varios archivos, una solución intermedia sería:

  • cópialos fuera del repositorio de Git
    (Actualmente, eleotlecram propone un alternativa interesante)
  • git stash
  • cópialos de vuelta
  • git stash # esta vez, solo los archivos que desea están escondidos
  • git stash pop stash@{1} # volver a aplicar todas sus modificaciones de archivos
  • git checkout -- afile # restablecer el archivo al contenido HEAD, antes de cualquier modificación local

Al final de ese proceso bastante engorroso, solo tendrá uno o varios archivos escondidos.


237
2018-06-14 21:23



Cuando git stash -p (o git add -p con stash --keep-index) sería demasiado engorroso, me pareció más fácil de usar diff, checkout y apply:

Para "esconder" un archivo / directorio particular solamente:

git diff path/to/dir > stashed.diff
git checkout path/to/dir

Luego luego

git apply stashed.diff

76
2018-02-12 13:44



Digamos que tienes 3 archivos

a.rb
b.rb
c.rb

y quiere esconder solo b.rb y c.rb pero no a.rb

puedes hacer algo como esto

# commit the files temporarily you don't want to stash
git add a.rb
git commit -m "temp" 

# then stash the other files
git stash save "stash message"

# then undo the previous temp commit
git reset --soft HEAD^
git reset

¡Y terminaste! HTH.


43
2017-10-31 07:10



Utilizar git stash push, Me gusta esto:

git stash push [--] [<pathspec>...]

Por ejemplo:

git stash push -- my/file.sh

Esto está disponible desde Git 2.13, lanzado en la primavera de 2017.


33
2017-08-15 13:10



Otra forma de hacer esto:

# Save everything
git stash 

# Re-apply everything, but keep the stash
git stash apply

git checkout <"files you don't want in your stash">

# Save only the things you wanted saved
git stash

# Re-apply the original state and drop it from your stash
git stash apply stash@{1}
git stash drop stash@{1}

git checkout <"files you put in your stash">

Se me ocurrió esto después de que (una vez más) llegué a esta página y no me gustaron las dos primeras respuestas (la primera respuesta simplemente no responde la pregunta y no me gustó mucho trabajar con -p modo interactivo).

La idea es la misma que @VonC sugirió usar archivos fuera del repositorio, usted guarda los cambios que desea en algún lugar, elimina los cambios que no quiere en su escondite, y luego vuelve a aplicar los cambios que se movió fuera del camino. Sin embargo, utilicé el escondite de git como "en algún lado" (y como resultado, hay un paso adicional al final: quitar los cañones que colocaste en el alijo, porque también los sacaste del camino).


25
2018-02-05 10:16



Actualización (14/02/2015) - He reescrito el script un poco, para manejar mejor el caso de conflictos, que ahora deberían presentarse como conflictos no fusionados en lugar de archivos .rej.


A menudo me resulta más intuitivo hacer lo contrario al enfoque de @ bukzor. Es decir, para realizar algunos cambios y luego esconder solo esos cambios por etapas.

Desafortunadamente, git no ofrece un "git stash" - only-index o similar, así que preparé un script para hacer esto.

#!/bin/sh

# first, go to the root of the git repo
cd `git rev-parse --show-toplevel`

# create a commit with only the stuff in staging
INDEXTREE=`git write-tree`
INDEXCOMMIT=`echo "" | git commit-tree $INDEXTREE -p HEAD`

# create a child commit with the changes in the working tree
git add -A
WORKINGTREE=`git write-tree`
WORKINGCOMMIT=`echo "" | git commit-tree $WORKINGTREE -p $INDEXCOMMIT`

# get back to a clean state with no changes, staged or otherwise
git reset -q --hard

# Cherry-pick the index changes back to the index, and stash.
# This cherry-pick is guaranteed to succeed
git cherry-pick -n $INDEXCOMMIT
git stash

# Now cherry-pick the working tree changes. This cherry-pick may fail
# due to conflicts
git cherry-pick -n $WORKINGCOMMIT

CONFLICTS=`git ls-files -u`
if test -z "$CONFLICTS"; then
    # If there are no conflicts, it's safe to reset, so that
    # any previously unstaged changes remain unstaged
    #
    # However, if there are conflicts, then we don't want to reset the files
    # and lose the merge/conflict info.
    git reset -q
fi

Puede guardar el script anterior como git-stash-index en algún lugar en su camino, y luego puede invocarlo como git stash-index

# <hack hack hack>
git add <files that you want to stash>
git stash-index

Ahora el alijo contiene una nueva entrada que solo contiene los cambios que había organizado, y su árbol de trabajo aún contiene cambios no registrados.

En algunos casos, los cambios del árbol de trabajo pueden depender de los cambios del índice, por lo que cuando oculta los cambios del índice, los cambios del árbol de trabajo tienen un conflicto. En este caso, obtendrá los conflictos no fusionados habituales que puede resolver con git merge / git mergetool / etc.


22
2018-06-16 21:00