Иконка подарка

Весенняя распродажа! Скидка 15% по промокоду

до 01.04.2026

Отправка изменений git push

27 марта 2026
Автор

Олег Марков

Введение

Команда git push отвечает за отправку ваших локальных изменений на удаленный репозиторий. Это тот момент, когда коммиты из вашего локального репозитория становятся доступны другим участникам команды или, например, попадают на GitHub или GitLab.

Смотрите, здесь важно понять одну простую вещь: git push ничего не делает с вашим рабочим каталогом и индексом. Он работает только с уже созданными локальными коммитами и переносит их в удаленный репозиторий. Если коммитов нет, отправлять просто нечего.

В этой статье вы шаг за шагом разберете:

  • как работает связь локальных и удаленных веток;
  • базовый и расширенный синтаксис git push;
  • как отправлять отдельные ветки, все ветки, теги;
  • что значит отслеживаемая ветка и upstream;
  • чем отличаются параметры --force и --force-with-lease;
  • как решать типичные ошибки при push.

Я буду опираться на практические примеры, чтобы вы могли сразу повторить команды у себя.


Базовые понятия перед git push

Локальный и удаленный репозиторий

Перед тем как делать git push, у вас уже должен быть:

  • локальный репозиторий (каталог с подпапкой .git);
  • настроенный удаленный репозиторий (обычно с именем origin).

Посмотрите небольшой пример создания локального репозитория и привязки к удаленному:

git init                                # Инициализация локального репозитория
git remote add origin https://github.com/user/project.git
# Добавляем удаленный репозиторий и даем ему имя origin

Теперь origin — это просто ярлык (алиас) для URL. Команда git push будет использовать этот алиас, когда вы будете отправлять изменения.

Что именно отправляет git push

Git push отправляет:

  • коммиты из локального репозитория;
  • ссылки на ветки (refs/heads/...) и теги (refs/tags/...) в удаленный репозиторий;
  • иногда обновляет связку "локальная ветка ↔ удаленная ветка".

Важно: git push не отправляет незакоммиченные изменения. Если у вас есть измененные файлы, но вы их не добавили и не закоммитили, push их просто проигнорирует.

Давайте разберемся на простом сценарии:

git status
# Видим измененные файлы, но пока без коммита

git add main.go
# Добавляем файл в индекс

git commit -m "Добавить базовую логику"
# Создаем коммит с изменениями

git push origin main
# Отправляем этот коммит в удаленный репозиторий

Без шага с коммитом git push не отправит ваши изменения.

Отслеживаемые ветки и upstream

Когда вы работаете с веткой main и отправляете ее на origin, Git может связать локальную ветку main с удаленной веткой origin/main. Такая локальная ветка называется отслеживаемой (tracking branch), а удаленная ветка — ее upstream.

Смотрите, как это выглядит:

git push -u origin main
# Ключ -u настраивает upstream для текущей ветки

После этого:

  • локальная ветка main знает, что ее "родитель" — origin/main;
  • вы можете использовать короткую форму git push без параметров;
  • команда git status сможет показывать, насколько локальная ветка впереди или позади удаленной.

Синтаксис и варианты использования git push

Общий синтаксис команды

Общий вид команды:

git push <remote> <local_ref>:<remote_ref>

Где:

  • — имя удаленного репозитория (обычно origin);
  • <local_ref> — локальная ветка или тег, который вы отправляете;
  • <remote_ref> — имя ветки (или тега) в удаленном репозитории, которое будет обновлено.

Простой пример:

git push origin main:main
# Отправить локальную ветку main в удаленную ветку main репозитория origin

Если имена совпадают, вы можете писать короче:

git push origin main
# То же самое, что main:main

Самый частый вариант: git push без аргументов

После того как вы настроили upstream (например, через git push -u origin main), вы можете просто писать:

git push
# Отправить текущую ветку в ее upstream

Git сам:

  • возьмет текущую ветку (HEAD);
  • посмотрит, какая удаленная ветка у нее указана как upstream;
  • обновит ее.

Это удобно в повседневной работе, когда вы постоянно пушите одну и ту же ветку.


Отправка веток

Отправка текущей ветки в первый раз

Представим, что вы создали новую ветку feature/login:

git checkout -b feature/login
# Создаем и переключаемся на новую ветку

# Вносим изменения в код, делаем несколько коммитов

git push -u origin feature/login
# Отправляем ветку на удаленный репозиторий и настраиваем upstream

Комментарий к шагам:

  • checkout -b создает локальную ветку;
  • первый push с -u создает удаленную ветку origin/feature/login и "связывает" ее с локальной;
  • в дальнейшем, находясь в этой ветке, вы сможете просто вызывать git push и git pull.

Отправка конкретной ветки с указанием имени

Вы не обязаны находиться в ветке, чтобы ее отправить:

git branch
# * main
#   dev
#   feature/login

git push origin dev
# Отправляем ветку dev в origin/dev, находясь в ветке main

Так вы можете пушить разные ветки, не переключаясь между ними.

Создание ветки в удаленном репозитории с другим именем

Иногда вам нужно, чтобы имя ветки в удаленном репозитории отличалось от локального. Покажу, как это сделать:

git push origin feature/login:feature/user-login
# Локальная ветка feature/login => удаленная ветка feature/user-login

После этого:

  • в локальном репозитории остается ветка feature/login;
  • в удаленном появляется новая ветка feature/user-login;
  • локальная ветка не становится отслеживаемой автоматически, если вы не добавите -u.

Если вы хотите сразу настроить upstream на ветку с другим именем:

git push -u origin feature/login:feature/user-login
# Локальная ветка будет отслеживать origin/feature/user-login

Отправка всех веток и зеркальное обновление

Отправка всех локальных веток

Иногда вам нужно отправить все локальные ветки в удаленный репозиторий:

git push origin --all
# Отправляем все локальные ветки в origin

Эта команда:

  • создаст в удаленном репозитории те ветки, которых там еще нет;
  • обновит те ветки, которые уже есть и "отстают" от локальных.

Но с ней стоит быть осторожнее: вы можете случайно опубликовать служебные или "черновые" ветки.

Зеркальное обновление: git push --mirror

Зеркальный push — более жесткий вариант:

git push --mirror origin
# Зеркально синхронизируем все ссылки (ветки, теги, удаленные ветки) с origin

Что делает --mirror:

  • удаляет в удаленном репозитории те ветки и теги, которых больше нет локально;
  • обновляет все ветки и теги, делая удаленный репозиторий точной копией локального.

Эта команда используется редко, обычно для обслуживания зеркал репозиториев или при миграции. В обычной продуктовой разработке лучше использовать точечные push.


Отправка тегов

Отправка одного тега

Тег в Git — это ссылка на конкретный коммит. Смотрите, как создать и отправить тег:

git tag v1.0.0
# Создаем простой тег v1.0.0 на текущем коммите

git push origin v1.0.0
# Отправляем тег в удаленный репозиторий

После этого тег появится в списке релизов/тегов на GitHub или другом хостинге.

Отправка всех тегов разом

Если у вас много тегов, вы можете отправить их одной командой:

git push origin --tags
# Отправляем все локальные теги, которые еще не были отправлены

Обратите внимание: --tags не трогает ветки, он работает только с тегами.

Удаление тега на удаленном репозитории

Если вы ошиблись с тегом, его можно удалить на стороне сервера:

git push origin :refs/tags/v1.0.0
# Удаляем тег v1.0.0 в удаленном репозитории

# Более короткая и удобная форма
git push origin :v1.0.0
# Пустое имя слева от двоеточия означает удаление ссылки на сервере

Удаление веток через git push

Удалить ветку на удаленном репозитории тоже можно через git push. Здесь используется синтаксис с "пустой" левой частью:

git push origin :feature/login
# Удаляем ветку feature/login в origin

# Эквивалентная запись (некоторые предпочитают именно такую)
git push origin --delete feature/login

Краткое разъяснение:

  • origin — удаленный репозиторий;
  • :feature/login — "установить" ветку feature/login на сервере в пустое значение, по сути удалить ее.

Важно: это не удаляет локальную ветку. Чтобы убрать ее локально:

git branch -d feature/login
# Удаляем локальную ветку, если она уже слита с основной

git branch -D feature/login
# Принудительное удаление локальной ветки, даже если она не слита

Политики push и защита истории

Что такое fast-forward push

По умолчанию git push позволяет только fast-forward обновления. Это значит:

  • история в удаленной ветке — прямая линия;
  • ваши новые коммиты просто "добавляются" к концу этой линии;
  • вы не переписываете уже существующие коммиты на сервере.

Схематично:

  • было: A → B → C (на сервере)
  • стало: A → B → C → D → E (после вашего push)

Это безопасный сценарий: никто не теряет историю.

Когда push отклоняется

Git откажет в push, если ваша локальная ветка "расходится" с удаленной. Типичный пример:

  • на сервере: A → B → C → D
  • у вас локально: A → B → C → E

Здесь ветка разошлась: у сервера коммит D, у вас — E, они оба основаны на C, но дальше пошли разными путями. В этом случае при git push вы увидите ошибку, что сначала нужно забрать изменения (git pull) и разрешить конфликт.


Принудительный push: --force и --force-with-lease

Иногда вам нужно переписать историю в удаленной ветке, например после git rebase. Именно тогда появляется соблазн использовать принудительный push.

git push --force

Команда:

git push --force origin main
# С силой перезаписываем ветку main на сервере

Что происходит:

  • удаленная ветка origin/main "откатывается" и выравнивается под ваши локальные коммиты;
  • если кто-то уже успел запушить свои коммиты в main, вы можете их затереть.

Поэтому --force потенциально опасен в командной работе.

git push --force-with-lease

Более безопасный вариант:

git push --force-with-lease origin main
# Принудительный push с проверкой, что удаленная ветка не изменилась "мимо вас"

Механика:

  • Git проверяет, что состояние origin/main на сервере совпадает с тем, которое вы видели последний раз (то, что у вас закешировано как origin/main);
  • если кто-то уже успел обновить origin/main, push отклоняется;
  • вы не перезатрете чужие коммиты "вслепую".

В командах обычно рекомендуют:

  • не использовать --force на общих ветках (main, develop);
  • если очень нужно — использовать только --force-with-lease;
  • активно использовать force только в личных фиче-ветках, пока вы единственный, кто с ними работает.

Настройка поведения git push по умолчанию

Git имеет глобальную настройку push.default, которая определяет, как ведет себя git push без аргументов (когда вы пишете просто git push).

Покажу, как посмотреть текущее значение:

git config --global push.default
# Выведет, например, simple или upstream

Рассмотрим основные варианты.

Режим simple (по умолчанию)

Режим simple — это стандарт по умолчанию в новых версиях Git. Он делает следующее:

  • позволяет пушить только в ветку с тем же именем, что и текущая локальная;
  • требует, чтобы для ветки был настроен upstream;
  • если upstream не совпадает по имени, push отклоняется.

Команда для явной установки:

git config --global push.default simple
# Устанавливаем режим simple для всех репозиториев

Этот режим помогает избежать случайных пушей в "чужие" ветки.

Режим upstream

Режим upstream позволяет:

  • пушить в ту ветку, которая указана как upstream для текущей;
  • имена веток могут отличаться.

Настройка:

git config --global push.default upstream
# Git будет пушить в ту ветку, которую текущая отслеживает

Полезно, если вы часто связываете локальные ветки с удаленными под другим именем.

Другие режимы (для понимания)

Есть и другие значения, которые реже используются:

  • matching — пушить все ветки, у которых есть совпадающие имена в удаленном репозитории;
  • current — пушить текущую ветку в ветку с тем же именем (даже если upstream не настроен);
  • nothing — git push без аргументов ничего не делает, вы всегда должны явно указывать refspec.

В большинстве рабочих сценариев достаточно simple или upstream.


Типичный рабочий цикл с git push

Давайте посмотрим типичный цикл от создания ветки до отправки изменений:

git checkout -b feature/profile
# 1. Создаем новую ветку для фичи

# 2. Вносим изменения в код, добавляем файлы
git add .
# Добавляем все измененные файлы в индекс

git commit -m "Добавить страницу профиля пользователя"
# 3. Создаем локальный коммит с осмысленным сообщением

git push -u origin feature/profile
# 4. Отправляем ветку на сервер и настраиваем upstream

# 5. В дальнейшем просто пушим обновления
git push
# Отправляем новые коммиты, не указывая ветку

Комментарии здесь важны:

  • вы изолируете работу в отдельной ветке feature/profile;
  • upstream позволяет вам использовать короткие формы git push и git pull;
  • команда git status наглядно покажет, насколько вы опережаете origin/feature/profile.

Работа с форками и git push

Когда вы работаете через форк на GitHub/GitLab, у вас обычно два удаленных репозитория:

  • origin — ваш форк;
  • upstream — оригинальный репозиторий.

Посмотрим пример настройки:

git remote -v
# origin   https://github.com/yourname/project.git (fetch)
# origin   https://github.com/yourname/project.git (push)

git remote add upstream https://github.com/original/project.git
# Добавляем оригинальный репозиторий как upstream

Теперь:

  • git push origin feature/login — отправляет ваши изменения в ваш форк;
  • git push upstream ... — обычно не используется, так как прав на запись туда нет.

Цикл работы будет примерно такой:

git checkout -b feature/login
# Создаем ветку для фичи на основе main

# Вносим изменения и делаем коммиты

git push -u origin feature/login
# Отправляем ветку в свой форк

# Дальше вы создаете Pull Request из ветки feature/login вашего форка в ветку main оригинального репозитория

Git push здесь по-прежнему отправляет изменения только в тот удаленный репозиторий, к которому у вас есть права записи, чаще всего в origin.


Типичные ошибки при git push и их решение

Ошибка: non-fast-forward

Сообщение может выглядеть так:

! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs
hint: Updates were rejected because the tip of your current branch is behind

Это как раз ситуация, когда история расходится. Чтобы разобраться, действуем так:

  1. Забираем изменения с сервера:

    git pull --rebase origin main
    # Подтягиваем изменения, аккуратно "поверх" накатываем свои коммиты
    
  2. Разрешаем конфликты, если они есть:

    # Редактируем конфликтующие файлы, удаляем конфликтные маркеры
    git add конфликтующий_файл.go
    # Подтверждаем, что конфликт разрешен
    
    git rebase --continue
    # Продолжаем процесс rebase
    
  3. После успешного rebase отправляем изменения:

    git push origin main
    # Теперь история стала "линейной", и push пройдет
    

Использование pull --rebase чаще дает более аккуратную историю, чем простой merge.

Ошибка аутентификации

Вы можете увидеть:

fatal: Authentication failed for 'https://github.com/...'

Возможные шаги решения:

  1. Проверить правильность URL:

    git remote -v
    # Убедитесь, что адрес корректен
    
  2. Если вы используете HTTPS и токены доступа:

    • убедитесь, что токен актуален и имеет нужные права;
    • в системном менеджере учетных данных удалите старые записи и введите новые данные при следующем push.
  3. Переключиться на SSH и настроить ключи:

    git remote set-url origin git@github.com:user/project.git
    # Меняем URL на SSH-формат
    

    Дальше убедитесь, что:

    • у вас создан SSH-ключ;
    • открытый ключ добавлен в настройки GitHub/GitLab.

Ошибка: нет такой ветки на сервере

Если вы пытаетесь сделать git push без указания -u на новой ветке, иногда вы увидите подсказку вида:

fatal: The current branch feature/login has no upstream branch.

Решение:

git push -u origin feature/login
# Первый push с настройкой upstream

После этого простого git push будет достаточно.


Резюме и ключевые моменты

Git push — это команда, которая переносит ваши локальные коммиты в удаленный репозиторий и обновляет ссылки на ветки и теги. Для уверенной работы с ней важно понимать несколько принципов:

  • push всегда отправляет только закоммиченные изменения;
  • связь локальной и удаленной ветки настраивается через upstream (ключ -u);
  • по умолчанию Git требует fast-forward обновления, чтобы не ломать историю;
  • принудительный push (--force, --force-with-lease) нужно использовать осторожно и осознанно;
  • удаление веток и тегов на сервере по сути тоже делается через git push со специальным синтаксисом;
  • поведение git push без аргументов настраивается через параметр push.default.

Если вы понимаете, как именно git push обновляет удаленные ветки, вам будет легче читать сообщения об ошибках, выбирать правильные флаги и не ломать общую историю репозитория.


Частозадаваемые технические вопросы по теме и ответы

Как отправить только выбранные коммиты, а не всю ветку

Иногда вы хотите отправить не все коммиты ветки, а только их подмножество. Один из вариантов:

  1. Создайте временную ветку от того коммита, куда хотите "доставить" изменения:

    git checkout -b temp target-commit
    # temp — новая ветка, target-commit — коммит, на который вы хотите опереться
    
  2. Перенесите нужные коммиты с помощью cherry-pick:

    git cherry-pick <hash1> <hash2>
    # Переносим только выбранные коммиты
    
  3. Отправьте ветку temp:

    git push -u origin temp
    

Дальше уже из этой ветки можно делать Pull Request.

Как отменить уже выполненный git push

Если вы запушили лишние коммиты:

  1. Найдите хеш "правильного" коммита (то есть того, к которому хотите откатиться):

    git log
    # Смотрите историю и выбираете нужный hash
    
  2. Переместите локальную ветку:

    git reset --hard <good_hash>
    # Откатываемся локально к нужному коммиту
    
  3. Принудительно обновите ветку на сервере:

    git push --force-with-lease origin ваша_ветка
    

Учтите, что это перепишет историю ветки для всех.

Как запретить себе случайный git push в основную ветку

Один из подходов — работать только через защищенные ветки на сервере, но можно добавить и локальную защиту:

  1. Создайте локальный hook pre-push:

    nano .git/hooks/pre-push
    
  2. Добавьте простой скрипт, который запретит push в main:

    #!/bin/sh
    while read local_ref local_sha remote_ref remote_sha
    do
      case "$remote_ref" in
        refs/heads/main)
          echo "Push в main запрещен"
          exit 1
          ;;
      esac
    done
    
  3. Сделайте hook исполняемым:

    chmod +x .git/hooks/pre-push
    

Теперь git push в main будет блокироваться на вашем локальном репозитории.

Как отправить изменения сразу в несколько удаленных репозиториев

Git push работает с одним remote за раз, но вы можете объединить несколько URL под одним именем:

  1. Добавьте второй URL к origin:

    git remote set-url --add --push origin git@github.com:user/project.git
    git remote set-url --add --push origin git@gitlab.com:user/project.git
    
  2. Теперь при git push origin ваши изменения будут отправляться сразу в оба репозитория. Если нужно пушить по одному — заведите отдельные remotes (github, gitlab) и вызывайте git push для каждого.

Стрелочка влевоУдаление удаленного репозитория в Git - git remote removeПолучение и слияние в Git - команда git pullСтрелочка вправо

Постройте личный план изучения Git до уровня Middle — бесплатно!

Git — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Git

Открыть базу знаний

Лучшие курсы по теме

изображение курса

Основы Git

Антон Ларичев
AI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий