2010-02-19 15 views
9

Me gustaría dividir los módulos distribuidos con una aplicación más grande en submódulos separados y mantener la capacidad de extracción desde la parte superior.Uso repetido de git-filter-branch para reescribir nuevas confirmaciones

Esto es más complejo que Detach subdirectory into separate Git repository. No solo utilizo git-filter-branch una vez, sino que quiero mantener la capacidad de realizar cambios en la cadena ascendente una vez que lo he hecho (y upstream no).

Simplemente volviendo a ejecutar git-filter-branch en el historial completo desde el inicio ahora incluyendo nuevas confirmaciones no encontradas en mi historial reescrito no es una opción ya que hay cientos de módulos para los cuales tengo que hacer esto y el número de confirmaciones acercándose a 100.000.

Supongo que esto implica limitar la historia a solo las nuevas confirmaciones, reescribirlas y luego agregarlas después de las confirmaciones previamente rescritas, pero no estoy seguro de cómo hacerlo, y tal vez haya un mejor enfoque.

Sería bueno si las ramas y las etiquetas pudieran conservarse también, pero esto no es absolutamente necesario y si esto complica las cosas, preferiría perderlas.

+0

También me gustaría saber acerca de esto. Cada vez que obtengo un repositorio de dependencia, tengo que ejecutar filter-branch nuevamente para fusionar las actualizaciones en mi proyecto (no quiero fusionar todo el repositorio). –

+0

Me sorprendió que a nadie se le ocurrió una respuesta, después de todo parece un desafío interesante. Bueno, yo mismo pirateé algo, pero olvidé publicarlo aquí. Su interés me recordó: a continuación está mi solución. – tarsius

+2

¿Alguna vez has visto [* git subárbol *] (http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt)? Puede dividir un subárbol en una nueva rama y, con la opción '--rejoin', hacerlo de forma incremental. –

Respuesta

8

Por primera rebase hacer esto:

git checkout -b rebased master 
git filter-branch --some-filter 
git tag rebased-done master 

Y de "fusionar" comete más tarde:

# Create a tempory branch and rebase it's tail use 'rebase-done~' 
# and not 'rebase-done' because some filters (like --index-filter) 
# require this, others might not. 
git checkout -b rebased-tail master 
git filter-branch -f --some-filter -- rebased-done~..HEAD 

# Get the commit in branch 'rebased' corresponding to tag 'rebase-done' 
# (which tags a commit in 'master' not 'rebased'). Depending on your 
# situation you might have to determine this commit differently (in my 
# use case I am absolutely sure that there is never a commit with the 
# same author date - if that doesn't work you might want to compare 
# commit messages). 
start_time=$(git show --quiet --pretty=%at rebased-done) 
start_hash=$(
git log --reverse --pretty="%H %at" rebased_tail | 
while read hash time 
do 
    [ "$time" = "$start_time" ] && echo $hash && break 
done 
) 

# Finally apply the rebased commits. 
git checkout rebased 
git format-patch -k --stdout $start_hash..rebased-tail | git am -k 
git branch -D rebased-tail 
git tag -f rebased-done master 
Cuestiones relacionadas