| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .gitignore | ||
| README.md | ||
| ящик 110826.SLDPRT | ||
Git + Forgejo: хранение 3D-моделей (STL/STEP)
Инструкция по настройке репозитория для хранения 3D-моделей на self-hosted Forgejo. Рассчитана на работу с Mac без IDE, только через терминал.
1. Базовые понятия
- Репозиторий — папка проекта + скрытая директория
.git, где хранится вся история изменений. - Коммит — «снимок» состояния файлов в конкретный момент с уникальным хешем и сообщением.
- Staging area (индекс) — промежуточная зона: вы явно указываете, какие файлы войдут в следующий коммит (
git add), и только потом фиксируете их (git commit). - Remote — удалённая копия репозитория на сервере (в нашем случае Forgejo).
pushотправляет свои коммиты,pull/fetch— забирает чужие. - Ветка (branch) — именованный указатель на цепочку коммитов;
main— ветка по умолчанию. - HEAD — указатель на коммит, на котором вы сейчас находитесь.
- .gitattributes — файл конфигурации, который говорит git, как обрабатывать определённые файлы (например, через LFS).
Git — распределённая система: у каждого, кто клонировал репозиторий, есть полная копия всей истории.
2. Установка Git на Mac
brew install git
git --version # проверить установленную версию
Разовая настройка автора коммитов (один раз на машину):
git config --global user.name "Ваше имя"
git config --global user.email "you@example.com"
Рекомендуется сразу отключить экранирование кириллицы в путях файлов:
git config --global core.quotepath false
Без этой настройки имена файлов на русском будут отображаться в git status/git log как восьмеричные коды (\321\202...) вместо читаемого текста. На сам коммит и работу это не влияет — только на отображение.
Дополнительные полезные глобальные настройки:
git config --global init.defaultBranch main # новые репозитории сразу с веткой main
git config --global core.editor "nano" # редактор для сообщений коммитов/rebase
git config --global color.ui auto # цветной вывод в терминале
git config --global pull.rebase true # стратегия pull по умолчанию — rebase
git config --global fetch.prune true # автоудаление устаревших remote-веток при fetch
git config --global credential.helper osxkeychain # хранить HTTPS-пароли в Keychain
git config --list # посмотреть все текущие настройки
git config --global -e # открыть глобальный конфиг в редакторе
Настройка глобального игнора системного мусора macOS (делается один раз, работает во всех репозиториях):
echo ".DS_Store" >> ~/.gitignore_global
echo "._*" >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global
3. SSH-ключ для доступа к Forgejo
Если ключа ещё нет:
ssh-keygen -t ed25519 -C "you@example.com" -f ~/.ssh/forgejo_ed25519
Добавить ключ в SSH-агент, чтобы не вводить пароль каждый раз:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/forgejo_ed25519
Скопировать публичный ключ для вставки в веб-интерфейс Forgejo (Settings → SSH Keys):
cat ~/.ssh/forgejo_ed25519.pub | pbcopy
Проверить, что соединение работает:
ssh -T -p 2222 git@git.example.com
Если используется нестандартный порт (как в вашем случае, 2222) и не хочется каждый раз прописывать его в URL, можно добавить алиас в ~/.ssh/config:
Host forgejo
HostName git.example.com
Port 2222
User git
IdentityFile ~/.ssh/forgejo_ed25519
После этого можно клонировать короче: git clone forgejo:user/repo.git.
4. Создание репозитория на Forgejo
- В веб-интерфейсе Forgejo нажать New Repository.
- Не отмечать галочку «Initialize repository с README» — иначе при первом push возникнет конфликт историй (
rejected — fetch first), так как на сервере уже будет коммит, а локально его не будет. - Скопировать SSH-адрес репозитория, вид:
ssh://git.example.com:2222/user/repo.gitилиgit@example.com:user/repo.git.
SSH-доступ удобнее HTTPS, так как не требует вводить логин/пароль при каждом push, если ключ добавлен в профиль на Forgejo.
5. Инициализация нового проекта
cd ~/Models/my-3d-project
git init # создаёт .git — локальный репозиторий
git branch -M main # на всякий случай явно переименовать ветку в main
git add . # кладёт файлы в staging area
git commit -m "Первый коммит" # фиксирует снимок
git remote add origin ssh://git.example.com:2222/user/repo.git
# запоминает алиас origin -> URL сервера
git remote -v # проверить, что адрес записан верно
git push -u origin main # первая отправка + связка ветки
Разбор флагов git push -u origin main:
origin— куда отправлять (алиас удалённого репозитория).main— какую локальную ветку отправлять (проверить имя:git branch).-u(--set-upstream) — связывает локальную ветку с удалённой, после чего достаточно писать простоgit push/git pullбез аргументов.
При первом SSH-подключении появится запрос подтверждения отпечатка ключа сервера:
The authenticity of host '...' can't be established.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Это нормально, отвечаем yes — ключ добавится в ~/.ssh/known_hosts, и запрос больше не появится.
Если репозиторий уже существует на сервере и нужно просто скачать его на новую машину:
git clone ssh://git.example.com:2222/user/repo.git
cd repo
git lfs pull # обязательно, если в репо используется LFS — подтягивает реальные файлы
6. Типичные ошибки при первом push
error: src refspec main does not match any
Причина — локально нет ни одного коммита в ветке main (ветка «пустая»).
Диагностика:
git log --oneline # если "does not have any commits yet" — коммитов нет
git status # проверить, видит ли git файлы вообще
git branch # проверить реальное имя ветки
Решение, если файлы есть, но не закоммичены:
git add .
git commit -m "Первый коммит"
git push -u origin main
Если ветка называется master, а не main — либо переименовать:
git branch -M main
либо просто пушить как есть: git push -u origin master.
rejected — fetch first / расходящиеся ветки (diverged)
Возникает, если репозиторий на сервере создан с README (см. п.4) или если push был сделан с другой машины/пользователя. Решение:
git add -A # добавить все изменения, включая удаления
git commit -m "sync local changes" # закоммитить, иначе pull откажется работать
git pull --rebase origin main # интегрировать удалённые коммиты
git push # отправить результат
Если репозиторий на сервере создан с README и общей истории вообще нет:
git pull origin main --allow-unrelated-histories
Конфликт при rebase/merge
Если git останавливается со словом CONFLICT:
git status # какие файлы конфликтуют
git checkout --ours <файл> # оставить свою версию файла
git checkout --theirs <файл> # либо оставить версию с сервера
git add <файл>
git rebase --continue # если шёл rebase
# или
git commit # если шёл обычный merge
Отменить rebase/merge и вернуться в исходное состояние, если всё пошло не так:
git rebase --abort
git merge --abort
zsh: unknown file attribute: ^ при вставке команд
Не связано с git — возникает, когда в терминал вставляется многострочный текст со спецсимволами. Вводите команды по одной строке, не вставляйте блоки с комментариями # разом.
7. Git LFS — обязательно для 3D-моделей
STL и другие бинарные форматы плохо сжимаются построчно и раздувают репозиторий с каждой новой версией файла. Git LFS хранит вместо самого файла маленький текстовый указатель в репозитории, а бинарные данные — в отдельном хранилище на сервере.
STEP-файлы формально текстовые (ISO 10303), но обычно тоже стоит подключать LFS, если модели большие или часто меняются.
Установка на Mac
brew install git-lfs
git lfs install # один раз на машину
git lfs version # проверить установку
Настройка в проекте
git lfs track "*.stl" "*.step" "*.stp"
git lfs track "*.3mf" "*.obj" "*.f3d" "*.blend" # при необходимости добавить другие форматы
git add .gitattributes
git commit -m "Настроил LFS для 3D моделей"
git add model.stl
git commit -m "Добавил модель"
git push
После git lfs track все файлы с указанными расширениями автоматически проходят через LFS при add/commit/push.
Полезные команды для работы с LFS
git lfs ls-files # список файлов, отслеживаемых через LFS в текущей ветке
git lfs status # статус LFS-объектов (закачаны/нет)
cat .gitattributes # посмотреть, какие паттерны уже под LFS
git lfs track # список всех LFS-паттернов без изменений
git lfs untrack "*.step" # убрать формат из отслеживания LFS
git lfs pull # скачать реальные бинарники вместо указателей
git lfs fetch --all # скачать все версии LFS-объектов из всех веток
git lfs prune # удалить локальные LFS-объекты, которые больше не нужны
git lfs env # диагностика конфигурации LFS (endpoint, версии, пути)
git lfs logs last # последний лог ошибки LFS, если push/pull падал
Локальное клонирование без скачивания бинарников (только указатели, полезно для быстрого просмотра структуры):
GIT_LFS_SKIP_SMUDGE=1 git clone ssh://git.example.com:2222/user/repo.git
Настройка на стороне Forgejo (сервер)
В app.ini:
[server]
LFS_START_SERVER = true
[lfs]
PATH = /data/forgejo/lfs
LFS_HTTP_AUTH_EXPIRY = 180m
Добавить volume для LFS-данных в docker-compose и перезапустить контейнер:
docker compose restart forgejo
docker compose logs -f forgejo # проверить, что сервис поднялся без ошибок
Проверить занятое место LFS-хранилищем на сервере:
du -sh /data/forgejo/lfs
Ограничения по умолчанию, которые стоит знать:
| Параметр | Значение | Что делать |
|---|---|---|
| Загрузка через веб-интерфейс | лимит 3 МБ на файл, 5 файлов за раз | использовать git push, а не веб-загрузку |
| Время истечения LFS-загрузки | 20 минут | увеличить LFS_HTTP_AUTH_EXPIRY = 180m для больших файлов |
| Хранилище LFS | локальный диск | можно вынести в S3-совместимое хранилище (Minio) |
| Максимальный размер файла LFS | без ограничений по умолчанию | ограничить при желании (MAX_FILE_SIZE) |
Пример конфигурации LFS на S3/Minio вместо локального диска в app.ini:
[lfs]
STORAGE_TYPE = minio
MINIO_ENDPOINT = minio.example.com:9000
MINIO_BUCKET = forgejo-lfs
MINIO_LOCATION = us-east-1
MINIO_ACCESS_KEY_ID = ваш_access_key
MINIO_SECRET_ACCESS_KEY = ваш_secret_key
MINIO_USE_SSL = true
Миграция уже существующих файлов на LFS
Если STL/STEP уже закоммичены обычным способом (без LFS):
git lfs migrate import --include="*.stl,*.step,*.stp" --everything
git push --all --force
git push --tags --force # если есть теги, их тоже нужно перезаписать
Команда переписывает историю, заменяя бинарники на LFS-указатели. Требует --force, так как меняет хеши коммитов — если с репозиторием работает кто-то ещё, нужно предупредить заранее, чтобы все сделали свежий clone после миграции.
Проверить размер репозитория до и после миграции:
du -sh .git
git count-objects -vH
8. Повседневный workflow после настройки
git status # что изменилось
git add новая_модель.step
git commit -m "описание изменения"
git push # без указания origin main благодаря -u при первом push
git pull # если работаете с нескольких машин
git log --oneline -10 # последние 10 коммитов кратко
git log --oneline --graph --all # визуальный граф веток и коммитов
git diff # что изменилось в файлах с последнего коммита (только текстовые)
git show HEAD # подробности последнего коммита
Отменить незакоммиченные изменения в файле (вернуть как было при последнем коммите):
git restore имя_файла
Убрать файл из staging area, не трогая сами изменения на диске:
git restore --staged имя_файла
Посмотреть историю изменений конкретного файла (например, версии одной модели):
git log --follow -- model.step
git log -p -- model.step # с показом самих изменений (для текстовых STEP-файлов)
Вернуться к конкретной версии файла из истории без потери текущих изменений:
git checkout <хеш-коммита> -- model.step
Посмотреть, кто и когда последний раз менял конкретную строку/файл:
git blame model.step
9. Работа с версиями и тегами моделей
Полезно помечать значимые версии моделей тегами (например, «готово к печати», «финал ревизии»):
git tag -a v1.0-print-ready -m "Версия готова к печати"
git push origin v1.0-print-ready
git tag # список всех тегов
git tag -d v1.0-print-ready # удалить тег локально
git push origin --delete v1.0-print-ready # удалить тег на сервере
Создать отдельную ветку для экспериментальной версии модели, не трогая основную:
git checkout -b experiment/new-mount
git add .
git commit -m "Пробный вариант крепления"
git push -u origin experiment/new-mount
Слить экспериментальную ветку обратно в main после проверки:
git checkout main
git pull
git merge experiment/new-mount
git push
git branch -d experiment/new-mount # удалить локально после слияния
git push origin --delete experiment/new-mount # удалить на сервере
10. Резервное копирование и восстановление
Сделать полный зеркальный бэкап репозитория (включая все ветки, теги, LFS-указатели):
git clone --mirror ssh://git.example.com:2222/user/repo.git repo-backup.git
Восстановить репозиторий на сервер из зеркальной копии (например, на новый Forgejo):
cd repo-backup.git
git push --mirror ssh://git.newserver.com:2222/user/repo.git
Экспортировать историю в единый архив для холодного хранения:
git bundle create repo.bundle --all
11. Диагностика и полезные "аварийные" команды
git fsck # проверить целостность репозитория
git gc # очистка и оптимизация .git (сжатие объектов)
git reflog # журнал всех перемещений HEAD — спасает, если что-то "потерялось"
git reset --hard HEAD # отменить ВСЕ незакоммиченные изменения (осторожно, без возврата)
git reset --soft HEAD~1 # отменить последний коммит, но оставить изменения в staging
git clean -fd # удалить неотслеживаемые файлы и папки (осторожно, без корзины)
git stash list # список сохранённых stash
git stash show -p stash@{0} # посмотреть содержимое конкретного stash
git stash drop stash@{0} # удалить конкретный stash без применения
12. Итоговый чек-лист для нового проекта с 3D-моделями
- Создать пустой репозиторий на Forgejo (без README).
- Добавить SSH-ключ в профиль Forgejo, проверить
ssh -T. cdв папку проекта,git init,git branch -M main.git lfs install+git lfs track "*.stl" "*.step" "*.stp"+ коммит.gitattributes.- Настроить
.gitignore(в т.ч..DS_Store) до первого коммита. - Скопировать/создать файлы моделей в папке.
git add .→git commit -m "...".git remote add origin <ssh-url>.git push -u origin main.- Подтвердить SSH fingerprint при первом подключении (
yes). - Проверить
git lfs ls-files, что бинарники ушли через LFS, а не как обычные blob-ы. - Далее — просто
git add/git commit/git pushдля новых версий моделей,git tagдля значимых релизов.