2012-03-21 19 views
13

Estoy tratando de usar el espejo git GCC, documentado here."No se puede determinar la información de SVN en sentido ascendente desde el historial de árbol de trabajo"

Hace algún tiempo, me clonó el repositorio git:

git clone git://gcc.gnu.org/git/gcc.git 

Agregado el material git-svn:

git svn init -Ttrunk --prefix=origin/ svn+ssh://gcc.gnu.org/svn/gcc 

Y luego git svn rebase y git svn dcommit etc. todo funcionó muy bien.

Algunos meses más tarde, he hecho varios trabajos de desarrollo en las ramas git locales, y he llegado a cometer más cambios a aguas arriba SVN:

  1. actualización de la miror git:

    $ git rebase 
    
  2. Asegúrese de que tengo la absoluta última desde SVN, pero no funciona:

    $ git svn rebase -v 
    Unable to determine upstream SVN information from working tree history 
    

¡De alguna manera he roto los metadatos! Además de lo anterior, creo que hice git svn fetch en algún momento, por error, pero eso no debería ser perjudicial, ¿o sí?

tanto, he intentado crear una rama fresca desde el espejo Git remoto:

$ git branch svntrunk remotes/origin/trunk 
$ git checkout svntrunk 
$ git svn rebase 
Unable to determine upstream SVN information from working tree history 

una búsqueda en Internet sugiere que la historia rama se ha desviado de alguna manera desde SVN, pero he comprobado git log y cada una tiene cometen correspondiente git-svn-id, lo que parece desmentir eso, ¿no?

Así que probé un nuevo clon de git: //gcc.gnu.org/git/gcc.git, y en ese repositorio git svn rebase funciona bien. ¿Cómo pueden los dos repos, en los que ambos han tenido git rebase de la misma fuente, tener un historial diferente? Presumiblemente no pueden, ¿y la diferencia está en los metadatos locales?

Ahora, no quiero destruir el repositorio en el que he estado trabajando (aunque podría) y exportar los parches a otro repositorio para cometer derrotas al punto de tener git-svn en primer lugar. Entonces, ¿cómo puedo repararlo?

Respuesta

12

Debería poder hacer esto con un injerto. El injerto está diseñado para ser utilizado para traer repositorios heredados, según entiendo. Te permite manualmente decir que algunos ref tienen un padre común.

Como se menciona en los comentarios, puede haber una solución más simple. Esto funcionaría si todo lo demás fallara.

Debería desplegar el repositorio git actual (ya sea con git o git-svn) y agregar su antiguo repositorio git-svn como control remoto. No van a estar relacionados, por lo gitk se verá así:

unrelated ancestry

tuve un incidente en el trabajo donde habíamos algunos hacer una copia del sistema de archivos en lugar de una copia SVN, por lo que algunos de mis nombres de rama alude a eso. Espero que todo tenga sentido de todos modos. Muy afortunado de que tenga todas estas imágenes e historias. ¿Cuáles son las posibilidades? Probablemente bastante bueno, git-svn se confunde fácilmente.

naming branches

La rama copied_from es donde se copian de. El graft_ref es donde se encontró esto. Habían agregado un grupo de archivos, cambiaban propiedades y luego modificaron algunos de los archivos. Fue un desastre.

La idea general es obtener el índice de la fuente original, pero el contenido del archivo para que coincida con las modificaciones. Así que comenzamos en la rama de ref, luego reiniciamos mixtos para obtener el índice.

$ git checkout graft_ref 
$ git checkout -b graft_parent 
$ git reset --mixed copied_from 

reset mixed

Si no hacer cambios entre las dos ramas cuando se rompe, entonces no debería tener que preocuparse acerca de este paso.

$ git commit -a -m "svn_branch changes made on svn_trunk filesystem copy" 

Ahora tenemos que hacer el injerto real. Recorté los hash aquí para facilitar la lectura.

$ git log -1 --pretty=format:%H graft_ref 
631d3c84e35de98236c3d36c08d14ec92f9c62ae 
$ git log -1 --pretty=format:%H graft_parent 
96a4e87b554e0030035d35ca3aac23e9d71962af 
$ echo "631d3... 96a4e8..." > .git/info/grafts 

grafted

que se ve cómo se puede esperar. Ahora solo tenemos que volver a establecer la base de los cambios en el árbol. Mis notas faltan para esto, pero creo que esto es lo que habría hecho, jeje.

$ git checkout svn_branch/master 
$ git checkout -b consolidate_changes 

consolidated

$ git rebase master 

rebase

Usted debe ser capaz de empujar estos cambios donde quiera. Los injertos no son rastreados por git sin embargo, por lo que la rama injertada (svn_branch/master y amigos) se romperá de nuevo. Es efectivamente un árbol muerto a menos que vuelva a hacer el injerto. Para git-svn, esto no es un gran problema, ya que solo se confirman los cambios y luego se vuelve a bajar la fuente como una copia limpia.

+0

+1, muy buena respuesta (de una de sus publicaciones en el blog, ¿quizás ...?). No estoy seguro si es directamente aplicable al problema que se está tratando (para eso, una solución más simple puede ser la más adecuada), pero como un procedimiento aplicable y utilizable para injertar cambios en repositorios en un estado inconsistente, lo apruebo completamente. :) – MrGomez

+1

@MrGomez Espero que haya una solución más simple. :)) Todo lo demás falla, estoy bastante seguro de que funcionaría bien. –

+0

Así que, esencialmente, comienzo desde un repositorio nuevo, inserto mis ramas de tema en la historia de git-svn no rota en el punto correcto a través de un injerto, y uso la rebase para hacer el injerto obsoleto. ¿Obtuve el extremo derecho del palo? – ams

3

Este es un escenario bastante común. Yo también me he encontrado con esto al intentar sincronizar mis repositorios Git más nuevos contra mi viejo almacén de datos respaldado por SVN.

El secreto es mantener el SVN en consonancia con la rama maestra de trabajo en Git. Los comandos comunes para hacerlo son, como mencionó, git svn rebase (para desenrollar los cambios y sincronizar de nuevo con SVN) y git reset --hard (para realizar una reversión a una revisión anterior cuando su índice interno está en un estado incoherente). Tomó una gran cantidad de búsqueda para enraizar este procedimiento para mí. (Tome una copia de seguridad antes de realizar cualquiera de estos). La razón por la que esto parece suceder es que Git se confunde mucho cuando gestiona dos o más historiales de cambios simultáneamente contra la misma rama de trabajo, que debe ser HEAD de manera predeterminada. Si algo cambia en el repositorio SVN ascendente y en los historiales de cambios descendentes que Git no puede conciliar, pierde su lugar y arroja el error que ha enumerado anteriormente.

Este problema se trata adicionalmente here. Como se mencionó en la respuesta principal, querrá descartar la posibilidad de que su versión de git necesite ser actualizada e intentar las correcciones que ellos recomendaron, también.

+0

Gracias, vi esa pregunta, pero como tengo la versión 1.7.0.4 de git no resolvió mi problema. Entonces, ¿piensas que si giro una rama hacia atrás de alguna manera, podría funcionar mágicamente de nuevo? – ams

+0

@ams ¡Lo hizo por mí, al menos! Me tomó cerca de tres días de consultas de Google infructuosas antes de encontrar esta solución para mi propio repositorio. En mi caso, he estado cometiendo cambios en Git de manera tridireccional: dentro de sus archivos de trabajo, desde un repositorio en sentido descendente y en SVN. No me gustó eso ni un poco. – MrGomez

+0

@ams Vea también estas sugerencias: http://stackoverflow.com/questions/3095611/git-svn-dcommit-error-unable-to-determine-upstream-svn-information – MrGomez

2

Lo más simple que podría funcionar es ejecutar git svn fetch. Si vuelve a adjuntar un repositorio de git existente a svn, obtendrá este error sin ningún motivo cuando git svn rebase. El problema subyacente es que git-svn hace suposiciones sobre el estado de su repositorio que no siempre se mantienen si no comenzó desde un clon svn limpio.

La siguiente opción es hacer una copia de seguridad del maestro git branch master-bkp. Y luego ejecuta git reset --hard <way-back>. Luego ejecute git svn rebase.

Solo si está trabajando en un git repo que no puede adjuntar de ninguna manera a svn de manera normal, puede intentar realizar un injerto. El injerto es inteligente y complejo, pero posible. También es difícil hacerlo bien, es fácil estropearlo, y muy que consume mucho tiempo. No recomendado como primera opción.

Cuestiones relacionadas