Ryan
No conozco muy bien a git. :-/
Fondo
Tengo dos repositorios de documentos basados en git no relacionados que me gustaría combinar en un solo repositorio. Me gustaría conservar las marcas de tiempo originales (que datan de 2005) y los historiales de archivos individuales. Los dos repositorios no contienen ramas, ni carpetas, y no hay superposición en términos de nombres de archivos.
En ASCII-land, se ve así:
REPO A |-------------------------|
REPO B |===============|
Donde la superposición denota tiempo.
Meta
Mi objetivo es “cerrar” las marcas de tiempo superpuestas para que los dos repositorios se vean como una historia única e ininterrumpida:
REPO A+B |-------------------==--=---============|
lo que he probado
Nuevamente, no conozco muy bien a git, así que podría haber estropeado algo.
Primero traté de agregar el repositorio más nuevo y más pequeño como control remoto para el repositorio más grande y antiguo, recuperar los cambios y confirmar el resultado. Terminé con todos los nuevos cambios del repositorio agrupados en una rama después del repositorio anterior:
MERGE |------------------------- -|
\===============/
Luego intenté rebasar (con --committer-date-is-author-date
), que pensé que funcionaría, pero en su lugar termino con un largo historial de confirmaciones que simplemente apila los dos repositorios uno encima del otro.
REBASE |-------------------------===============|
No he podido encontrar una manera de “reproducir” la historia combinada. Realmente esperaba que la rebase fuera la respuesta.
Respuestas que he mirado
- Combinar dos repositorios de Git sin interrumpir el historial de archivos (#1)
- git rebase sin cambiar las marcas de tiempo de confirmación (n. ° 2 anterior, no “cremallera” las historias)
- Cómo combinar dos repositorios Git separados no relacionados en uno con una sola línea de tiempo de historial
- combinar repositorios git no relacionados que retienen el historial/ramas
Si bien la respuesta de @codeWizard fue útil, ese enfoque no retuvo las marcas de tiempo como yo quería. Sin embargo, me llevó a una madriguera de conejo que me ayudó a encontrar una solución…
-
Crear un nuevo repositorio en blanco
git init
-
Agregue y obtenga los repositorios antiguos como remotos
git remote add -f oldRepoA ../oldRepoA git remote add -f oldRepoB ../oldRepoB
-
Exporte el historial de confirmación combinado por marca de tiempo y hash, canalice la salida a
sort
descartar las marcas de tiempo a través decut
y luego canalice la lista de hashes ordenados cronológicamente axargs
que ejecuta un script de shell para exportar un parche para cada hash individual y luego aplica inmediatamente el parche al nuevo repositorio.git log --all --oneline --format="%at %H" | sort | cut -c12- | xargs -I {} sh -c 'git format-patch -1 {} --stdout | git am --committer-date-is-author-date'
El --committer-date-is-author-date
es clave para mantener las marcas de tiempo originales. Puede haber una mejor manera de hacer esto, ¡pero funciona lo suficientemente bien para mi caso de uso!
-
¿Qué pasó con la sugerencia de @CodeWizard? ¿Cada elección selectiva establece la fecha de la confirmación en la fecha y hora actual? Estoy tratando de hacer algo similar a ti, pero los repositorios son similares, así que no sé si funcionará.
– Noble Uplift
08/08/2016 a las 21:54
-
Sí, esto eventualmente resulta en
X: already exists in working directory Patch failed at 0001
. ¿Funcionaría esto para un repositorio con múltiples ramas comomaster
ydevelop
?– Noble Uplift
9 de agosto de 2016 a las 14:59
Tendrás que escribir un script que lo haga.
Cómo hacerlo
-
obtenga una lista de todas sus marcas de tiempo de confirmaciones por rama
# print out the commits time stamp & sha-1 of each commit # do it for all your branches git log --oneline --format="%at %H"
-
Combine las 2 listas juntas y ordénelas por la marca de tiempo usando cualquier herramienta de clasificación (sublime, unix sort, etc.)
-
Revisa la nueva rama comenzando con la primera confirmación que tienes en tus archivos
git checkout <first commit id>
-
Crear nueva rama a partir de este compromiso
git checkout -b <new_branch_name>
-
Recorra todas las demás confirmaciones y use la opción de selección para llevarlas a su rama (secuencia de comandos)
git cherry-pick <next commit id>
-
¿Funcionaría esto para dos repositorios que tienen la misma estructura de archivos, pero uno es una instantánea bifurcada del otro en una fecha posterior? Estoy tratando de abordar este problema aquí.
– Noble Uplift
09/08/2016 a las 20:44
Si usa el unir acercarse,
git log --date-order
mostrará las confirmaciones ordenadas por su tiempo de confirmación como lo está solicitando, ygit log --date-order --graph
mostrará la rama del árbol también.– David Parsson
9 de junio de 2016 a las 11:43