Программирование и IT

git push

Пока ты не выполнил git push, твои коммиты существуют только на твоём диске. Команда отправляет их в удалённый репозиторий и сдвигает там указатель ветки — поэтому она же чаще всего и отказывает, если кто-то успел отправить своё раньше.

Обновлено
В этой статье

Что уезжает на сервер#

Отправляются коммиты — те, которых на сервере ещё нет, — и новое положение
указателя ветки. Незакоммиченные правки, файлы из рабочего каталога и
содержимое индекса не уезжают никуда: сначала git commit,
потом отправка.

Сервер принимает изменение, только если оно продолжает уже имеющуюся там
историю. Такое продолжение называют перемоткой вперёд, fast-forward. Если
серверная ветка ушла вперёд или твоя история переписана, git остановится и
ничего не тронет — это главная защита от потери чужой работы.

Синтаксис и ключи#

git push <источник> <ветка>

Чаще всего источник называется origin, а ветка совпадает с текущей.
Когда у ветки есть связь с серверной (upstream), хватает короткого
git push.

Ключ Зачем
-u, --set-upstream отправить и связать ветку с серверной — нужен один раз
--force-with-lease переписать серверную ветку, но только если на ней нет неизвестных тебе коммитов
-f, --force переписать без всяких условий, чужая работа может исчезнуть
--tags отправить теги, которые обычным push не уходят
--delete <ветка> удалить ветку на сервере
-n, --dry-run показать, что произошло бы, но ничего не менять

Пример: первая отправка новой ветки#

git switch -c feature/login
git add login.py
git commit -m "Форма входа"
git push -u origin feature/login
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 512 bytes | 512.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0)
To https://github.com/example/notes.git
 * [new branch]      feature/login -> feature/login
branch 'feature/login' set up to track 'origin/feature/login'.

Без -u git напомнит о себе сам:

fatal: The current branch feature/login has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin feature/login

Дальше для этой ветки достаточно git push без аргументов.

Отказ non-fast-forward#

Самая частая картина: пока ты работал, в ветку на сервере попал чужой
коммит.

To https://github.com/example/notes.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/example/notes.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally.

Пометка бывает fetch first, а бывает non-fast-forward — вторая
появляется, когда твоя история разошлась с серверной, например после
--amend или перебазирования. Решение одно и то же: сначала забрать чужое,
потом отправить своё.

git pull --rebase
git push

Перебазирование перенесёт твои коммиты поверх чужих, и отправка станет
обычной перемоткой. Подробности — в статье про git pull.
Отвечать на такой отказ ключом --force нельзя: он стирает с сервера
именно те коммиты, из-за которых отказ и возник.

Когда переписать всё-таки нужно#

Бывает законно: ты поправил сообщение своего последнего коммита в личной
ветке, которую никто не смотрит. Тогда вместо --force берут его
осторожного родственника:

git push --force-with-lease origin feature/login

Ключ сверяет, что серверная ветка стоит там, где ты её видел в последний
раз. Появился чужой коммит — отправка отклоняется с stale info, и ты
разбираешься, а не затираешь. В общей ветке вроде main не стоит
переписывать историю вовсе.

Как отозвать отправленное#

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

git revert 9d31c07
git push

Появится новый коммит, отменяющий действие прежнего. История остаётся
непрерывной, ни у кого не ломаются копии.

Ошибочно созданную ветку убирают целиком:

git push origin --delete feature/login

А случайно отправленный тег — командой git push origin --delete v1.4.
Помни, что отправленное на общий сервер может быть уже скачано, и секрет,
попавший в коммит, считается скомпрометированным независимо от того, что ты
сделаешь с историей: пароль или токен нужно менять, а не прятать. Остальные
команды обмена перечислены в шпаргалке.

План по этапам

  1. Убедиться, что всё закоммиченоgit status: незакоммиченные правки на сервер не уезжают.
  2. Забрать чужоеgit pull --rebase, чтобы твои коммиты легли поверх серверных.
  3. Отправить с привязкойПервый раз git push -u origin ветка, дальше просто git push.
  4. Прочитать ответ сервераСтрока new branch или диапазон хешей — принято; rejected — читать подсказку.
  5. Исправлять отменой, а не силойgit revert для общих веток, --force-with-lease только для своих.

Начать изучать эту тему у себя

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

Начать план

Проверь себя

1.Первая отправка новой ветки: какая команда и отправит её, и свяжет с серверной?

2.Push отклонён с пометкой non-fast-forward. Что сделать сначала?

3.Чем --force-with-lease лучше обычного --force?

Источники

Было полезно?

Ещё темы

Программирование и IT git stash Заначка — временная полка для незаконченных правок. Ты кладёшь туда всё, что наработал, получаешь чистую рабочую копию, делаешь срочное дело и возвращаешь отложенное обратно. Полка общая на весь репозиторий и устроена как стопка: последнее положенное лежит сверху. Программирование и IT git merge Слияние переносит работу из одной ветки в другую. Команда git merge берёт указанную ветку и соединяет её историю с текущей — иногда просто сдвигая указатель, иногда создавая отдельный коммит, а иногда останавливаясь и прося помощи. Программирование и IT git clone Команда git clone забирает репозиторий с сервера целиком — со всей историей, ветками и тегами — и кладёт копию в новую папку на твоём компьютере. С неё начинается работа с любым уже существующим проектом, своим или чужим. Программирование и IT git commit Коммит — это сохранённое состояние проекта с автором, временем и сообщением. Команда git commit берёт то, что ты заранее отобрал командой git add, и записывает это в историю одной неделимой порцией. Программирование и IT git pull Команда git pull приносит из удалённого репозитория чужие коммиты и сразу вливает их в твою текущую ветку. Это две операции подряд, и почти все трудности с pull растут из второй — из того, каким способом он соединяет истории. Программирование и IT Как создать репозиторий с нуля Репозиторий — это папка проекта плюс скрытая папка `.git`, в которой хранится вся история. Создаётся одной командой, но между ней и первым осмысленным коммитом есть несколько шагов, которые потом трудно переделать: имя ветки, список игнорируемых файлов, привязка к серверу.

Ещё сценарии