Git: copia el historial del archivo de un repositorio a otro [duplicate]

5 minutos de lectura

Git copia el historial del archivo de un repositorio a
Pablo Varghese

Tengo dos repositorios de git, digamos A y B, ambos contienen un archivo llamado file1.cc. ¿Es posible fusionar/copiar el historial de file1.cc en el repositorio A a file1.cc en el repositorio B?

El problema es que ya hemos movido los archivos del repositorio A al repositorio B y el historial de todos los archivos se ha perdido. pero ahora algunos de los desarrolladores ya comenzaron a trabajar en el repositorio B e impulsaron sus cambios. Así que ahora quiero fusionar/copiar el historial de algunos archivos del repositorio A al repositorio B y que solo se aplican a algunos de los archivos. ¿Es posible hacerlo? ¿O el historial de los archivos una vez perdidos se pierde para siempre?

Por favor ayuda. Gracias por adelantado.

  • ¿Puedes explicar por qué quieres hacer esto?

    – Tim Biegeleisen

    27 jun.

Git copia el historial del archivo de un repositorio a
Marcos Adelsberger

Se puede hacer, pero puede que no sea fácil. Pero lo primero es lo primero: no se puede “mover el historial de un archivo”. Solo hay confirmaciones móviles, por lo que si desea confirmaciones que representen el historial de un subconjunto de archivos, crear esas confirmaciones es el primer desafío.

Lo más sencillo sería transferir todo historia. (De hecho, si sucede que hiciste Repo B como un clon superficial de Repo A, entonces podrías deshacerlo y listo. Pero supongo que no fue así como creaste Repo B…)

De todos modos, dado que se está moviendo de Repo A a Repo B, tal vez haya algún historial que desee eliminar específicamente. Ese es potencialmente un tema completo en sí mismo, pero supongamos que realmente solo desea el historial de algunos archivos.

En el caso especial en el que todos los archivos que desea (y ningún otro) están en un subdirectorio y desea (o, al menos, puede aceptar) mover esos archivos al directorio raíz del repositorio, puede usar filter-branch con el --subdirectory-filter.

Más generalmente, si asumimos caminos no debería cambiar y que los archivos que desea podrían estar en cualquier parte del árbol, entonces podría usar filter-branch con un --index-filter.

git filter-branch --index-filter 'git rm --cached --ignore-unmatch each file or *glob* you do NOT want' --prune-empty -- all

Eso podría llevar un tiempo si el repositorio tuviera muchas confirmaciones. Si la lista de archivos a rm no es trivial, es posible que desee poner múltiples git rm comandos en un script de shell y usarlo como el --index-filter argumento en lugar de alinearlo como se muestra arriba.

Bueno, de una forma u otra, espero que tengas un historial que te gustaría injertar en Repo B.

cd repo-b
git remote add repo-a path/to/repo-a
git fetch repo-a

Ahora tienes en Repo B:

... A -- B <--(repo-a/master)
  
   (repo-a/other-branches-maybe)

B' -- C -- D (master)(origin/master)

Así que estoy haciendo una suposición aquí, que el TREE de la última master commit en Repo A – aquel a partir del cual se creó nuestra reescritura de historial B – o al menos una parte de ese árbol, se importó como la confirmación raíz en Repo B.

Ahora tiene tres opciones: re-parentalizar, reorganizar o reemplazar

Dado que asumo que el estado de la historia reciente es más importante que el estado de la historia anterior, y que la historia anterior solo se agrega como referencia, lo más seguro sería volver a crear un padre C a B. (Puede elegir volver a ser padre B' a A en cambio, pero asumo que eso no hace mucha diferencia…)

Así que dibujando desde el filter-branch documentos en https://git-scm.com/docs/git-filter-branch tú podrías

# be sure you're on master
echo "$commit-id $graft-id" >> .git/info/grafts
git filter-branch $graft-id..HEAD

donde $commit-id es el SHA para B y $graft-id es el SHA para C

Un rebase puede ser un poco más simple (asumiendo un cierto nivel de consistencia entre las historias) pero presenta la posibilidad de que termines modificando el árbol en D. Si decide intentar una rebase, sería

git rebase --onto repo-A/master B' master

donde B' es el SHA ID de la confirmación raíz de Repo B. (Alternativamente

git rebase --interactive --onto repo-A/master --root master

y luego suelte la entrada para B'.)

Cualquiera de estas opciones reescribirá las confirmaciones C y D. (Aunque la reeducación asegura la TREE permanece sin cambios, las confirmaciones aún se reemplazan). Sus desarrolladores tendrían que tratar esto como una reorganización ascendente (consulte la git rebase documentación en “recuperación de rebase ascendente”). Para mitigar esto, generalmente recomiendo hacer una transición coordinada en la que los desarrolladores verifiquen todo lo que tienen, descarten sus clones, luego reescriban y ellos vuelvan a clonar desde el nuevo repositorio.

Si desea evitar la reescritura, puede utilizar la tercera opción: git replace. Se sabe que esto tiene algunas peculiaridades y requiere que cada clon se configure correctamente para “ver” el historial empalmado.

Entonces, para respaldar esto, solo etiquetarías B (y tal vez también B'):

git tag old-history repo-a/master
git tag new-root B'

(donde B' es el ID de valor SHA adecuado o una expresión equivalente).

Cuando alguien clone el repositorio, solo verá el nuevo historial, pero podrá decir

git replace new-root old-history

y esto cubrirá la ruptura en la historia.

Una vez que haya hecho su reparent, rebase o replace, puede eliminar el repo-a remoto.

  • Esto es de hecho lo que estoy tratando de lograr. Muchas gracias.

    –Paul Varghese

    27 jun.

  • También intenté escribir un script usando gitpython pero me está tomando algo de tiempo :(.

    –Paul Varghese

    27 jun.

  • Esto funcionó muy bien para mí, pero una cosa que me desconcertó al principio es que el único tic en tu --index-filter ejemplo se ven como marcas de retroceso (`) en mi navegador. Me tomó algunos intentos darme cuenta de que deberían ser marcas individuales (‘) en su lugar.

    – rbhitchcock

    01 ago. 17 en 13:55

  • Lo siento, ese fue mi error; cada vez que tengo una publicación con muchos tictacs simples y tictacs inversos, aparecen errores tipográficos

    –Mark Adelsberger

    07 ago. 17 en 15:50

.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad