Переписати історію git, щоб замінити всі CRLF на LF?


32

Я збираюся перенести приватне сховище Git з вікна win32 в Ubuntu. Хоча я можу зробити остаточне виконання dos2unix, але я хотів би переписати всю історію, тому деякі графічні інтерфейси Git відображатимуть log / diff правильно. Наприклад, gitg буде вставляти порожні рядки для кожної CR / LF.

Відповіді:


25

Ви можете використовувати git filter-branchдля цього за допомогою --tree-filterпараметра та вказівки --allдля галузі.

Ось приклад (запускається в порожній каталог із текстовим файлом типу Unix:

Підготовка:

$ 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

Команда:

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

Вихід:

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

Я настійно рекомендую робити повну резервну копію заздалегідь . Запустити це зі своєї машини Linux (якщо у вас не встановлена ​​хороша оболонка у вашому середовищі Windows), можливо, простіше.

Редагувати: коли перехід конвертувався вперше.


1
Дякую, ця публікація мені дуже допомогла. У мене було кілька файлів з пробілами в імені, трохи зміна оригінальної команди зафіксував його: git filter-branch --tree-filter 'git ls-files -z | xargs -0 dos2unix' -- --all. Прапори -zі -0повідомляти git ls-filesта xargsдрукувати та інтерпретувати nullяк кінець рядка.
Іван

Ще одна альтернатива команді dos2unix - покладатися на сам git:git filter-branch --prune-empty --tree-filter 'git add --renormalize .' -- --all
Вільмантас Баранаускас

6

Мета відповідь прибив право випуску на голові. На жаль, в Ubuntu Linux, починаючи з версії 10.04 (Lucid Lynx), команди dos2unix / unix2dos більше не доступні, і їх замінили fromdos / todos. Крім того, обидва набори команд перетворення мають різний ступінь незнання щодо існування бінарних файлів, тому, якщо ваше сховище містить зображення, шрифти тощо, вони будуть пошкоджені цим процесом.

Мені вдалося знайти вирішення проблеми з пошкодженням двійкових файлів, яка використовує команду Linux 'file' для правильного визначення та обробки лише текстових файлів, як показано нижче. Команда нижче використовує параметр --tag-name-filter для збереження існуючих тегів шляхом переміщення їх до нещодавно змінених комітетів. Також він використовує прапор --force для того, щоб команда працювала у випадку, якщо ви раніше запустили фільтр дерева у вашому сховищі.

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

І без будь-яких додаткових інструментів (як-от "fromdos", "dos2unix" тощо):

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) корисний аналог 'fromdos', 'dos2unix':

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

Можливо, корисний 'unix2dos':

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

Якщо ви абсолютно не знаєте, що ви робите, ви можете використовувати цю просту вбудовану команду для видалення "/ r" з усіх файлів у поточному каталозі ".":

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

1
Скоріше змініть \ r \ n на \ n, а не видаляючи лише \ r
xdevs23

Я думаю, що відповідне sedвиклик можна замінити коротшим:sed -n -e "s/\(.*\): .*text.*/\1/p"
dma_k
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.