Learning Platform
Глоссарий Troubleshooting
Урок 07.01 · 18 мин
Начальный
Gitremotesoriginremote-tracking

Концепция remote: что это и зачем

До этого момента мы работали с локальным репозиторием — .git/ в твоей файловой системе. Но Git создан для распределённой работы. Remote — это именованный указатель на копию этого же репозитория где-то ещё: на GitHub, GitLab, корпоративном сервере или даже на соседнем диске.

В этом уроке мы разберёмся, что такое remote с точки зрения Git (это не сервер, это запись в конфиге), почему именно origin стал стандартом, как работает связка origin + upstream для форков, и что такое remote-tracking branches вида origin/main — те самые, которые ты постоянно видишь в git status.


Mental model: remote — это закладка

Когда ты слышишь “remote репозиторий”, в голове рисуется сервер. Это правда, но не полная. Для самого Git remote — это просто запись в .git/config: имя + URL + правила синхронизации refs.

Что такое remote с точки зрения Git
.git/config
name = "origin"
URL = адрес
refspec = mapping

То есть remote — это алиас. Вместо того чтобы каждый раз писать полный URL [email protected]:user/repo.git, ты используешь короткое имя origin. Git берёт это имя, лезет в .git/config, находит URL и идёт туда.

TIP

Remote можно потрогать руками. Открой .git/config в любом проекте, который ты клонировал — там увидишь блок [remote "origin"]. Это весь “remote” со стороны Git.


Команды: посмотреть и добавить

git remote -v

Самая частая команда — показать все remotes текущего репозитория с их URL.

$ git remote -v
origin  [email protected]:acme/data-pipelines.git (fetch)
origin  [email protected]:acme/data-pipelines.git (push)

Заметь: каждый remote показан дважды — для fetch (откуда читать) и push (куда писать). В 99% случаев это один и тот же URL. Но Git позволяет иметь разные — например, читать с GitHub-зеркала, а писать в основной GitLab.

git remote add

Добавить новый remote:

$ git remote add origin [email protected]:user/repo.git
$ git remote -v
origin  [email protected]:user/repo.git (fetch)
origin  [email protected]:user/repo.git (push)

git remote remove и git remote rename

$ git remote rename origin github
$ git remote remove old-server

Заметь: всё это локальные операции. Они меняют только твой .git/config. Никакого “удаления с сервера” не происходит.


Почему origin — стандарт

Когда ты пишешь git clone <url>, Git создаёт remote с именем origin автоматически. Это не магическая константа — это просто дефолт для команды clone.

$ git clone [email protected]:acme/repo.git
$ cd repo
$ git remote -v
origin  [email protected]:acme/repo.git (fetch)
origin  [email protected]:acme/repo.git (push)

Можно сменить дефолт через флаг -o:

$ git clone -o github [email protected]:acme/repo.git
$ git remote -v
github  [email protected]:acme/repo.git (fetch)
github  [email protected]:acme/repo.git (push)

Но не делай так. origin — конвенция, и ломать её — значит создавать когнитивную нагрузку всем, кто увидит твой репо. Все инструменты, туториалы и скрипты ожидают origin.


Multi-remote setup: origin + upstream при форке

Самый частый случай нескольких remote — работа с fork на GitHub/GitLab.

Сценарий: ты хочешь контрибьютить в open-source проект apache/airflow. Ты не можешь пушить туда напрямую — у тебя нет прав. Поэтому:

  1. Делаешь fork через UI GitHub -> получаешь your-name/airflow.
  2. Клонируешь свой fork локально.
  3. Добавляешь оригинальный репо как второй remote — обычно с именем upstream.
Fork workflow: origin (твой fork) + upstream (оригинал)
upstream
origin
local clone

Команды:

# Клонировал свой fork
$ git clone [email protected]:your-name/airflow.git
$ cd airflow

# Добавил оригинал как upstream
$ git remote add upstream [email protected]:apache/airflow.git

$ git remote -v
origin    [email protected]:your-name/airflow.git (fetch)
origin    [email protected]:your-name/airflow.git (push)
upstream  [email protected]:apache/airflow.git (fetch)
upstream  [email protected]:apache/airflow.git (push)

Теперь ты:

  • Получаешь обновления из оригинала: git fetch upstream -> git merge upstream/main (или rebase).
  • Пушишь свою feature ветку в свой fork: git push origin feature/my-fix.
  • Открываешь PR из your-name/airflow:feature/my-fix -> apache/airflow:main через UI.
WARNING

Часто бывает: пушнул сразу в upstream (или попытался). Получил 403 Permission denied. Это потому что у тебя нет прав в оригинальном репо. Пушить в open-source — это про fork + PR, а не про прямой push в apache/*.


Remote-tracking branches: origin/main

Самая частая путаница у джунов — что такое origin/main. Это не remote-ветка. Это локальная ссылка вида “что я в последний раз видел в main на origin при fetch”.

Remote-tracking branch — это локальная закладка
server: origin
local repo
git fetch -> origin/main := C7

Где они лежат физически?

$ ls .git/refs/heads/
main  feature-x

$ ls .git/refs/remotes/origin/
HEAD  main  develop

Видишь? refs/heads/main — твоя локальная ветка. refs/remotes/origin/main — снимок того, что ты видел на сервере при последнем fetch. Это два разных ref, указывающих на разные коммиты.

Когда git status пишет:

Your branch is ahead of 'origin/main' by 3 commits.

Это значит: твоя локальная main ушла на 3 коммита вперёд относительно того, что ты последний раз скачал с сервера. Может быть, на сервере уже 5 новых коммитов — Git не знает, пока ты не сделаешь git fetch.

NOTE

Ключевая мысль: origin/main обновляется только командами fetch, pull или push. Это не “живой указатель на сервер”. Это закладка. Поэтому привычка делать git fetch перед git status — здоровая.


Refspec: как ветки маппятся

В блоке [remote "origin"] ты видишь строчку:

fetch = +refs/heads/*:refs/remotes/origin/*

Это refspec — правило: “когда я делаю git fetch origin, забери все ветки с сервера (refs/heads/*) и сохрани их локально под именами refs/remotes/origin/*”.

Звёздочка раскрывается как glob: ветка main на сервере -> origin/main локально, develop -> origin/develop и так далее.

Знак + означает “разрешить force-update” — то есть если на сервере историю переписали через force-push, твой origin/main обновится без ошибки. Без + Git ругался бы на non-fast-forward.

В быту тебе не нужно править refspec вручную. Просто знай: вот так Git понимает, что чему соответствует.


Практика: посмотри свой remote

Открой любой склонированный репо и пройди по чек-листу:

# 1. Что есть в remote?
git remote -v

# 2. Какие remote-tracking branches у меня?
git branch -r

# 3. Все ветки сразу — локальные + remote
git branch -a

# 4. Полная инфо про remote
git remote show origin

Команда git remote show origin сходит на сервер и покажет очень полезное:

$ git remote show origin
* remote origin
  Fetch URL: [email protected]:acme/data-pipelines.git
  Push  URL: [email protected]:acme/data-pipelines.git
  HEAD branch: main
  Remote branches:
    main      tracked
    develop   tracked
    feature/x tracked
  Local branches configured for 'git pull':
    main    merges with remote main
    develop merges with remote develop
  Local refs configured for 'git push':
    main    pushes to main    (up to date)

Это полный отчёт: какие ветки есть на сервере, какие из них ты трекаешь, какая HEAD branch (default branch проекта).


Попробуй сам

# Создай локальный репо
mkdir remote-demo && cd remote-demo
git init
echo "hello" > README.md
git add . && git commit -m "init"

# Добавь несуществующий remote (Git не проверяет — это просто запись в config)
git remote add origin [email protected]:fake/repo.git
git remote -v

# Посмотри config
cat .git/config

# Удали remote
git remote remove origin
cat .git/config

Заметь: git remote add не делает запросов в сеть. Ты можешь добавить remote с любым URL — Git проверит его, только когда ты сделаешь fetch/push.


curl, wget: HTTP-запросы из командной строки
Проверка знанийKnowledge check
У тебя в проекте `git status` пишет: `Your branch is ahead of 'origin/main' by 7 commits`. Ты заходишь на GitHub и видишь, что в `main` за это время добавились ещё 3 коммита от коллеги. Почему `git status` этого не показал?
ОтветAnswer
Потому что `origin/main` — это локальная remote-tracking branch, snapshot того, что Git видел при последнем `fetch`. `git status` сравнивает твою локальную `main` с этим snapshot, а не лезет в сеть. Чтобы Git узнал об изменениях коллеги, нужно `git fetch` — тогда `origin/main` обновится, и `git status` покажет реальное состояние: `Your branch and 'origin/main' have diverged, and have 7 and 3 different commits each`. Это фундамент distributed VCS: Git не делает скрытых сетевых запросов, ты явно управляешь синхронизацией.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. Что такое remote с точки зрения Git?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5