Files
lpra/docs/gitlab-migration.md
T

8.1 KiB
Raw Permalink Blame History

Перенос проекта с GitHub на GitLab с сохранением истории и дат

Инструкция для локального репозитория, когда GitHub недоступен (аккаунт заблокирован) и переносить приходится из своей копии. Так был перенесён lpra: 195 коммитов, 8 тегов, 3 релиза - хэши и даты совпали.

Что сохраняется, а что нет

Что Сохраняется?
Даты коммитов (автора и коммита) Да, точно. Они хранятся внутри коммита; push той же истории не меняет ни одного хэша
Ветки и теги Да, если они есть локально (см. шаг 2)
Дата создания проекта Нет. На gitlab.com она всегда - день создания проекта, задним числом не ставится. Начало проекта видно по первому коммиту
Релизы Создаются заново, с исходной датой (--released-at); файлы релизов - заново собрать или взять свои копии
Issues, PR, звёзды, Actions Нет: при заблокированном GitHub их не выгрузить

Нельзя: rebase, squash, filter-branch, filter-repo, commit --amend по старым коммитам, «Import from GitHub» с чужой копии - всё это переписывает коммиты и их даты.

0. Один раз: вход в GitLab

brew install glab
glab auth login --hostname gitlab.com --web --git-protocol https

Вход через браузер даёт права и на push, и на релизы. Git берёт пароль у glab - для каждого репозитория это настраивается в шаге 4 (или один раз для всех: git config --global credential.https://gitlab.com.helper '!glab auth git-credential').

SSH-ключ тоже подойдёт, но в GitLab у ключа должен быть Usage type: Authentication & Signing (с типом «Signing» по SSH не пускает).

1. Пустой проект в GitLab

https://gitlab.com/projects/new → Create blank project → имя, владелец itzredtea. Снять галочку «Initialize repository with a README» - иначе в проекте появится свой первый коммит, и историю придётся склеивать.

Или из терминала:

glab repo create itzredtea/ИМЯ --public      # или --private; README не создаётся

2. Проверить, что всё есть локально

cd ~/CodeRepos/ИМЯ
git status                 # незакоммиченное закоммитить или убрать
git branch -a              # ветки: свои и remotes/origin/*
git tag -l                 # теги
  • Ветки, которых нет локально, но есть remotes/origin/X, тоже переносятся (шаг 3).
  • Теги, созданные на GitHub при публикации релиза, могут не быть локально - если их не делали git fetch --tags. Такой тег создаётся заново на нужном коммите (шаг 5). Коммит ищется по дате публикации релиза: последний коммит перед ней (git log --format='%h %cd %s' --date=iso --until='ДАТА').

Снимок до переноса - для сверки:

git log --branches --remotes=origin --tags --format='%H %aI %cI' | sort > /tmp/before.txt
git show-ref --tags | sort > /tmp/tags-before.txt

3. Отправить историю

git remote rename origin github                      # GitHub остаётся под своим именем
git remote add origin https://gitlab.com/itzredtea/ИМЯ.git
H='!glab auth git-credential'
git -c credential.helper= -c "credential.helper=$H" push origin --all          # все локальные ветки
git -c credential.helper= -c "credential.helper=$H" push origin 'refs/remotes/github/*:refs/heads/*'  # ветки, что были только на GitHub
git -c credential.helper= -c "credential.helper=$H" push origin --tags

Вторая команда push может сказать про HEAD - это не ветка, сообщение можно не смотреть.

4. Сверить и переключиться

Сверка - по свежей копии из GitLab:

rm -rf /tmp/check && git clone -q https://gitlab.com/itzredtea/ИМЯ.git /tmp/check
cd /tmp/check && git log --remotes=origin --tags --format='%H %aI %cI' | sort > /tmp/after.txt
git show-ref --tags | sort > /tmp/tags-after.txt
diff /tmp/before.txt /tmp/after.txt && echo "коммиты и даты совпали"
diff /tmp/tags-before.txt /tmp/tags-after.txt && echo "теги совпали"

Пустой diff - история перенесена один в один. Дальше работать с GitLab:

cd ~/CodeRepos/ИМЯ
git config --local credential.https://gitlab.com.helper '!glab auth git-credential'
git fetch origin && git branch -u origin/main main

5. Релизы с исходными датами

Дата - время публикации релиза на GitHub (UTC). Файлы - свои копии или сборка из коммита релиза во временной папке:

git worktree add --detach /tmp/rel-1.2.0 1.2.0      # тег или хэш коммита релиза
cd /tmp/rel-1.2.0 && ./build.sh                       # как проект собирается
glab release create 1.2.0 bin/файл1 bin/файл2 \
  -R itzredtea/ИМЯ --name "Release 1.2.0" \
  --released-at "2026-10-15T16:34:53Z" \
  --notes "Перенесено с GitHub, дата публикации исходная."
# тега нет (его делал GitHub) - добавить: --ref <полный хэш коммита>
git worktree remove /tmp/rel-1.2.0

Создавать по порядку, от старых к новым. Последним GitLab считает релиз с самой поздней датой. Ссылки на файлы:

  • конкретный релиз: https://gitlab.com/itzredtea/ИМЯ/-/releases/ТЕГ/downloads/ФАЙЛ
  • последний: https://gitlab.com/itzredtea/ИМЯ/-/releases/permalink/latest/downloads/ФАЙЛ

6. Ссылки в самом проекте

Найти и заменить всё, что смотрит на GitHub:

grep -rn "github.com\|githubusercontent" --exclude-dir=.git .
GitHub GitLab
https://raw.githubusercontent.com/USER/ИМЯ/main/ПУТЬ https://gitlab.com/itzredtea/ИМЯ/-/raw/main/ПУТЬ
https://github.com/USER/ИМЯ/releases/latest/download/ФАЙЛ https://gitlab.com/itzredtea/ИМЯ/-/releases/permalink/latest/downloads/ФАЙЛ
https://api.github.com/repos/USER/ИМЯ/releases/latest (tag_name) https://gitlab.com/api/v4/projects/itzredtea%2FИМЯ/releases/permalink/latest (tag_name)
https://api.github.com/repos/USER/ИМЯ/contents/ПАПКА?ref=main https://gitlab.com/api/v4/projects/itzredtea%2FИМЯ/repository/tree?path=ПАПКА&ref=main (поле path)
картинки github.com/user-attachments/... скачать, пока открываются, в docs/ и ссылаться на файлы

Путь Go-модуля (module github.com/... в go.mod) можно не трогать: это только имя.

7. После переноса

  • Описание проекта в GitLab: «Перенесён с GitHub, начат ДД.ММ.ГГГГ» - раз дата создания новая.
  • Токены, которые светились в чатах и логах, - отозвать и выпустить новые.