Riscrivi la cronologia di git per sostituire tutto CRLF in LF?


32

Ho intenzione di trasferire un repository Git privato da Win32 Box a Ubuntu. Anche se posso eseguire un commit finale di dos2unix, ma mi piacerebbe riscrivere l'intera cronologia, quindi alcune GUI di Git visualizzeranno log / diff correttamente. Ad esempio, gitg inserirà righe vuote per ogni CR / LF.

Risposte:


25

Puoi usarlo git filter-branch, con l' --tree-filteropzione, e specificando --allper il ramo.

Ecco un esempio (avviato in una directory vuota con un file di testo di tipo Unix:

Preparazione:

$ 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

Il comando:

$ git filter-branch --tree-filter 'git ls-files -z | xargs -0 dos2unix' -- --all

Produzione:

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

Consiglio vivamente di fare prima un backup completo . Eseguirlo dalla tua macchina Linux (a meno che tu non abbia una buona shell impostata nel tuo ambiente Windows) è probabilmente più facile.

Modifica: la conversione è stata invertita la prima volta.


1
Grazie, questo post mi ha aiutato molto. Ho avuto un paio di file con spazi nel loro nome, un piccolo cambiamento al comando originale è stato risolto: git filter-branch --tree-filter 'git ls-files -z | xargs -0 dos2unix' -- --all. Bandiere -ze -0dire git ls-filese xargsstampare e interpretare nullcome fine della linea.
Ivan

Un'altra alternativa al comando dos2unix è affidarsi allo stesso git:git filter-branch --prune-empty --tree-filter 'git add --renormalize .' -- --all
Vilmantas Baranauskas il

6

La risposta di Mat ha risolto il problema proprio sulla testa. Sfortunatamente su Ubuntu Linux, a partire dalla versione 10.04 (Lucid Lynx), i comandi dos2unix / unix2dos non sono più disponibili e sono stati sostituiti da fromdos / todos. Inoltre, entrambi gli insiemi dei comandi di conversione hanno vari gradi di ignoranza sull'esistenza di file binari, quindi se il tuo repository contiene immagini, caratteri, ecc., Verranno danneggiati da questo processo.

Sono stato in grado di trovare una soluzione alternativa al problema di corruzione dei file binari che utilizza il comando 'file' di Linux per identificare ed elaborare correttamente solo i file di testo, come mostrato di seguito. Il comando seguente utilizza l'opzione --tag-name-filter per preservare i tag esistenti spostandoli nei commit appena modificati. Inoltre usa --force flag per assicurarsi che il comando funzionerà nel caso in cui tu abbia già eseguito il filtro ad albero sul tuo repository.

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

3

E senza strumenti aggiuntivi (come 'fromdos', 'dos2unix', ecc.):

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

Crossplatform (OS X, FreeBSD, Linux) utile analogo 'fromdos', 'dos2unix':

sed -i'' -e 's/'"$(printf '\015')"'$//'

Forse utile 'unix2dos':

sed -i '' -e 's|$|'"`printf '\015'`"'|' file.name

Se stai assolutamente assicurando cosa stai facendo, puoi usare questo semplice comando inline per eliminare "/ r" da tutti i file nella directory corrente ".":

find . -type f -exec sed -i'' -e 's/'"$(printf '\015')"'$//' {} \;

1
Piuttosto cambia \ r \ n in \ n invece di rimuovere solo \ r
xdevs23

Penso che l' sedinvocazione corrispondente possa essere sostituita con una più breve:sed -n -e "s/\(.*\): .*text.*/\1/p"
dma_k,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.