Je vais transférer un dépôt Git privé d'une boîte win32 à Ubuntu. Bien que je puisse faire un dos2unix final commit, mais j'aimerais réécrire tout l'historique, afin qu'une certaine interface graphique Git affiche correctement les logs/diffs. Par exemple, gitg insérera des lignes vides pour chaque CR/LF.
Réponses
Trop de publicités?Vous pouvez utiliser git filter-branch
pour cela, avec le --tree-filter
et en spécifiant --all
pour la branche.
Voici un exemple (démarré dans un répertoire vide avec un fichier texte de type Unix :
Préparation :
$ hexdump -C testfile
00000000 61 0d 0a 62 0d 0a 63 0d 0a |a..b..c..|
00000009
$ git init
Initialized empty Git repository in /home/seigneur/tmp/a/.git/
$ git add testfile && git commit -m "dos file checked in"
[master (root-commit) df4970f] dos file checked in
1 files changed, 3 insertions(+), 0 deletions(-)
create mode 100644 testfile
La commande :
$ git filter-branch --tree-filter 'git ls-files -z | xargs -0 dos2unix' -- --all
Sortie :
Rewrite df4970f63e3196216d5986463f239e51eebb4014 (1/1)dos2unix: converting file testfile to Unix format ...
Ref 'refs/heads/master' was rewritten
$ hexdump -C testfile
00000000 61 0a 62 0a 63 0a |a.b.c.|
00000006
I fortement recommande de faire une sauvegarde complète au préalable . Exécuter cela à partir de votre machine Linux (à moins que vous n'ayez une bonne Shell configurée dans votre environnement Windows) est probablement plus facile.
Edit : la conversion a été inversée la première fois.
Mat's réponse a mis le doigt sur le problème. Malheureusement, sur Ubuntu Linux, à partir de la version 10.04 (Lucid Lynx), les commandes dos2unix/unix2dos ne sont plus disponibles, et ont été remplacées par fromdos/todos. De plus, les deux ensembles de commandes de conversion ignorent à des degrés divers l'existence des fichiers binaires, donc si votre dépôt contient des images, des polices, etc. ils seront corrompus par ce processus.
J'ai pu trouver une solution de contournement pour le problème de corruption des fichiers binaires qui utilise la commande 'file' de Linux pour identifier correctement et traiter uniquement les fichiers texte comme indiqué ci-dessous. La commande ci-dessous utilise l'option --tag-name-filter pour préserver les balises existantes en les déplaçant vers le commits nouvellement modifié. Elle utilise également le drapeau --force pour s'assurer que la commande fonctionnera dans le cas où vous avez déjà exécuté tree-filter sur votre référentiel.
git filter-branch --force --tree-filter 'git ls-files | xargs file | sed -n -e "/.*: .*text.*/s/\(.*\): .*/\1/p" | xargs fromdos' --tag-name-filter cat -- --all
Et sans aucun outil supplémentaire (comme 'fromdos', 'dos2unix', etc.) :
git filter-branch --force --tree-filter 'git ls-files | xargs file | sed -n -e "/.*: .*text.*/s/\(.*\): .*/\1/p" | xargs -0 sed -i"" -e "s/"$(printf "\015")"$//"' --tag-name-filter cat -- --all
Multiplateforme (OS X, FreeBSD, Linux) analogue utile 'fromdos', 'dos2unix' :
sed -i'' -e 's/'"$(printf '\015')"'$//'
Peut-être utile "unix2dos" :
sed -i '' -e 's|$|'"`printf '\015'`"'|' file.name
Si vous êtes absolument sûr de ce que vous faites, vous pouvez utiliser cette simple commande en ligne pour supprimer "/r" de tous les fichiers du répertoire courant "." :
find . -type f -exec sed -i'' -e 's/'"$(printf '\015')"'$//' {} \;
git filter-branch
présente plusieurs problèmes, principalement en termes de performances, car il est déprécié au profit de l'option git filter-repo
un projet séparé qui consiste en plusieurs scripts Python.
Pour convertir toutes les fins de lignes d'un référentiel, utilisez lint-history
lint-history dos2unix # CRLF => LF
lint-history unix2dos # LF => CRLF
Vous pouvez également effectuer d'autres tâches de linting, comme ajouter une nouvelle ligne à la fin du fichier.
lint-history sed -i '$a\'
Cela suppose que le lint-history
script est dans votre chemin et que git filter-repo
est installé correctement avec les liens symboliques et autres.
Si vous ne disposez pas d'un filter-repo
installation avec lint-history
mais seulement git-filter-repo
vous pouvez courir :
git filter-repo --blob-callback '
if not b"\0" in blob.data[0:8192]:
filename = ".git/info/tmpfile"
with open(filename, "wb") as f:
f.write(blob.data)
subprocess.check_call(["sed", "-i", "$a\\", filename])
with open(filename, "rb") as f:
blob.data = f.read()
os.remove(filename)
'