2010-06-29 26 views
53

Digamos que tengo un acuerdo de recompra que incluye esta estructura de directorios:¿Cómo puedo mover un directorio en un repositorio de Git para todas las confirmaciones?

repo/ 
    blog/ 
    _posts/ 
     some-post.html 
    another-file.txt 

quiero mover _posts al nivel superior de la cesión temporal, por lo que la estructura se verá así:

repo/ 
    _posts/ 
    some-post.html 
    another-file.txt 

Este es lo suficientemente simple con git mv, pero quiero hacer que la historia parezca _postssiempre existía en la raíz del repositorio, y quiero poder obtener el historial completo de some-post.html a través de git log -- _posts/some-post.html. Me imagino que puedo usar magia con git filter-branch para lograr esto, pero no he descubierto exactamente cómo hacerlo. ¿Algunas ideas?

Respuesta

68

Usted puede utilizar el filtro subdirectorio para lograr este

$ git filter-branch --subdirectory-filter blog/ -- --all 

EDIT 1: Si no quiere hacer efectiva _posts la raíz, utilice un árbol-filtro en su lugar:

$ git filter-branch --tree-filter 'mv blog/_posts .' HEAD 

EDIT 2: Si blog/_posts no existía en algunas de las confirmaciones, lo anterior fallará. Use este lugar:

$ git filter-branch --tree-filter 'test -d blog/_posts && mv blog/_posts . || echo "Nothing to do"' HEAD 
+3

También es * mucho * más rápido de usar' --index-filter', ya que no tiene que ver el árbol. – Cascabel

+6

Yeah index -filter es más rápido, pero no funcionará porque los comandos que se muestran no afectan el índice. Solo tiene que hacer manipulaciones de índice si desea usar index-filter (por ejemplo, 'git rm -cached' en lugar de' rm') – sehe

+0

¿Puedo guardar etiquetas también? Parece que se han ido en mi caso. – Michael

31

Si bien la respuesta de Ramkumar es muy útil y que merezca la pena, no va a funcionar en muchas situaciones. Por ejemplo, cuando desea mover un directorio con otros subdirectorios a una nueva ubicación.

Para ello, la página de manual contiene el dominio perfecto:

git filter-branch --index-filter \ 
    'git ls-files -s | sed "s-\t\"*-&NEWSUBDIR/-" | 
    GIT_INDEX_FILE=$GIT_INDEX_FILE.new \ 
    git update-index --index-info && 
    mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD 

basta con sustituir NEWSUBDIR con su nuevo directorio deseado. También puede usar directorios anidados como dir1/dir2/dir3/- "

+9

Y dado que no es inmediatamente obvio al mirar ese comando o los errores resultantes, el \ t no funciona k en la versión de sed de os x. Hay muchas formas de evitarlo, pero quizás el más rápido es eliminar el \ t y reemplazarlo con una pestaña literal al escribir ctrl-v, . –

+2

¿Cómo se especifica la carpeta original o simplemente se mueve la rama completa? Cuando trato de ejecutar esto desde una carpeta que me gustaría mover, recibo 'Necesitas ejecutar este comando desde el nivel superior del árbol de trabajo' – joshcomley

+1

¿Qué hace el comando' sed'? Estoy intentando esto en Windows y necesito una alternativa. – Lucius

Cuestiones relacionadas