Показаны сообщения с ярлыком git. Показать все сообщения
Показаны сообщения с ярлыком git. Показать все сообщения

понедельник, 7 мая 2012 г.

Кроссплатформная проблема длинных имен файлов (Crossplatform long file name problem)


Хотя я демонстрирую ошибку на примере работы с системами контроля версий для MacOsX и Windows - это проблема более глобальная и поймать её вы можете в любой другой комбинации софта (да хоть в той же Samba).
Используемый подход решения проблемы наверняка не единственный, но, при этом, довольно универсален.

Различные файловые системы по разному хранят информацию об имени файла.
Из-за чего возникают коллизии если разработка ведётся многими людьми и у всех разные ОС.
В моём случае получилось так, что другой разработчик закоммитил в репозиторий файл длиной 180 русских букв.

$ echo "яяяяяяяяя яя яяяя яя яяяяяяяяяя яяяяяяяяя я яяяяяя я яяя яяяяяяяяя яяяяяяяяяяяяя яяяяяяяя я яяяяяяяяяяяяяяяяяя яяяяяя яя яяяяяя яяяяяяяяяяяяя яяяяяяяя яяяяя яяяяяя я яяя яяяяя яяя" | wc -m

180


Но

$ echo "яяяяяяяяя яя яяяя яя яяяяяяяяяя яяяяяяяяя я яяяяяя я яяя яяяяяяяяя яяяяяяяяяяяяя яяяяяяяя я яяяяяяяяяяяяяяяяяя яяяяяя яя яяяяяя яяяяяяяяяяяяя яяяяяяяя яяяяя яяяяяя я яяя яяяяя яяя" | wc -c

334

Русские буквы занимают два байта вместо одного.
При попытке создать такой файл под MacOsX на диске со стандартной файловой системой HFS+

$ touch "яяяяяяяяя яя яяяя яя яяяяяяяяяя яяяяяяяяя я яяяяяя я яяя яяяяяяяяя яяяяяяяяяяяяя яяяяяяяя я яяяяяяяяяяяяяяяяяя яяяяяя яя яяяяяя яяяяяяяяяяяяя яяяяяяяя яяяяя яяяяяя я яяя яяяяя яяя"

Получим странное

$ ls я*

яяяяяяяяя яя яяяя яя яяяяяяяяяя яяяяяяяяя я яяяяяя я яяя яяяяяяяяя яяяяяяяяяяяяя яяяяяяяя я яяяяяяяяяяяяяяяяяя яяяяяя яя яяяяяя яяяя#299CD031

Несмотря на заявляемые 255 знаков в кодировке UTF-16 (точно также в NTFS).
А если такой файл попробовать отредактировать, например с помощью vim, то после сохранения и выхода
:wq
файл исчезает.

Кстати, несмотря на то, что некоторые ФС поддерживают ещё более длинные имена, штатные утилиты linux, по всей вероятности, всё равно оперируют байтами и поэтому комманда touch мне стабильно выдавала ошибку: “File name too long”
Я, например, пробовал ReiserfFS под Ubuntu 12.04 LTS.

Возвращаясь к MacOs. Именно эту ошибку я поймал при попытке получить последние изменения из репозитория.
$ git svn rebase
First, rewinding head to replay your work on top of it...
error: cannot stat '$73_chars_4_deep_levels_path_with_spaces/$180_chars_file_name_with_spaces_too': File name too long
error: cannot stat '$73_chars_4_deep_levels_path_with_spaces/$180_chars_file_name_with_spaces_too': File name too long
error: cannot stat '$73_chars_4_deep_levels_path_with_spaces/$180_chars_file_name_with_spaces_too': File name too long
could not detach HEAD
rebase refs/remotes/git-svn: command returned error: 1

Первой моей идеей стало установить Windows внутри VirtualBox и там настроить Cygwin, т.к. в этой экосистеме файлы с длинными именами чувствуют себя вольготно.
Но, всё-таки, ОС внутри виртуальной машины - это довольно тяжелая штука в плане потребления ресурсов.
К тому же, Cygwin/MSysGit имеют и другие проблемы, с которыми приходится периодически бороться.

И, вот, после неудачи с Windows и Ubuntu, ко мне пришла идея попробовать создать образ диска с подходящей ФС средствами MacOS.

Хотя Linux и позволяет создавать и монтировать образы дисков даже более гибко, но надо что-то в нём докручивать, либо чтобы ядро поддерживало длинные уникодные имена, либо выставлять однобайтную локаль и на лету конвертировать файлы с помощью чего-то вроде iconv или средствами самого гита.

В комплекте с макосью идёт инструмент DiskUtility.
Где я для начала попробовал создать DMG-образы с NTFS.
Но, вероятно, имеющиеся у меня драйверы NTFS-3G и Tuxero, содержат ошибку.
В обоих случаях я получал до боли знакомый “File name too long”.

Удача меня ждала с ФС ExFat.



$ touch "яяяяяяяяя яя яяяя яя яяяяяяяяяя яяяяяяяяя я яяяяяя я яяя яяяяяяяяя яяяяяяяяяяяяя яяяяяяяя я яяяяяяяяяяяяяяяяяя яяяяяя яя яяяяяя яяяяяяяяяяяяя яяяяяяяя яяяяя яяяяяя я яяя яяяяя яяя"

И, ву-а-ля

$ ls я*

яяяяяяяяя яя яяяя яя яяяяяяяяяя яяяяяяяяя я яяяяяя я яяя яяяяяяяяя яяяяяяяяяяяяя яяяяяяяя я яяяяяяяяяяяяяяяяяя яяяяяя яя яяяяяя яяяяяяяяяяяяя яяяяяяяя яяяяя яяяяяя я яяя яяяяя яяя


После перемещения своего проекта в новый раздел, вся остальная операция прошла как по-маслу.

Далее, можно почитать про Unicode в названиях файлов в HFS.

понедельник, 30 января 2012 г.

Скрипт Ruby для вычисления SHA1 по аналогии с Git



Некоторое время назад, участвовал в одном обсуждении.
Тогда же, по его результатам, родился небольшой скриптик.
Вкратце, это действует так.
Если вы когда-то давным-давно закоммитили файл. Потом имя (но не содержимое) этого файла несколько раз менялось.
А сейчас вам необходимо найти содержимое блоба, зная только текущее наименование файла.

Следующий скрипт должен помочь.


Выполните:
$ git-sha1.rb filename1 filename2 ... filenameN

На выходе получите список хешей:
sha1_1
sha1_2
...
sha1_N

Теперь можно попробовать найти нужный блоб.
$ git show sha1_N

Так же исходный код этого срипта можно взять на гитхабе.

пятница, 20 января 2012 г.

Cygwin: Starting Gerrit Code Review: Error: Unable to access jarfile


When you encountered this error then you should search in the file "bin/gerrit.sh" for string Если вы встретили такую ошибку, то необходимо в файле "bin/gerrit.sh" найти строку 

GERRIT_SITE=`pwd`

and replace it to the next string и заменить на следующее

GERRIT_SITE=`cygpath -am \`pwd\``





четверг, 12 января 2012 г.

MacOSX: Unicode в названиях файлов в HFS


Недавно, я столкнулся с тем что Git на свежевыкачанном репозитории SVN упорно считает, что некоторые файлы находятся в состоянии Untracked.
Небольшое расследование вывело на следующее.

Unicode позволяет, если не совсем избавиться, то минимизировать проблемы национальных кодировок.
Большое число символов задаётся одним единственным кодом.
Но также имеется немаленькое количество знаков, которые составляются из пар кодов.
Наглядный пример, азиатские языки или различные служебные модификаторы вроде признака направления письма справа-налоево или знака ударения.

Кириллица не стала исключением.

При создании файлов, содержащих в наименовании композитные буквы, HFS сохраняет эти названия в виде двух отдельных знаков.

Для меня это стало сюрпризом, т.к. хотя по спецификации всё верно: буква "Й" является композицией следующих двух:

Тем не менее, буква имеет и единичный код

Аналогично и для "Ё".

Если невооружённым взглядом такое поведение или сложно или невозможно, то оно прекрасно наблюдается во время SSH-сессии.

Локально из терминала проблему можно воспроизвести если создать какой-либо файл, например:
$ touch Ё-моё.txt
И попровать затем выполнить автодополение клавишей [TAB].
$ ./Ё[TAB]
не срабатывает.

Но если ввести
$ ./Е[TAB]
то мы увидим нашу многострадальную "Ё".

Некоторые программы (в моём случае GIT и SVN) не могут корректно обработать такую ситуацию.
Файл, по-мнению алгоритмов, просто не существует.
То есть один и тот же файл в репозитории (попавший туда из других файловых систем) и хранящийся локально (в HFS) считается двумя разными файлами.

Пока мне не попалось подходящего решения или обходного пути.
И, похоже, что необходимо заводить тикет с багой.


Далее, можно почитать про проблему длинных имён в HFS+

пятница, 25 ноября 2011 г.

Как в Git игнорировать изменение прав у файлов

Работая в среде Cygwin или MSysGit, часто бывает так что права файлов изменяются, либо внешней средой, либо внутренними процессами.
У меня наиболее часто меняется признак исполнимости. И, к сожалению, пока отсутствует время чтобы разобраться в причинах.

Загадочным, для меня, образом некоторым файлам добавляется +x, некоторым -x. И Git уже начинает считает эти файлы изменёнными, которые обязательно надо закоммитить.
Т.к. происходит такое довольно часто, то это вызывает раздражение и пустую трату времени на починку с помощью chmod и/или git reset --hard.

Так, вот, если в вашем проекте не используются системные права, то можно заставить git игнорировать изменение прав у файлов.

Отключением/включением проверки управляет ключ filemode из секции core.
Его значение необходимо установить в false.

Либо прямым редактированием .gitconfig:
[core]
        filemode = false

Либо командой:
$ git config core.filemode false

Приятной разработки!

вторник, 7 июня 2011 г.

Как в Git вывести файл из под версионного контроля

Что делать, если вы когда-то взяли файл под версионный контроль, а теперь поняли что он не нужен?
И что делать, если файл, который находится под контролем вы меняете локально, и эти изменения нельзя коммитить?
В обоих случаях .gitignore не работает. А действовать надо так:
$ git rm --cached <file>
Данная команда выведет файл из под версионного контроля при следующем коммите, но оставит его живым в рабочем каталоге.

вторник, 30 ноября 2010 г.

Как передать правильный путь Windows-приложению из Cygwin

Рассмотрим такую ситуацию, для конкретики, возьму Git.
Запущенный под Cygwin, он понимает пути только в Unix-формате, например, "/cygdrive/c/home/projects".
Приложения, вроде KDiff3, P4Merge ждут этот путь в формате "c:\home\projects".

Необходимо как-то сконвертировать.
И такая утилита уже есть в комплекте Cygwin - называется cygpath.
Она имеет много полезных параметров, но, в контексте решаемой задачи, нас интересуют только два:
"-w" конвертирует путь в формат Windows.
"-a" Выдаёт абсолютный путь.


Дополнительно требуется обернуть строки в кавычки, на случай, если в путях попадутся знаки пробелов.
Сейчас разделы инструментов сравнения в моём ~/.gitconfig выглядят так (прочие параметры убрал для наглядности).
[mergetool "kdiff"]
        path = /here_your_path/kdiff3.exe -b \"`cygpath -w -a $BASE`\" \"`cygpath -w -a $LOCAL`\" \"`cygpath -w -a $REMOTE`\" -o \"`cygpath -w -a $MERGED`\"

[mergetool "p4m"]
        cmd = /here_your_path/p4merge \"`cygpath -w -a $BASE`\" \"`cygpath -w -a $LOCAL`\" \"`cygpath -w -a $REMOTE`\" \"`cygpath -w -a $MERGED`\"

[difftool "p4m"]
        cmd = /here_your_path/p4merge \"`cygpath -w -a $LOCAL`\" \"`cygpath -w -a $REMOTE`\"

[difftool "kdiff"]
        cmd = /here_your_path/kdiff3.exe \"`cygpath -w -a $LOCAL`\" \"`cygpath -w -a $REMOTE`\"

пятница, 13 ноября 2009 г.

Интерактивное перебазирование в Git.

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

TortoiseGit - замечательный клиент Git для Windows, пожалуй даже лучший.
Одна из удобнейших фишек объединение нескольких локальных коммитов в один.
Корпоративная политика в настоящее время запрещает ставить Git и TortoiseGit на основную машину разработчика.
А, в отсутствие админских прав, на работе, я не могу установить TortoiseGit самостоятельно.
Клиент имеется в виртуальной машине. Но только для того, чтобы поправить пару коммитов, стартовать виртуалку как-то лениво и непрактично.
На прочих осях, с которыми я работаю, TortoiseGit отсутствует, а местные клиенты такой фишки не имеют.

Я давно знаю про команду rebase и ключик "-i".
Но у меня всё как-то никак не получалось увидеть список этих "pick", "squash", "edit".

Первый мой просчёт в том, что для удобства работы, в качестве редактора я использовал Notepad++.
По, надеюсь, покамест неведомой мне причине, сотрудничество Git и Notepad++ при перебазировании хромает и редактор открывается просто пустым.
Поэтому откатываемся к vim.

Второй недосмотр, что я периодически забираю изменения из SVN: git checkout master && git svn rebase.
Затем синхронизирую хакаемый бранч по: git rebase master.
Таким образом в интерактивном режиме у меня список операций всегда был пуст.
Но гит показывал, что всё равно исправно перебазирует все коммиты, которые я просил.

Оказывается достаточно сделать хотя бы один коммит после перебазирования и тогда уже можно делать
git rebase -i HEAD~хотьсто.
Небольшо хинт для тех кто с vim на "Вы". Чтобы автоматом заменить все pick на squash, переходим в командную строку, нажав ":" (возможно понадобится выйти в режим просмотра сначала).
Пишем там:
%s/pick/squash/
Теперь остаётся только заменить первый squash на pick.
Можно использовать сокращения: "s" и "p", соответственно.

Ни в коей мере, не умаляя других достоинств TortoiseGit, теперь у меня нет необходимости запускать виртуалку только для того чтобы слить несколько коммитов в один.

Как говорится, учите матчасть ;)

среда, 11 ноября 2009 г.

Git для Cygwin и русские или другие национальные буквы в именах файлов

Сделал приятное открытие для себя.
Например,  представим такой сценарий:
Имеем репозиторий git, который только что создан с помощью git init.
Теперь мы хотим создать и добавить в репозиторий файлик "прочти меня.txt". И видим такую картинку:
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
#       "\320\277\321\200\320\276\321\207\321\202\320\270 \320\274\320\265\320\275\321\217.txt"
nothing added to commit but untracked files present (use "git add" to track)

Что, во-первых неэстетично и непонятно. А во-вторых, если закоммитить и продолжить работу, то могут обнаружаться конфликты файлов из разных веток, которые не могут быть разрешены автоматически. При этом мёржилке не получится отдать правильные имена и будет выдана ошибка, что файл не найден.

Если в .git/config в раздел [core] прописать:
quotepath = false
То происходит небольшое и ожидаемое, но всё-таки волшебство ;)
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
#       прочти меня.txt
nothing added to commit but untracked files present (use "git add" to track)

 Приятной разработки и вам!

вторник, 9 июня 2009 г.

Ошибка "trailing whitespace" при коммите в git

Git, как и некоторые другие SCM, например Mercurial, следят за некоторой чистотой кода и проверяют невидимые символы в конце строк.
Эти символы являются мусором и не несут какой-либо полезной информации.
Поэтому, если по команде:
$ git svn rebase
выдается ошибка подобная:
/какой-то_путь/.git/rebase-apply/patch:61: trailing whitespace.
using System.Collections.Generic;
То правильным решением будет открыть эти строки и убрать лишние служебные символы.
Например это можно сделать в интерактивном режиме:
git svn rebase -i
Если во время работы случится что-то непредвиденное и Git начнет сыпать:
Interactive rebase already started
То это легко лечится:
git rebase --continue
Допустим, время или желание не позволяют наводить красоту, то возможно добавить исключение, после чего Git будет пропускать такие ошибки в будущем:
git config core.whitespace nowarn

Включение поддержки UTF-8 в cygwin 1.7

При установке по умолчанию CygWin не поддерживает работу с русским языком.
И если попробовать что-то написать в русской раскладке, то получим что-то вроде:
$ фывапр

На многих форумах пишут что для версий меньше 1.7 проблема актуальна, но я сам не проверял. Для сборки 1.5.25-15 существует специальный патч.
Который, судя по всему, был включен в основную ветку.

Итак, чтобы включить поддержку кодировки UTF-8 необходимо проделать следующие шаги:

1. Если ставите CygWin заново, то отметьте в инсталляторе пакеты интернационализации
libintl, libiconv2. Либо просто убедитесь в их наличии при уже установленном CygWin
2. Добавьте или приведите к следующему виду строки в файле /etc/inputrc или ~/.inputrc:
set input-meta on
set meta-flag on
set convert-meta off
set output-meta on

3. Добавьте или приведите к следующему виду строку в файле /etc/profile или ~/.profile:
export LANG=ru_RU.UTF-8

Или же можно создать отдельный файлик локализации в папке /etc/profile.d/. Пусть это будет, например utf-8.sh.

А теперь запускаем CygWin и видим нормальную поддержку русского языка.
В частности, теперь нормально работает git, особенно git svn rebase.

Для некоторых задач удобно использовать GitExtensions. Это довольно неплохая утилита, аналогичная TortoiseGit, но поддерживает совместную работу с Visual Studio 2005, 2008.
Первая проблема - утилита требует файл git.cmd, которого в CygWin нет. Берем его из MSysGit и кладем в c:\cygwin\cmd.
Вторая, в том, что git.cmd не учитывает свойства среды, которые мы настроили ранее, поэтому я немного подправил его до такого вида:

@echo off
set PLINK_PROTOCOL=ssh
setlocal
for /F "delims=" %%I in ("%~dp0") do @set git_install_root=%%~fI
rem set git_install_root=C:\cygwin
set path=%git_install_root%\bin;%git_install_root%\cmd;%PATH%

if "%1"=="gui" @goto gui
:default
for /f "tokens=* usebackq" %%i in (`@cygpath.exe %CD%`) do (
set HOME=%%i
)
bash.exe -lc 'git.sh --git-dir=%HOME%/.git %*'
exit /b %ErrorLevel%
:gui
if "%2"=="citool" @goto default
start wish.exe "%git_install_root%\libexec\git-core\git-gui" -- %2 %3 %4 %5 %6 %7 %8 %9


И вроде бы все достаточно очевидно, но тем не менее, примерно за один день в режиме ленивого гугления, мне не удалось найти подобной статейки на русском.
Надеюсь информация окажется кому-нибудь полезной.