# upstream vs origin _Удалённые репозитории · GitLab Knowledge Base_ **TL;DR:** Два общепринятых имени remote. `origin` - куда клонировал (обычно свой fork). `upstream` - «настоящий» проект, у которого ты сделал fork. Это просто конвенция: ничего магического, оба имени можно переименовать. В open-source чаще всего работают через fork. Сценарий: ``` github.com/original-project/awesome ← оригинал, ты в нём не пишешь github.com/me/awesome ← твой fork, ты в нём пишешь ``` Локально удобно настроить два remote: ```bash # При clone'е своего форка git clone git@github.com:me/awesome.git cd awesome # Добавляем оригинал как upstream git remote add upstream git@github.com:original-project/awesome.git git fetch upstream ``` Теперь: - `origin` - твой fork. Сюда пушишь свои ветки. - `upstream` - оригинал. Отсюда тянешь чужие обновления. ## Зачем оба нужны Без `upstream` ты получаешь обновления только через GitHub UI: «Sync fork» в браузере. Это работает, но цикл медленный и не подходит для скриптов/CI. С `upstream` цикл «синхронизироваться с оригиналом» - две команды: ```bash git fetch upstream git switch main git rebase upstream/main # или git merge upstream/main git push origin main # обновить main в своём fork'e ``` Никакой UI не нужен, работает из терминала, повторяемо. ## Workflow для нового PR ```bash # 1. Подтянуть оригинал git fetch upstream # 2. Создать фича-ветку от свежей upstream/main, не от origin/main git switch -c feat/my-fix upstream/main # 3. ... коммиты ... # 4. Запушить в свой fork (origin), не в upstream git push -u origin feat/my-fix # 5. На GitHub открыть PR: from me:feat/my-fix → original-project:main ``` Ключевой момент шага 2 - ветвиться от **upstream/main**, не от `origin/main`. Иначе твой fork может быть на день отставать, и в PR попадёт куча устаревших коммитов. ## Это просто имена Git ничего не знает про «оригинал» и «fork». Это конвенция, ничего больше. Можно назвать их `mine` и `theirs`, работать будет одинаково: ```bash git remote rename origin mine git remote rename upstream theirs ``` Но в команде проще говорить общими словами, чтобы инструкции «git fetch upstream && git rebase upstream/main» работали у всех. ## Когда upstream не нужен Если у тебя нет fork'а, а ты пушишь напрямую в основной репо (член команды, owner) - `upstream` не нужен. Один `origin`, стандартный flow. ## Подводные камни - **Случайный push в upstream.** Если у тебя есть права на запись в upstream (например, ты maintainer оригинала и твой fork - для экспериментов), можно по ошибке `git push upstream main` и обновить main оригинала. Спасают branch-protection правила. - **Расхождение origin/main и upstream/main.** Если в свой fork кто-то запушил отдельно (другой контрибьютор, копия), main в нём и main в upstream разойдутся. Решение - синхронизировать через `git push origin upstream/main:main` (или просто пересоздать fork). - **При forge-смене (GitHub → GitLab) забывают переключить upstream.** Если оригинал переехал - обнови `git remote set-url upstream `. ## Команды ```bash git remote add upstream ``` Добавить оригинальный репо как второй remote ```bash git fetch upstream ``` Подтянуть изменения из оригинала ```bash git switch -c feat/x upstream/main ``` Ветвиться от свежего upstream, не от своего fork ```bash git rebase upstream/main ``` Догнать оригинал перед PR ## См. также - [git remote](/courses/git/kb/remote-cmd.md) - [git fetch](/courses/git/kb/fetch.md) - [Fork vs clone](/courses/git/kb/fork-vs-clone.md) - [git clone](/courses/git/kb/clone.md)