Переход от одного средства разработки к другому - вообще довольно затруднительное занятие, почти всегда сопряжённое с трудностями, ошибками и неприятностями. Так и переход с svn на git. Последний вообще оказался довольно своеобразной системой. И здесь под своеобразием я понимаю не то, что он ведёт себя не как svn, а то, что его поведение не интуитивно.
Много неприятностей доставила система submodule'ей. Submodule - это отдельный репозиторий, который считается дочерним к корневому. Т.е. пусть существует 2 проекта, которые развиваются независимо друг от друга, но один использует другой. Тогда оба будут лежать в разных независимых репозиториях, но один из них для другого будет submodule'ем. Вроде всё логично. Но на практике возникают неожиданные проблемы.
Пример первый. Клоним репозиторий
и начинаем работу
Вроде всё нормально. До тех пор, пока не происходит попытки перейти на другую ветвь. Оказывается, после инициализации submodule'ей, они находятся в ветке no branch. Теперь получить написанный код можно будет только по хешу коммита. Чтобы такого не происходило, надо после
делать:
Я ещё могу понять, почему submodule'и клонятся в no branch (хотя это на самом деле тоже не интуитивно, т.к. корневой репозиторий клонится сразу в master), но почему git позволяет делать commit в no branch?
Пример второй. Работали мы себе в submodule'е, делали коммиты. Потом понадобилось срочно поправить корневой реп и запушить его. Сделали. Вроде всё нормально. Но вот что получает человек, захотевший склонить репозиторий себе на другую машину:
Произошло примерно следующее: git узнал, что в submodule'е были коммиты, записал эту информацию на сервер, но в submodule'е не было push. Т.е. информация о коммитах есть, а самих коммитов нет. Вполне законные вопросы: а какого такая ситуация вообще допускается и какого 2 независимых репозитория вдруг стали друг от друга зависеть? Очередная неприятная ситуация с непонятной ошибкой и неочевидными причинами её возникновения.
Пример третий. У меня есть несколько git-репозиториев, хранящихся на монтируемых устройствах. Т.е. когда я работаю с каким-либо проектом, я делаю mount и работаю в точке монтирования. Но вот, в один прекрасный день я поучил сообщение:
Оказывается, в файле .git в submodule'е прописывается абсолютный локальный путь до директории этого submodule'я. Но в зависимости от порядка монтирования устройств реальный путь на моей машине меняется. Т.е. я ещё должен помнить, в каком порядке мне подключать устройства с репозиториями. Зачем вообще так делать - я хз, но опять при довольно обычных действиях пользователя система ведёт себя неадекватно.
В общем, git не оправдал моих надежд как супер-мега средство, которое сделает мне хорошо. По крайней мере на данный момент проблем от него больше чем пользы.
Много неприятностей доставила система submodule'ей. Submodule - это отдельный репозиторий, который считается дочерним к корневому. Т.е. пусть существует 2 проекта, которые развиваются независимо друг от друга, но один использует другой. Тогда оба будут лежать в разных независимых репозиториях, но один из них для другого будет submodule'ем. Вроде всё логично. Но на практике возникают неожиданные проблемы.
Пример первый. Клоним репозиторий
git colne user@adress
git submodule init
git submodule update
и начинаем работу
cd repo/submodule_1
#...
git commit -m "..."
git push
Вроде всё нормально. До тех пор, пока не происходит попытки перейти на другую ветвь. Оказывается, после инициализации submodule'ей, они находятся в ветке no branch. Теперь получить написанный код можно будет только по хешу коммита. Чтобы такого не происходило, надо после
git submodule update
делать:
git submodule foreach git checkout master
Я ещё могу понять, почему submodule'и клонятся в no branch (хотя это на самом деле тоже не интуитивно, т.к. корневой репозиторий клонится сразу в master), но почему git позволяет делать commit в no branch?
Пример второй. Работали мы себе в submodule'е, делали коммиты. Потом понадобилось срочно поправить корневой реп и запушить его. Сделали. Вроде всё нормально. Но вот что получает человек, захотевший склонить репозиторий себе на другую машину:
Cloning into repo...
remote: Counting objects: 42, done.
remote: Compressing objects: 100% (36/36), done.
remote: Total 42 (delta 6), reused 38 (delta 5)
Receiving objects: 100% (42/42), 597.08 KiB, done.
Resolving deltas: 100% (6/6), done.
fatal: reference is not a tree: ...
Unable to checkout '...' in submodule path 'repo'
Произошло примерно следующее: git узнал, что в submodule'е были коммиты, записал эту информацию на сервер, но в submodule'е не было push. Т.е. информация о коммитах есть, а самих коммитов нет. Вполне законные вопросы: а какого такая ситуация вообще допускается и какого 2 независимых репозитория вдруг стали друг от друга зависеть? Очередная неприятная ситуация с непонятной ошибкой и неочевидными причинами её возникновения.
Пример третий. У меня есть несколько git-репозиториев, хранящихся на монтируемых устройствах. Т.е. когда я работаю с каким-либо проектом, я делаю mount и работаю в точке монтирования. Но вот, в один прекрасный день я поучил сообщение:
$ git pull
remote: Counting objects: 50914, done.
remote: Compressing objects: 100% (29735/29735), done.
remote: Total 50912 (delta 19352), reused 50368 (delta 18906)
Receiving objects: 100% (50912/50912), 817.64 MiB | 5.95 MiB/s, done.
Resolving deltas: 100% (19352/19352), completed with 1 local objects.
From xxx.xxx.xxx.xxx:/repo
cc7208e..55dc87e master -> origin/master
fatal: Not a git repository: /media/mount_point_1/repo
Оказывается, в файле .git в submodule'е прописывается абсолютный локальный путь до директории этого submodule'я. Но в зависимости от порядка монтирования устройств реальный путь на моей машине меняется. Т.е. я ещё должен помнить, в каком порядке мне подключать устройства с репозиториями. Зачем вообще так делать - я хз, но опять при довольно обычных действиях пользователя система ведёт себя неадекватно.
В общем, git не оправдал моих надежд как супер-мега средство, которое сделает мне хорошо. По крайней мере на данный момент проблем от него больше чем пользы.
C устройствами, логичнее экспортировать репозиторий в файл. И на самом устройстве хранить только файл.
ОтветитьУдалитьС субмодулями, как понимаю, так делать не надо. Лучше править там, где субмодуль является корнем.
Репозиторий и находится в файле. На самом деле там просто криптоконтейнер, в который склонен корневой репозиторий и его субмодули. Но в корневом репе адреса субмодулей прописываются абсолютно, что делает затруднительным их использование в другой точке монтирования.
УдалитьНу и субмодуль в принципе не всегда является корнем. Просто с ними надо быть крайне осторожным и по возможности избегать их использования.
> Репозиторий и находится в файле.
ОтветитьУдалитьЯ про
http://diseaz.github.com/gitmagic/ch06.html#_git_3
> Ну и субмодуль в принципе не всегда является корнем.
Тогда смысл его иметь как субмодуль? Для удобства и симлинками можно воспользоваться.
Я так понял, git bundle используется просто для переноса проекта на другую машину. Хотя, я не уверен, что он корректно обработает submodule. У меня на устройстве рабочая копия. Там проблема в том, что в файле main_repo/any_submodule/.git лежит строка
Удалитьgitdir: /absolute/path/to/submodule
Соответственно, когда я монтирую 3 своих криптоконтейнера в произвольном порядке, фактический путь меняется, а путь в конфиге - нет. Из-за этого git не может найти submodule.
Смысл во-первых чтобы логически отделить разные проекты. Но есть и более экзотический случай. Предположим, есть 2 несвязанных проекта A и B и есть небольшой модуль M, который используется обоими. Нужно как-то хранить его рядом с обоими репозиториями и при этом делать так, чтобы при изменении M из проекта A можно было легко без костылей за pull'ить его в проект B. Держать 2 копии модуля S в разных репах и руками мержить - не вариант.
Я к тому, что все хранить на одной машине. Без внешних устройств. А с устройствами возиться только когда нужно синхронизировать, и только через bundle. Т.е. на устройстве хранить только сбандленный файл, а не кусок репа или реп.
УдалитьС логическим отделением сталкивался. Ничего лучшего чем создать проект Ц и работать с ним отдельно не придумал.
+ Если еще появятся проекты D и E, которые его юзают, будет удобнее прикреплять Ц к ним.
Но вообще, не даром для erlang есть rebar, который частично дублирует функционал git относительно подпроектов.
может быть git-subtree окажется более полезным.
ОтветитьУдалитьНе сталкивался с ним, но как я понял из описания, subtree является частью репозитория и не получится склонить его отдельно. Оно конечно не критично, но иногда эта функция бывает полезна.
УдалитьНо да, скорей всего в следующий раз я попробую его, т.к. submodule постоянно вызывает какие-то проблемы :(
Посмотри опции git push, там есть спец опция для субмодулей, чтобы проверять, есть ли там коммит.
ОтветитьУдалить"Вполне законные вопросы: а какого такая ситуация вообще допускается и какого 2 независимых репозитория вдруг стали друг от друга зависеть?"
не понимаю, репо с субмодулями зависит от репо-источников своих субмодуля. Не ужели у тебя ошибка такая что стало вдруг: от репо с субмодулями зависит репо-источник субмодуля?
> Посмотри опции git push, там есть спец опция для субмодулей, чтобы проверять, есть ли там коммит.
УдалитьДа, вопрос только почему она не включается сама в довольно очевидной ситуации.
> не понимаю, репо с субмодулями зависит от репо-источников своих субмодуля. Не ужели у тебя ошибка такая что стало вдруг: от репо с субмодулями зависит репо-источник субмодуля?
Зачем им друг от друга зависеть? В обе стороны. Нет, понятно, что в охватывающем репо должна быть возможность скачать репо-субмодуль, но почему сделано так, что действия в субмодуле как-то отражаются в охватывающем репо?
ППКС. Синхрофазотрон, которым предлагается забивать гвозди.
ОтветитьУдалить