2010-08-26 7 views

Respuesta

10

Se piensa que esto es más fácil de hacer con commits temporales. Cuando tiene confirmaciones escalonadas y sin escena, tiene la posibilidad de conflictos al intentar reordenar los cambios.

Hacer una confirmación con los cambios por etapas, crear una rama para su uso posterior:

git commit -m "Saved staged" 
git branch save-staged 

Hacer una confirmación con los cambios unstaged (si los cambios unstaged incluyen nuevos archivos es posible que necesite de forma explícita git add ellos primero) :

git commit -a -m "Unstaged changes" 

rebase los cambios unstaged sobre la cabeza originales (puede implicar la resolución de conflictos):

git rebase --onto HEAD^^ HEAD^ 

rebase los cambios escalonados sobre el cambio unstaged (puede implicar la resolución de conflictos):

git reset --hard save-staged 
git rebase --onto [email protected]{1} HEAD^ 

Por último, restablezca el índice para los (originalmente) cambios unstaged:

git reset HEAD^ 

y mover el puntero rama de nuevo a la cabeza original:

git reset --soft HEAD^ 

rama temporal Eliminado:

git branch -D save-staged 
+1

sí, esta forma es demasiado compleja para comprenderla o recordarla, pero realmente funciona. Supongo que hay una manera más fácil, ¿tal vez usando parches? – whitered

+1

@whitered: pregunta abierta: ¿qué tienes dificultad para entender? Las páginas man para restablecimiento, rebase y confirmación deben describir todas las opciones que he utilizado en detalle y los pasos que uso se suponen acciones lógicas paso a paso. –

1

Charles Bailey tiene un more complete solution que implica compromisos y la gestión de posibles conflictos de resolución.

yo estaba tratando originalmente para utilizar sólo git stash, a excepción de lo que inicialmente se pasa por alto fue que git stash Guardar guardará tanto el índice (por etapas cambios) y los cambios unstaged (lo cual es un inconveniente cuando se desea cambiar el contenido del índice con los cambios no escalonados).

Así que modifica para el enfoque siguiente en su lugar:

  • git commit -m "temp cometer" (crear un compromiso para el índice actual)
  • git stash (esconder, obviamente, lo que aún no se añade al índice)
  • git reset --soft HEAD^ (preservar los archivos previamente comprometidos)
  • git stash nuevo
  • git stash pop [email protected]{1} (una pplying no es lo que acaba de escondiste, pero lo escondiste antes, es decir, los cambios iniciales que aún no se han agregado al índice)
  • git add -A
  • git stash drop [email protected]{1} para limpiar el alijo hemos aplicado anteriormente (escondite @ {0} sigue contiene lo que estaba originalmente en el índice)

al final:

  • lo que no se agrega al índice ahora se añade.
  • lo que era inicialmente en el índice termina siendo escondido
+0

'git stash' implica un' git reset --hard' entonces 'git reset --mixed' es un no-operativo y el segundo' git stash' no tiene nada que hacer? –

+0

@Charles: a la derecha. He actualizado la respuesta para usar 'git stash --keep-index'. De esa forma, el 'git reset --mixed' tiene algo que ver;) – VonC

+0

OK, pero no' git drop stash @ {1} 'seguramente no es correcto y si el último paso en su proceso es' git add -A '¿Entonces no vas a terminar con ningún cambio sin escena? No estoy seguro de que el alijo sea la respuesta, parece muy complejo hacerlo bien ;-). –

3

La forma de manchas (que no funciona para cambios binarios):

Guardar parches para ambos protagonizaron y estados unstaged

git diff >> unstaged.patch 
git diff --cached >> staged.patch 

Aplicar cambios originalmente unstaged

git reset --hard 
git apply unstaged.patch 

Etapa de estos cambios, excepto los archivos de parche

git add -A 
git reset -- staged.patch unstaged.patch 

Aplicar organizaron originalmente cambios

git apply staged.patch 

Eliminar archivos del parche

rm staged.patch unstaged.patch 
+0

Solución interesante también. +1. Solo por curiosidad, ¿volvió a probar la versión actualizada de mi respuesta 'git stash'? – VonC

+0

Sí, lo he vuelto a probar, funciona bien a menos que haya algunos archivos nuevos (sin seguimiento antes) organizados. Mi variante con parches falla también en este caso. – whitered

4

Para una solución de nivel inferior, se puede usar un poco de plomería para hablar directamente con el índice:

INDEXTREE=`git write-tree` 
git add -A 
WORKTREE=`git write-tree` 
git checkout $INDEXTREE -- . 
git clean -f 
git read-tree $WORKTREE 

Lo que hace es construir un par de objetos de árbol temporales en la tienda de git, uno para el índice y otro para el copia de trabajo. Luego, restaura el índice anterior y lo revisa en el árbol de trabajo. Finalmente. restablece el índice a la versión que representa el árbol de trabajo anterior.

No he probado esto, así que no estoy seguro de qué tan bien maneja los archivos agregados en el índice o en el árbol de trabajo.

+1

+1 para un enfoque interesante – sehe

+0

¡Gracias por la respuesta! Esto me inspiró a hacer una mejor versión para secuencias de comandos, y también a crear otra secuencia de comandos que pueda esconder solo cambios por etapas. – JesusFreke

3

Esto se basa en Walter Mundt's answer, pero funciona mejor cuando se organizan nuevos archivos. Esto está destinado a ser usado como un script, p. git-invert-index

#!/bin/sh 

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

# write out a tree with only the stuff in staging 
INDEXTREE=`git write-tree` 

# now write out a tree with everything 
git add -A 
ALL=`git write-tree` 

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

# apply the changes that were originally staged, that we want to 
# be unstaged 
git checkout $INDEXTREE -- . 
git reset 

# apply the originally unstaged changes to the index 
git diff-tree -p $INDEXTREE $ALL | git apply --index --reject 
+0

(Tenga en cuenta que, como está escrito, esto puede eliminar algunos subdirectorios vacíos de la copia de trabajo durante la limpieza de git. Dada la desatención general de git para los directorios vacíos, esto puede ser difícil de evitar.) –

+0

¿Por qué está utilizando "diff-tree | apply; agregue -A "en lugar de" pagar $ INDEXTREE -. "? Tenga en cuenta que el pago con un árbol no cambia su sucursal, por lo que los dos deben tener el mismo efecto neto, pero el pago debe ser mucho más rápido ya que no tiene que construir y analizar un archivo de parche y luego volver a explorar el árbol de trabajo para rellenar el índice. –

+0

Para el primer árbol diff, desea los cambios entre árboles INDEXTREE guardados y TODOS. Solo retirar no es lo que quieres. Para el segundo caso, el uso de git checkout agrega los cambios de INDEXTREE al índice, pero deben ser eliminados – JesusFreke

Cuestiones relacionadas