2011-07-09 12 views
8

Tengo un repositorio y me gustaría separar uno de sus directorios en un nuevo repositorio. This es un lugar perfecto para comenzar, sin embargo, hay una advertencia: el directorio que quiero separar se renombró en algún momento. Y si sigo la solución de esa publicación con el nuevo nombre del directorio, entonces parece que estoy perdiendo el historial antes de cambiar el nombre. ¿Alguna idea de un ajuste para que funcione en esta situación?Separar subdirectorio (que se renombró!) En un nuevo repositorio

Respuesta

9

git filter-branch puede operar en rangos de confirmaciones; así que lo que podemos hacer es filtrar el 'antes' y 'después' de forma separada, y el uso de injertos para virar juntos:

git branch rename $COMMIT_ID_OF_RENAME 
git branch pre-rename rename~ 
## First filter all commits up to rename, but not rename itself 
git filter-branch --subdirectory-filter $OLDNAME pre-rename 
## Add a graft, so our rename rev comes after the processed pre-rename revs 
echo `git rev-parse rename` `git rev-parse pre-rename` >> .git/info/grafts 
## The first filter-branch left a refs backup directory. Move it away so the 
## next filter-branch doesn't complain 
mv .git/refs/original .git/refs/original0 
## Now filter the rest 
git filter-branch --subdirectory-filter $NEWNAME master ^pre-rename 
## The graft is now baked into the branch, so we don't need it anymore 
rm .git/info/grafts 

Esto es ligeramente más complejo si necesita filtrar múltiples ramas o etiquetas; las ramas antes del cambio de nombre pueden incluirse en la primera rama de filtro, mientras que las posteriores deben incluirse antes del ^rename en la segunda rama de filtro.

Otra opción sería agregar un filtro de índice (o filtro de árbol) que verifique tanto los directorios, antiguos como los nuevos, y conserva el que esté presente.

Ya que no han proporcionado un repositorio de pruebas, aquí es un script cordura comprobación rápida para este escenario:

#!/bin/bash 

set -u 
set -e 
set -x 

rm -rf .git x y foo 

git init 
mkdir x 
echo initial > x/foo 
git add x/foo 
git commit -m 'test commit 1' 

echo tc2 >> x/foo 
git commit -a -m 'test commit 2' 

mv x y 
git rm x/foo 
git add y/foo 
git commit -a -m 'test rename' 

git branch rename HEAD 

echo post rename >> y/foo 
git commit -a -m 'test post rename' 

git branch pre-rename rename~ 

git filter-branch --subdirectory-filter x pre-rename 
echo `git rev-parse rename` `git rev-parse pre-rename` >> .git/info/grafts 

mv .git/refs/original .git/refs/original0 

git filter-branch --subdirectory-filter y master ^pre-rename 

rm .git/info/grafts 

git log -u 

Si este procedimiento no funciona para usted, entonces no es probable que sea algo más extraño acerca de su historial de repositorio que no ha descrito, como otro cambio de nombre escondido en el historial.

+0

Hmm, he intentado el método con injertos (que no sé nada de) y no funcionó para mí. Después de procesar uno de los commit "antes" se vació, los archivos de otro se movieron a la raíz del repositorio; No puedo encontrarle sentido. Estaba pensando antes de usar un filtro de árbol pero no tengo ninguna experiencia con eso; te importaría elaborarme muéstrame algunos consejos? – akoprowski

+0

¿Estás seguro de que la confirmación previa estaba usando el subdirector correcto? ¿Puedes publicar tu git repo en alguna parte? – bdonlan

+0

Sí, el cambio de nombre estaba en la confirmación que hizo el cambio de nombre y pre-cambio de nombre justo antes. El repositorio es enorme y parcialmente privado, así que no puedo publicarlo en ninguna parte: | – akoprowski

Cuestiones relacionadas