2012-03-17 11 views
11

Tengo un poco de una rama desordenada con 20 compromisos o así, y me estoy preparando para una fusión de nuevo a maestro. Lo he vuelto a basar en master, y al mirar más de cerca, me doy cuenta de que hay archivos que se están modificando de forma totalmente irrelevante para esta rama y que no están listos para comprometerse. Los cambios en esos archivos no se limitan a confirmaciones específicas.Git: la mejor manera de eliminar todos los cambios de un archivo determinado para una rama

Básicamente, no quiero tener nada que ver con esos archivos para ser incluidos en esta rama si es posible. ¿Hay una buena manera de hacerlo? Mi posición de repliegue n. ° 1 es, obviamente, copiar la última copia de cada uno de esos archivos y luego confirmarlos. Pero entonces la historia aún contendrá los cambios, y los Dioses Git fruncirán el ceño sobre mí.

La posición de retroceso # 2 es hacer lo mismo, luego aplastar todo el historial de ramas hasta una confirmación.

¿Alguna mejora en esto?

Respuesta

16

Digamos que su historia es

$ git lola 
* 6473d7f (master) Update 
| * 9bcfa7e (HEAD, topic) Munge a, b, and c 
| * 99af942 Munge b and c 
| * 8383e2c Munge a and b 
|/ 
* d1363f4 Baseline

Nota: lola es un alias no estándar pero útil.

Las confirmaciones han modificado tres archivos diferentes.

$ git log --decorate=short --pretty=oneline --name-status topic 
9bcfa7e946a92c226ad50ce430a9e4ae55b32490 (HEAD, topic) 
M  a 
M  b 
M  c 
99af942dbb922effcad8a72e96bec9ee9afcc437 Munge b and c 
M  b 
M  c 
8383e2c8d6092550fec13d3c888c037b3a68af15 Munge a and b 
M  a 
M  b 
d1363f4fba67d94999b269b51bdb50a8a68ba27a Baseline 
A  a 
A  b 
A  c

Los cambios en el archivo b son los que desea mantener, y que desea descartar todos los cambios a a y c. Una forma de hacerlo es con git filter-branch.

$ git checkout -b tmp topic 
Switched to a new branch 'tmp' 

$ git merge-base topic master 
d1363f4fba67d94999b269b51bdb50a8a68ba27a 

$ git filter-branch --tree-filter 'git checkout d1363f -- a c' master..tmp 
Rewrite 8383e2c8d6092550fec13d3c888c037b3a68af15 (1/3) 
Rewrite 99af942dbb922effcad8a72e96bec9ee9afcc437 (2/3) 
Rewrite 9bcfa7e946a92c226ad50ce430a9e4ae55b32490 (3/3) 
Ref 'refs/heads/tmp' was rewritten 

El filtro de árbol por encima de cheques a cabo las confirmaciones en el rango con nombre y restaura archivos a y c a los contenidos en la base “ fusión, ” es decir, el envío de datos a la que topic ramificado lejos de master.

Ahora tmp tiene todos topic ’ s cambia a b pero no cambia a ningún otro archivo.

$ git log --decorate --pretty=oneline --name-status tmp 
9ee7e2bd2f380cc338b0264686bcd6f071eb1087 (HEAD, tmp) Munge a, b, and c 
M  b 
226c22f150af1ddc1f9adc19f97fc4f220851ada Munge b and c 
M  b 
45e706f7b22c37ee2025ee0d04c651135e7b31cd Munge a and b 
M  b 
d1363f4fba67d94999b269b51bdb50a8a68ba27a Baseline 
A  a 
A  b 
A  c

Como medida de seguridad, git filter-branch almacena una copia de seguridad de su referencia inicial. Cuando ’ re satisfecho con los cambios y quiere eliminar la copia de seguridad tmp, ejecute

$ git update-ref -d refs/original/refs/heads/tmp
+3

excelente respuesta.Usar filter-branch es una herramienta tan increíble una vez que te envuelves con la cabeza. – ralphtheninja

+0

Hay muchas cosas buenas aquí todavía estoy digiriendo. 'log --name-status ' es genial. –

+0

Buh. Seguí todos los pasos de esta excelente respuesta, y todo transcurrió sin problemas hasta el final de la rama de filtro. "ADVERTENCIA: Ref 'refs/heads/tmp' no ha cambiado". Comprobando el historial, las modificaciones del archivo todavía están allí, y ninguno de los identificadores de confirmación ha cambiado (hasta donde sé), aunque git informó "reescribiéndolos" a todos. Hmm. –

0

Puede hacer los cambios para eliminar la funcionalidad como una nueva confirmación, luego crear un parche de la misma. Hacer su cambio de base/aplastamiento o lo que usted necesita para prepararse para fusionar de nuevo a maestro, a continuación, cuando se desea añadir la nueva funcionalidad de nuevo, se puede aplicar el parche en modo inverso con

git apply -R 

Nota tengo nunca hice esto ... pero debería funcionar en teoría, creo. :-)

0

por caja para una versión específica que puede hacer git checkout <sha1> <file> donde sha1 es el hash SHA1 única de esa versión desea que el archivo esté en.

+0

bien, eso es básicamente mi posición de reserva # 1 ... 1 –

Cuestiones relacionadas