No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-22 07:55:07 +03:00
.gitignore clean up .gitignore 2026-08-05 01:04:21 +03:00
README.md Обновить README.md 2026-08-04 21:52:21 +00:00
ящик 110826.SLDPRT Добавил штабелируемый ящик 11082026 2026-08-11 10:23:30 +03:00

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

  1. В веб-интерфейсе Forgejo нажать New Repository.
  2. Не отмечать галочку «Initialize repository с README» — иначе при первом push возникнет конфликт историй (rejected — fetch first), так как на сервере уже будет коммит, а локально его не будет.
  3. Скопировать 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-моделями

  1. Создать пустой репозиторий на Forgejo (без README).
  2. Добавить SSH-ключ в профиль Forgejo, проверить ssh -T.
  3. cd в папку проекта, git init, git branch -M main.
  4. git lfs install + git lfs track "*.stl" "*.step" "*.stp" + коммит .gitattributes.
  5. Настроить .gitignore (в т.ч. .DS_Store) до первого коммита.
  6. Скопировать/создать файлы моделей в папке.
  7. git add . → git commit -m "...".
  8. git remote add origin <ssh-url>.
  9. git push -u origin main.
  10. Подтвердить SSH fingerprint при первом подключении (yes).
  11. Проверить git lfs ls-files, что бинарники ушли через LFS, а не как обычные blob-ы.
  12. Далее — просто git add / git commit / git push для новых версий моделей, git tag для значимых релизов.