8.1 KiB
Перенос проекта с 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, начат ДД.ММ.ГГГГ» - раз дата создания новая.
- Токены, которые светились в чатах и логах, - отозвать и выпустить новые.