Reescreve o histórico do git para substituir todo o CRLF por LF?

27

Vou transferir um repositório Git privado da caixa win32 para o Ubuntu. Embora eu possa fazer um commit final dos2unix, mas eu gostaria de reescrever todo o histórico, então alguma GUI do Git irá mostrar log / diff corretamente. Por exemplo, o gitg inserirá linhas vazias para cada CR / LF.

    
por Xiè Jìléi 07.06.2011 / 11:08

3 respostas

20

Você pode usar git filter-branch para isso, com a opção --tree-filter e especificando --all para o ramo.

Aqui está um exemplo (iniciado em um diretório vazio com um arquivo de texto do tipo Unix:

Preparação:

$ 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

O comando:

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

Saída:

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

Eu recomendo que você faça um backup completo antecipadamente . Executar isso a partir de sua máquina Linux (a menos que você tenha um bom shell configurado em seu ambiente Windows) é provavelmente mais fácil.

Edit: teve a conversão invertida na primeira vez.

    
por 07.06.2011 / 11:43
5

A resposta da Mat abordou a questão diretamente na cabeça. Infelizmente no Ubuntu Linux, a partir da versão 10.04 (Lucid Lynx), os comandos dos2unix / unix2dos não estão mais disponíveis e foram substituídos por fromdos / todos. Além disso, ambos os conjuntos de comandos de conversão têm vários graus de ignorância sobre a existência de arquivos binários, portanto, se o seu repositório contiver imagens, fontes, etc., eles serão corrompidos por esse processo.

Consegui encontrar uma solução alternativa para o problema de corrupção de arquivos binários que usa o comando 'file' do Linux para identificar e processar corretamente apenas os arquivos de texto, conforme mostrado abaixo. O comando abaixo usa a opção --tag-name-filter para preservar as tags existentes, movendo-as para os commits recém-corrigidos. Também usa o flag --force para garantir que o comando funcionará no caso de você ter executado o filtro de árvore em seu repositório antes.

git filter-branch --force --tree-filter 'git ls-files | xargs file | sed -n -e "/.*: .*text.*/s/\(.*\): .*//p" | xargs fromdos' --tag-name-filter cat -- --all
    
por 10.04.2012 / 17:20
3

E sem ferramentas adicionais (como 'fromdos', 'dos2unix', etc.):

git filter-branch --force --tree-filter 'git ls-files | xargs file | sed -n -e "/.*: .*text.*/s/\(.*\): .*//p" | xargs -0 sed -i"" -e "s/"$(printf "5")"$//"' --tag-name-filter cat -- --all

Crossplatform (OS X, FreeBSD, Linux) analógico útil 'fromdos', 'dos2unix':

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

Talvez seja útil "unix2dos":

sed -i '' -e 's|$|'"'printf '5''"'|' file.name

Se você está absolutamente certo o que está fazendo, você pode usar este comando inline simples para excluir "/ r" de todos os arquivos no diretório atual ".":

find . -type f -exec sed -i'' -e 's/'"$(printf '5')"'$//' {} \;
    
por 19.01.2015 / 12:39

Tags