Исправление неработающих фиксаций all-on-all, если у автора autocrlf = true для Git - PullRequest
0 голосов
/ 10 мая 2018

Я получил ответвление с разорванными коммитами в целом из-за автоматического удаления Git CR, даже если была изменена только одна строка.

Сам наш репозиторий сломан: он был преобразован из SVN без удаления CR.

Так что любой Git-клиент без autocrlf = input исправляет окончание CR / LF автоматически.

Я исправил битый коммит с чудовищной серией, например (с core.autocrlf=false и добавлением / удалением последней строки в файле вразличать их):

git co broken
git co -b fixed HASH_OF_BROKEN
git -c core.autocrlf=false reset --hard

for f in broken.txt; do echo >>$f; unix2dos $f; done

git -c core.autocrlf=false add -u
git -c core.autocrlf=false ci --amend --no-edit

for f in broken.txt; do sed -i '$ d' $f; done

git -c core.autocrlf=false add -u
git -c core.autocrlf=false ci --amend --no-edit

git cherry-pick HASH_OF_NEXT_TO_BROKEN..broken
git push origin fixed

Есть ли простой способ исправить результат:

warning: CRLF will be replaced by LF in ...

1 Ответ

0 голосов
/ 10 мая 2018

Если цель состоит в том, чтобы иметь репозиторий с согласованными окончаниями строк, лучше переписать всю историю, используя git-filter-branch, чем работать с ним commit-by-commit. Допустим, вам нужны последовательные окончания строки DOS.

Напишите небольшую программу, которая может преобразовывать окончания строк всех файлов в дереве каталогов, кроме .git. Если у вас есть бинарные файлы, вам также придется их пропустить. Вот простой пример.

$ cat ~/bin/all2dos
#!/bin/sh

find . -path ./.git -prune -o -type f -print0 | xargs -0 unix2dos

Затем используйте это в tree-filter для преобразования концов строк каждого коммита во всей истории.

$ git filter-branch --tree-filter 'all2dos' -- --all

Хотя переписывание истории страшно, оно на некоторое время полностью обратимо. Git не переписывает коммиты, он пишет новые и использует их. Ваши исходные коммиты доступны через reflog , и вы можете переместить туда свои ветви.

$ git reflog
10eed67 (HEAD -> master) HEAD@{0}: filter-branch: rewrite
e8615e3 HEAD@{1}: commit (initial): Test files

Это говорит о том, что первоначальный коммит для master был e8615e3, а новый переписанный - 10eed67. Я могу переместить master обратно к оригиналу с помощью git reset --hard e8615e3.

Это приведет к появлению новых идентификаторов коммитов, поэтому любой, кто в данный момент работает над вашим проектом, должен будет сделать git pull --rebase=preserve для обновления (что они должны делать в любом случае), возможно, с --ignore-cr-at-eol, чтобы избежать конфликтов из-за изменения новой строки. Если у них есть открытые ветки, они будут на старом master; они должны git rebase master основать их на переписанной ветке master.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...