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


32

Vou transferir um repositório Git privado da caixa win32 para o Ubuntu. Embora eu possa fazer uma confirmação final do dos2unix, mas gostaria de reescrever toda a história, portanto, algumas GUI do Git exibirão log / diff corretamente. Por exemplo, o gitg irá inserir linhas vazias para cada CR / LF.

Respostas:


25

Você pode usar git filter-branchpara isso, com a --tree-filteropção e especificar --alla ramificação.

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 fortemente recomendo fazer um backup completo de antemão . Executar isso na sua máquina Linux (a menos que você tenha um bom shell configurado no ambiente Windows) é provavelmente mais fácil.

Editar: teve a conversão revertida na primeira vez.


1
Obrigado, este post me ajudou muito. Eu tive alguns arquivos com espaços em seu nome, uma pequena mudança de comando original fixa-lo: git filter-branch --tree-filter 'git ls-files -z | xargs -0 dos2unix' -- --all. Sinaliza -ze -0informa git ls-filese xargsimprime e interpreta nullcomo fim de linha.
1013 Ivan Ivan

Outra alternativa ao comando dos2unix é confiar no próprio git:git filter-branch --prune-empty --tree-filter 'git add --renormalize .' -- --all
Vilmantas Baranauskas

6

A resposta de Mat acertou a questão 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, os dois conjuntos de comandos de conversão têm vários graus de ignorância quanto à 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 arquivo binário que usa o comando 'file' do Linux para identificar e processar corretamente apenas arquivos de texto, como mostrado abaixo. O comando abaixo usa a opção --tag-name-filter para preservar as tags existentes, movendo-as para as confirmações recém-alteradas. Também usa o sinalizador --force para garantir que o comando funcione no caso de você ter executado o filtro em árvore no seu repositório antes.

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 sem nenhuma ferramenta adicional (como '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

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

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

Talvez 'unix2dos' útil:

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

Se você tem certeza absoluta do que está fazendo, pode usar este comando embutido simples para excluir "/ r" de todos os arquivos no diretório atual ".":

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

1
Em vez disso mudar \ r \ n \ n em vez de remover \ única r
xdevs23

Eu acho que correspondente sedinvocação pode ser substituído por um mais curto:sed -n -e "s/\(.*\): .*text.*/\1/p"
dma_k
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.