Objectif
- Utilisation (inspiré de Smar , emprunté à Exherbo )
git am
- Ajouter l'historique de validation des fichiers copiés / déplacés
- D'un répertoire à l'autre
- Ou d'un référentiel à un autre
Limitation
- Les balises et les branches ne sont pas conservées
- L'historique est coupé lors du changement de nom du fichier de chemin (renommer le répertoire)
Sommaire
- Extraire l'historique au format e-mail à l'aide
git log --pretty=email -p --reverse --full-index --binary
- Réorganiser l'arborescence des fichiers et mettre à jour les noms de fichiers
- Ajouter un nouvel historique à l'aide
cat extracted-history | git am --committer-date-is-author-date
1. Extraire l'historique au format e-mail
Exemple: l' histoire Extrait du file3
, file4
etfile5
my_repo
├── dirA
│ ├── file1
│ └── file2
├── dirB ^
│ ├── subdir | To be moved
│ │ ├── file3 | with history
│ │ └── file4 |
│ └── file5 v
└── dirC
├── file6
└── file7
Définir / nettoyer la destination
export historydir=/tmp/mail/dir # Absolute path
rm -rf "$historydir" # Caution when cleaning the folder
Extraire l'historique de chaque fichier au format email
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"' {} ';'
Malheureusement option --follow
ou --find-copies-harder
ne peut pas être combinée avec --reverse
. C'est pourquoi l'historique est coupé lorsque le fichier est renommé (ou lorsqu'un répertoire parent est renommé).
Historique temporaire au format e-mail:
/tmp/mail/dir
├── subdir
│ ├── file3
│ └── file4
└── file5
Dan Bonachea suggère d'inverser les boucles de la commande de génération de journaux git dans cette première étape: plutôt que d'exécuter git log une fois par fichier, exécutez-le exactement une fois avec une liste de fichiers sur la ligne de commande et générez un seul journal unifié. De cette façon, les validations qui modifient plusieurs fichiers restent une seule validation dans le résultat, et toutes les nouvelles validations conservent leur ordre relatif d'origine. Notez que cela nécessite également des modifications à la deuxième étape ci-dessous lors de la réécriture des noms de fichiers dans le journal (désormais unifié).
2. Réorganisez l'arborescence des fichiers et mettez à jour les noms de fichiers
Supposons que vous souhaitiez déplacer ces trois fichiers dans cet autre référentiel (il peut s'agir du même référentiel).
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
Réorganisez donc vos fichiers:
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
Votre historique temporaire est maintenant:
/tmp/mail/dir
└── dirB
├── dirB1
│ ├── file33
│ └── file44
└── dirB2
└── file5
Modifiez également les noms de fichiers dans l'historique:
cd "$historydir"
find * -type f -exec bash -c 'sed "/^diff --git a\|^--- a\|^+++ b/s:\( [ab]\)/[^ ]*:\1/$0:g" -i "$0"' {} ';'
3. Appliquer une nouvelle histoire
Votre autre dépôt est:
my_other_repo
├── dirF
│ ├── file55
│ └── file56
└── dirH
└── file77
Appliquer des validations à partir de fichiers d'historique temporaires:
cd my_other_repo
find "$historydir" -type f -exec cat {} + | git am --committer-date-is-author-date
--committer-date-is-author-date
conserve les horodatages de validation d'origine (commentaire de Dan Bonachea ).
Votre autre dépôt est maintenant:
my_other_repo
├── dirF
│ ├── file55
│ └── file56
├── dirB
│ ├── dirB1
│ │ ├── file33
│ │ └── file44
│ └── dirB2
│ └── file5
└── dirH
└── file77
Utilisez git status
pour voir le nombre de commits prêts à être poussés :-)
Astuce supplémentaire: vérifiez les fichiers renommés / déplacés dans votre référentiel
Pour répertorier les fichiers renommés:
find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow {} ';' | grep '=>'
Plus de personnalisations: vous pouvez exécuter la commande à l' git log
aide des options --find-copies-harder
ou --reverse
. Vous pouvez également supprimer les deux premières colonnes en utilisant cut -f3-
et en accueillant le motif complet '{. * =>. *}'.
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