145 lines
8.1 KiB
Markdown
145 lines
8.1 KiB
Markdown
# Перенос проекта с 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
|
||
|
||
```sh
|
||
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»** - иначе в проекте появится свой первый
|
||
коммит, и историю придётся склеивать.
|
||
|
||
Или из терминала:
|
||
|
||
```sh
|
||
glab repo create itzredtea/ИМЯ --public # или --private; README не создаётся
|
||
```
|
||
|
||
## 2. Проверить, что всё есть локально
|
||
|
||
```sh
|
||
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='ДАТА'`).
|
||
|
||
Снимок до переноса - для сверки:
|
||
|
||
```sh
|
||
git log --branches --remotes=origin --tags --format='%H %aI %cI' | sort > /tmp/before.txt
|
||
git show-ref --tags | sort > /tmp/tags-before.txt
|
||
```
|
||
|
||
## 3. Отправить историю
|
||
|
||
```sh
|
||
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:
|
||
|
||
```sh
|
||
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:
|
||
|
||
```sh
|
||
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). Файлы - свои копии или сборка из коммита
|
||
релиза во временной папке:
|
||
|
||
```sh
|
||
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:
|
||
|
||
```sh
|
||
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, начат ДД.ММ.ГГГГ» - раз дата создания новая.
|
||
- Токены, которые светились в чатах и логах, - отозвать и выпустить новые.
|