2012-02-01 13 views
9

que tienen un repositorio sencillo con historia lineal de confirmaciones, como:¿Cómo volver a aplicar confirmaciones en la parte superior de una rama no relacionada?

[A] -> [B] -> [C] -> [D] -> [E] ... 

Básicamente necesito para eliminar comete A y B, así que pensé que crearía un nuevo repositorio y me gustaría conseguir algo como:

[X] -> [C] -> [D] -> [E] ... 

Así que he creado un nuevo repositorio, creada manualmente cometer X que toma almacena la información relevante de a y B y ahora necesitan un comando que traerá compromete C, D, e, etc. desde el repositorio original y pondrá en la parte superior de mi nueva confirmación X.

¿Cómo hacer eso?

Editar: Dos problemas que tengo con el método de cereza-escoge sugerido son:

  1. Transferido commits perdieron sus fechas. ¿Hay alguna forma de preservar las fechas de compromiso?
  2. Cuando obtuve el maestro del repositorio original (y ese maestro remoto no tiene ningún compromiso en común con el nuevo repositorio), tengo problemas para eliminar esos commits recuperados. Cuando hago git branch -D myoriginalrepo/master, dice que no existe tal rama, mientras que puedo ver claramente que se comprometan en mi herramienta GUI.
+0

Creo que deberías mirar a git cherry-pick. –

+0

¿Alguna vez descubrió cómo evitar que las fechas cambien? – thinsoldier

Respuesta

15

No estoy seguro de por qué es necesario la fecha de comprometerse a permanecer igual, pero aquí va:

git rebase B E --onto X --committer-date-is-author-date 

Si B..E no están en el mismo repositorio que X (como pueden ser if you create your fresh start in-place), tendrá que buscarlos en primer lugar:

git fetch <path_to_old_repos> 

Por supuesto, B, E y X aquí significa cometer sus ids si no lo ha hecho etiquetado/ellas ramificado.

También puede hacer algo similar (aunque la fecha no cometer será preservado) por rebase de A en su repositorio original y aplastando B en él:

git rebase -i `A` 

# change "pick b" to "squash b" 

Usted obtendrá la oportunidad de cambiar cometer mensaje en que punto podría hacerlo X 's.

+0

Esto suena como el mejor enfoque hasta ahora, sin embargo, tengo un problema al trabajar con commits obtenidos usando 'git fetch'. ¿Cómo los hago referencia? No están en ninguna rama, ¿verdad? – Borek

+2

'git fetch' creará para usted una rama de conveniencia llamada' FETCH_HEAD' que apuntará a lo que sea 'HEAD' (es decir, lo que sea que haya sido prestado) en su antiguo repositorio. Además, las identificaciones de compromiso serán exactamente las mismas en todos los repositorios, por lo que puede ir a 'gitlog ', por ejemplo. También puede elegir crear una rama correspondiente durante la recuperación: 'git fetch their_branch: my_branch'. – antak

3

Puede usar git cherry-pick. En su caso:

git cherry-pick C D E 

mientras que X es su cabeza debería hacerlo.

+0

Gracias, pensé que el rebase sería mi amigo, pero el comando cherry es el que debes usar. Espero poder especificar commits como "C .." ya que tengo cientos de ellos en el repositorio original. – Borek

+0

Si tiene lotes, hay algunas opciones de recolección que le permitirán agruparlos. Verifique la documentación. Rebase también funcionará: si lo usa en el repositorio original para reemplazar A & B por X, obtendrá el mismo resultado que está buscando. –

+1

La selección de cereza parece perder la información de fecha de compromiso (probablemente crea una nueva confirmación), ¿el problema será el mismo con la rebase? Eso sería bastante malo, necesito mantener las fechas de compromiso. – Borek

1

Dice que creó "un nuevo repositorio". Probablemente no quisiste hacer eso. Si por algún motivo los commits A y B deben dejar de existir (por ejemplo, por razones legales o porque accidentalmente has ingresado tu número de tarjeta de crédito y tu receta secreta de haggis) en tu repositorio, necesitarás leer acerca de cómo eliminar permanentemente un commit . Pero primero arreglemos el resto del árbol.

Pruebe algo como

git checkout -b freshstart A 
# modify the state of the system until it reflects your desired new beginning X 
git commit --amend 
git cherry-pick C D E 

Ahora usted tiene una FreshStart llamado rama que tiene su nuevo comienzo X y se compromete C, D y E, suponiendo que se fusionan muy bien en X.

+0

Correcto, A y B deben eliminarse por completo del historial, por lo que crear un repositorio nuevo parece una buena forma de comenzar. Creé una X de estado, busqué la rama remota original-repo/master y ahora puedo seleccionar las confirmaciones desde la rama principal. Dos problemas que tengo: 1) Los commits de Cherry Pick pierden su fecha 2) No puedo hacer referencia a la rama original/repo/master (ya que no tiene ningún padre común con maestro local y se encuentra al lado de mi 'maestro', supongo). No puedo borrar esa rama temporal de la que elegí. – Borek

+1

No necesita un nuevo repositorio para eliminar por completo las confirmaciones. Puede usar rebase, por ejemplo, para eliminar commits. Lo único es que si tienes razones legales o algo para eliminar confirmaciones, debes asegurarte de que los objetos que se convierten en basura cuando quitas las confirmaciones se limpien, de modo que no estén todavía disponibles para las personas que saben lo que hacen. Y, por supuesto, debe acudir a todos los clones del repositorio en todas partes y hacer lo mismo o no estar a la altura de la obligación legal. – bames53

+0

A y X no tienen ninguna confirmación previa en común, ¿es posible crear una rama que no tenga un padre en mi repositorio original? – Borek

Cuestiones relacionadas