Objetivo
- Uso (inspirado en Smar , tomado de Exherbo )
git am
- Agregar historial de confirmación de archivos copiados / movidos
- De un directorio a otro
- O de un repositorio a otro
Limitación
- Las etiquetas y ramas no se guardan
- El historial se corta al cambiar el nombre del archivo de ruta (cambio de nombre del directorio)
Resumen
- Extraiga el historial en formato de correo electrónico utilizando
git log --pretty=email -p --reverse --full-index --binary
- Reorganice el árbol de archivos y actualice los nombres de archivo
- Agregar nueva historia usando
cat extracted-history | git am --committer-date-is-author-date
1. Extraiga el historial en formato de correo electrónico
Ejemplo: historia Extracto de file3
, file4
yfile5
my_repo
├── dirA
│ ├── file1
│ └── file2
├── dirB ^
│ ├── subdir | To be moved
│ │ ├── file3 | with history
│ │ └── file4 |
│ └── file5 v
└── dirC
├── file6
└── file7
Establecer / limpiar el destino
export historydir=/tmp/mail/dir # Absolute path
rm -rf "$historydir" # Caution when cleaning the folder
Extraiga el historial de cada archivo en formato de correo electrónico
cd my_repo/dirB
find -name .git -prune -o -type d -o -exec bash -c 'mkdir -p "$historydir/${0%/*}" && git log --pretty=email -p --stat --reverse --full-index --binary -- "$0" > "$historydir/$0"' {} ';'
Lamentablemente opción --follow
o --find-copies-harder
no se puede combinar con --reverse
. Es por eso que el historial se corta cuando se cambia el nombre del archivo (o cuando se cambia el nombre de un directorio principal).
Historial temporal en formato de correo electrónico:
/tmp/mail/dir
├── subdir
│ ├── file3
│ └── file4
└── file5
Dan Bonachea sugiere invertir los bucles del comando git log generation en este primer paso: en lugar de ejecutar git log una vez por archivo, ejecútelo exactamente una vez con una lista de archivos en la línea de comando y genere un único registro unificado. De esta manera, las confirmaciones que modifican varios archivos siguen siendo una única confirmación en el resultado, y todas las nuevas confirmaciones mantienen su orden relativo original. Tenga en cuenta que esto también requiere cambios en el segundo paso a continuación al reescribir nombres de archivo en el registro (ahora unificado).
2. Reorganice el árbol de archivos y actualice los nombres de archivo
Suponga que desea mover estos tres archivos en este otro repositorio (puede ser el mismo repositorio).
my_other_repo
├── dirF
│ ├── file55
│ └── file56
├── dirB # New tree
│ ├── dirB1 # from subdir
│ │ ├── file33 # from file3
│ │ └── file44 # from file4
│ └── dirB2 # new dir
│ └── file5 # from file5
└── dirH
└── file77
Por lo tanto, reorganice sus archivos:
cd /tmp/mail/dir
mkdir -p dirB/dirB1
mv subdir/file3 dirB/dirB1/file33
mv subdir/file4 dirB/dirB1/file44
mkdir -p dirB/dirB2
mv file5 dirB/dirB2
Tu historial temporal es ahora:
/tmp/mail/dir
└── dirB
├── dirB1
│ ├── file33
│ └── file44
└── dirB2
└── file5
Cambie también los nombres de archivo dentro del historial:
cd "$historydir"
find * -type f -exec bash -c 'sed "/^diff --git a\|^--- a\|^+++ b/s:\( [ab]\)/[^ ]*:\1/$0:g" -i "$0"' {} ';'
3. Aplicar nuevo historial
Su otro repositorio es:
my_other_repo
├── dirF
│ ├── file55
│ └── file56
└── dirH
└── file77
Aplicar confirmaciones de archivos de historial temporales:
cd my_other_repo
find "$historydir" -type f -exec cat {} + | git am --committer-date-is-author-date
--committer-date-is-author-date
conserva las marcas de tiempo de confirmación originales ( comentario de Dan Bonachea ).
Su otro repositorio es ahora:
my_other_repo
├── dirF
│ ├── file55
│ └── file56
├── dirB
│ ├── dirB1
│ │ ├── file33
│ │ └── file44
│ └── dirB2
│ └── file5
└── dirH
└── file77
Use git status
para ver la cantidad de confirmaciones listas para ser empujadas :-)
Truco adicional: verifique los archivos renombrados / movidos dentro de su repositorio
Para enumerar los archivos que han cambiado de nombre:
find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow {} ';' | grep '=>'
Más personalizaciones: puede completar el comando git log
con las opciones --find-copies-harder
o --reverse
. También puede eliminar las dos primeras columnas utilizando cut -f3-
y agrupando el patrón completo '{. * =>. *}'.
find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow --find-copies-harder --reverse {} ';' | cut -f3- | grep '{.* => .*}'
git mv
: stackoverflow.com/questions/1094269/whats-the-purpose-of-git-mv