Русский ▾ Topics ▾ Latest version ▾ git-push last updated in 2.53.0

НАЗВАНИЕ

git-push - Обновление внешних ссылок и связанных объектов

ОБЗОР

git push [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<пакет-получения-git>]
	 [--repo=<репозиторий>] [-f | --force] [-d | --delete] [--prune] [-q | --quiet] [-v | --verbose]
	 [-u | --set-upstream] [-o <строка> | --push-option=<строка>]
	 [--[no-]signed | --signed=(true|false|if-asked)]
	 [--force-with-lease[=<имя-ссылки>[:<ожидаемое>]] [--force-if-includes]]
	 [--no-verify] [<репозиторий> [<спецификатор-ссылки>…​]]

ОПИСАНИЕ

Обновляет одну или несколько веток, меток или других ссылок во внешнем (remote) репозитории из вашего локального репозитория и отправляет все необходимые данные, которых ещё нет во внешнем репозитории.

Самый простой способ отправить изменения — git push <внешний-репозиторий> <ветка>. git push origin main отправит локальную ветку main в ветку main во внешнем репозитории с именем origin.

Аргумент <репозиторий> по умолчанию указывает на вышестоящий (upstream) репозиторий для текущей ветки или на origin, если вышестоящий репозиторий не настроен.

Чтобы решить, какие ветки, метки или другие ссылки отправлять, Git использует (в порядке приоритета):

  1. Аргумент(ы) <спецификатор-ссылки> (например, main в git push origin main) или параметры --all, --mirror или --tags

  2. Конфигурация remote.<имя>.push для репозитория, в который выполняется отправка

  3. Конфигурация push.default. Значение по умолчанию — push.default=simple, которое отправляет изменения в ветку с тем же именем, что и текущая ветка. См. раздел КОНФИГУРАЦИЯ ниже для получения дополнительной информации о push.default.

git push может завершиться сбоем, если вы не установили вышестоящую (upstream) ветку для текущей ветки, в зависимости от того, на что установлен push.default. См. раздел ВЫШЕСТОЯЩИЕ ВЕТКИ ниже для получения дополнительной информации о том, как устанавливать и использовать вышестоящие ветки.

Вы можете заставить репозиторий выполнять интересные действия каждый раз, когда вы отправляете в него изменения, настроив там перехватчики (hooks). См. документацию по git-receive-pack[1].

ПАРАМЕТРЫ

<репозиторий>

«Внешний» (remote) репозиторий, являющийся целью операции отправки (push). Этот параметр может быть либо URL-адресом (см. раздел URL-АДРЕСА GIT ниже), либо именем внешнего репозитория (см. раздел ВНЕШНИЕ РЕПОЗИТОРИИ ниже).

<refspec>...

Указывает, какую целевую ссылку обновлять с помощью какого исходного объекта.

Формат спецификатора ссылки (refspec): [+]<источник>[:<назначение>], например main, main:other или HEAD^:refs/heads/main.

<источник> часто является именем локальной ветки для отправки, но это может быть любое произвольное «выражение SHA-1» (см. gitrevisions[7]).

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

+ необязателен и делает то же самое, что и --force.

Вы можете написать спецификатор ссылки, используя полностью развёрнутую форму (например, refs/heads/main:refs/heads/main), которая указывает точный источник и назначение, или более короткую форму (например, main или main:other). Вот правила того, как разворачиваются спецификаторы ссылок, а также различные другие специальные формы спецификаторов ссылок:

  • <источник> без :<назначение> означает обновление той же ссылки, что и <источник>, если только конфигурация remote.<репозиторий>.push не указывает другое <назначение>. Например, если main — это ветка, то спецификатор ссылки main разворачивается в main:refs/heads/main.

  • Если <назначение> однозначно ссылается на ссылку во внешнем репозитории <репозиторий>, то развернуть его в эту ссылку. Например, если v1.0 — это метка во внешнем репозитории, то HEAD:v1.0 разворачивается в HEAD:refs/tags/v1.0.

  • Если <источник> преобразуется в ссылку, начинающуюся с refs/heads/ или refs/tags/, то добавить это префикс к <назначение>. Например, если main — это ветка, то main:other разворачивается в main:refs/heads/other

  • Специальный спецификатор ссылки : (или +: для разрешения обновлений, отличных от перемотки вперёд) указывает Git отправлять «совпадающие» ветки: для каждой ветки, существующей на локальной стороне, внешняя сторона обновляется, если ветка с таким же именем уже существует на внешней стороне.

  • <источник> может содержать * для указания простого сопоставления с образцом. Это работает как glob-шаблон, который соответствует любой ссылке, подходящей под образец. В <источник> и <назначение> должен быть только один *. Он будет сопоставлять ссылки с назначением, заменяя * содержимым, соответствующим источнику. Например, refs/heads/*:refs/heads/* отправит все ветки.

  • Спецификатор ссылки, начинающийся с ^, является отрицательным спецификатором ссылки. Он указывает ссылки для исключения. Ссылка будет считаться соответствующей, если она соответствует хотя бы одному положительному спецификатору ссылки и не соответствует ни одному отрицательному спецификатору ссылки. Отрицательные спецификаторы ссылок могут быть шаблонными спецификаторами ссылок. Они должны содержать только <источник>. Полностью записанные шестнадцатеричные имена объектов также не поддерживаются. Например, git push origin refs/heads/*' ^refs/heads/dev-*' отправит все ветки, кроме тех, которые начинаются с dev-

  • Если <источник> пуст, он удаляет ссылку <назначение> из внешнего репозитория. Например, git push origin :dev удалит ветку dev.

  • tag <метка> разворачивается в refs/tags/<метка>:refs/tags/<метка>. Технически это специальный синтаксис для git push, а не спецификатор ссылки, поскольку в git push origin tag v1.0 аргументы tag и v1.0 являются отдельными.

  • Если спецификатор ссылки не может быть однозначно развёрнут, завершиться с ошибкой, указывающей, что было предпринято, и, в зависимости от конфигурации advice.pushUnqualifiedRefname (см. git-config[1]), предложить, в какое пространство имён refs/ вы, возможно, хотели отправить.

Не все обновления разрешены: подробности см. в разделе ПРАВИЛА ОТПРАВКИ ниже.

--all
--branches

Отправить все ветки (т.е. ссылки в refs/heads/); нельзя использовать с другими <спецификатор-ссылки>.

--prune

Удалить внешние ветки, у которых нет локального аналога. Например, внешняя ветка tmp будет удалена, если локальной ветки с таким же именем больше не существует. Это также учитывает спецификаторы ссылок, например, git push --prune внешний-репозиторий refs/heads/*:refs/tmp/* гарантирует, что внешняя refs/tmp/foo будет удалена, если refs/heads/foo не существует.

--mirror

Вместо указания каждой отправляемой ссылки указывает, что все ссылки в refs/ (что включает, но не ограничивается refs/heads/, refs/remotes/ и refs/tags/) должны быть зеркально отражены во внешнем репозитории. Новые локальные ссылки будут отправлены на внешнюю сторону, локально обновлённые ссылки будут принудительно обновлены на внешней стороне, а удалённые ссылки будут удалены с внешней стороны. Это значение по умолчанию, если установлен параметр конфигурации remote.<внешний-репозиторий>.mirror.

-n
--dry-run

Сделать всё, кроме фактической отправки обновлений.

--porcelain

Выдавать машиночитаемый вывод. Строка состояния вывода для каждой ссылки будет разделена табуляцией и отправлена в stdout вместо stderr. Будут предоставлены полные символические имена ссылок.

-d
--delete

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

--tags

Все ссылки в refs/tags отправляются в дополнение к спецификаторам ссылок, явно указанным в командной строке.

--follow-tags

Отправить все ссылки, которые были бы отправлены без этого параметра, а также отправить аннотированные метки в refs/tags, которых нет во внешнем репозитории, но которые указывают на указатели коммитов (commit-ish), достижимые из отправляемых ссылок. Это также можно указать с помощью переменной конфигурации push.followTags. Для получения дополнительной информации смотрите push.followTags в git-config[1].

--signed
--no-signed
--signed=(true|false|if-asked)

Подписать GPG запрос на отправку (push) для обновления ссылок на принимающей стороне, чтобы позволить перехватчикам (hooks) проверить его и/или зарегистрировать в журнале. Возможные значения:

false
--no-signed

подписание не будет предпринято.

true
--signed

отправка завершится сбоем, если сервер не поддерживает подписанные отправки.

if-asked

подписывать тогда и только тогда, когда сервер поддерживает подписанные отправки. Отправка также завершится сбоем, если фактический вызов gpg --sign завершится сбоем. Подробности о принимающей стороне смотрите в git-receive-pack[1].

--atomic
--no-atomic

Использовать атомарную транзакцию на внешней стороне, если доступно. Либо обновляются все ссылки, либо в случае ошибки не обновляется ни одна ссылка. Если сервер не поддерживает атомарные отправки, отправка завершится сбоем.

-o <параметр>
--push-option=<option>

Передать данную строку на сервер при обмене данными по протоколу версии 2. Данная строка не должна содержать символы NUL или LF. Если параметр --push-option=<параметры> указан несколько раз, то все эти строки будут отправлены другой стороне в том порядке, в котором они указанном в командной строке. Если в командной строке параметр --push-option=<параметры> не задан ни разу, то вместо этого будет использовано значения переменной конфигурации push.pushOption.

--receive-pack=<пакет-получения-git>
--exec=<git-receive-pack>

Путь к программе git-receive-pack на внешней стороне. Иногда полезно при отправке во внешний репозиторий по ssh, и у вас нет этой программы в каталоге, находящемся в стандартном $PATH.

--force-with-lease
--no-force-with-lease
--force-with-lease=<refname>
--force-with-lease=<refname>:<expect>

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

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

Представьте, что вам нужно переместить (rebase) то, что вы уже опубликовали. Вам придётся обойти правило «обязательно перемотки вперёд», чтобы заменить историю, которую вы изначально опубликовали, на перемещённую историю. Если кто-то другой основал свою работу на вашей исходной истории, пока вы перемещали, верхушка (tip) ветки во внешнем репозитории может продвинуться с их коммитом, и слепая отправка с --force приведёт к потере их работы.

Этот параметр позволяет вам указать, что вы ожидаете, что обновляемая вами история — это та, которую вы переместили и хотите заменить. Если внешняя ссылка всё ещё указывает на указанный вами коммит, вы можете быть уверены, что никто другой не делал ничего с этой ссылкой. Это похоже на взятие «аренды» (lease) на ссылку без её явной блокировки, и внешняя ссылка обновляется, только если «аренда» всё ещё действительна.

--force-with-lease сам по себе, без указания деталей, защитит все внешние ссылки, которые будут обновлены, требуя, чтобы их текущее значение совпадало с отслеживаемой внешней веткой (remote-tracking branch), которая у нас есть для них.

--force-with-lease=<имя-ссылки>, без указания ожидаемого значения, защитит <имя-ссылки> (отдельно), если оно будет обновлено, требуя, чтобы его текущее значение совпадало с отслеживаемой внешней веткой, которая у нас есть для неё.

--force-with-lease=<имя-ссылки>:<ожидаемое> защитит <имя-ссылки> (отдельно), если оно будет обновлено, требуя, чтобы его текущее значение совпадало с указанным значением <ожидаемое> (которое может отличаться от отслеживаемой внешней ветки, которая у нас есть для этого имени ссылки, или при использовании этой формы у нас может даже не быть такой отслеживаемой внешней ветки). Если <ожидаемое> — пустая строка, то указанная ссылка не должна уже существовать.

Обратите внимание, что все формы, кроме --force-with-lease=<имя-ссылки>:<ожидаемое>, которая явно указывает ожидаемое текущее значение ссылки, всё ещё являются экспериментальными, и их семантика может измениться по мере накопления опыта работы с этой функцией.

--no-force-with-lease отменяет все предыдущие --force-with-lease в командной строке.

Общее замечание по безопасности: использование этого параметра без ожидаемого значения, т.е. как --force-with-lease или --force-with-lease=<имя-ссылки>, очень плохо взаимодействует с любым процессом, который неявно выполняет git fetch для внешнего репозитория, в который выполняется отправка, в фоновом режиме, например, git fetch origin для вашего репозитория в задании cron.

Защита, которую он предлагает по сравнению с --force, заключается в обеспечении того, что последующие изменения, на которых ваша работа не основывалась, не будут затёрты, но это легко нарушается, если какой-либо фоновый процесс обновляет ссылки в фоне. У нас нет ничего, кроме информации об отслеживаемых внешних ветках, чтобы использовать в качестве эвристики для ссылок, которые вы, как ожидается, видели и готовы затёрть.

Если ваш редактор или какая-то другая система выполняет git fetch в фоне за вас, способ смягчить это — просто настроить другой внешний репозиторий:

git remote add origin-push $(git config remote.origin.url)
git fetch origin-push

Теперь, когда фоновый процесс выполняет git fetch origin, ссылки в origin-push не будут обновляться, и, следовательно, такие команды, как:

git push --force-with-lease origin-push

завершатся сбоем, если только вы вручную не выполните git fetch origin-push. Этот метод, конечно, полностью нарушается чем-то, что выполняет git fetch --all; в этом случае вам нужно либо отключить это, либо сделать что-то более утомительное, например:

git fetch              # обновить 'master' из внешнего репозитория
git tag base master    # отметить нашу базовую точку
git rebase -i master   # переписать некоторые коммиты
git push --force-with-lease=master:base master:master

Т.е. создать метку base для версий вышестоящего (upstream) кода, которые вы видели и готовы перезаписать, затем переписать историю и, наконец, принудительно отправить изменения в master, если внешняя версия всё ещё находится на base, независимо от того, до чего была обновлена ваша локальная remotes/origin/master в фоне.

Кроме того, указание --force-if-includes в качестве дополнительного параметра вместе с --force-with-lease[=<имя-ссылки>] (т.е. без указания, на какой именно коммит должна указывать ссылка на внешней стороне или какие именно ссылки на внешней стороне защищаются) во время «отправки» проверит, интегрированы ли локально обновления из отслеживаемых внешних ссылок, которые могли быть неявно обновлены в фоне, прежде чем разрешить принудительное обновление.

-f
--force

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

Этот флаг отключает эту проверку, другие проверки безопасности в разделе ПРАВИЛА ОТПРАВКИ ниже и проверки в --force-with-lease. Это может привести к потере коммитов во внешнем репозитории; используйте с осторожностью.

Обратите внимание, что --force применяется ко всем отправляемым ссылкам, поэтому использование его с push.default, установленным в matching, или с несколькими целевыми репозиториями отправки, настроенными с помощью remote.<имя>.push, может перезаписать ссылки, отличные от текущей ветки (включая локальные ссылки, которые строго отстают от своих внешних аналогов). Чтобы принудительно отправить изменения только в одну ветку, используйте + перед спецификатором ссылки (например, git push origin +master для принудительной отправки в ветку master). Подробности смотрите в разделе <спецификатор-ссылки>... выше.

--force-if-includes
--no-force-if-includes

Принудительно выполнить обновление, только если верхушка (tip) отслеживаемой внешней ссылки была интегрирована локально.

Этот параметр включает проверку, которая определяет, достижима ли верхушка (tip) отслеживаемой внешней ссылки из одной из записей «журнала ссылок» (reflog) локальной ветки, основанной на ней, для перезаписи. Проверка гарантирует, что любые обновления из внешнего репозитория были включены локально, отклоняя принудительное обновление, если это не так.

Если параметр передан без указания --force-with-lease или указан вместе с --force-with-lease=<имя-ссылки>:<ожидаемое>, это «пустая операция» (no-op).

Указание --no-force-if-includes отключает это поведение.

--repo=<repository>

Этот параметр эквивалентен аргументу <репозиторий>. Если указаны оба, аргумент командной строки имеет приоритет.

-u
--set-upstream

Для каждой ветки, которая актуальна или успешно отправлена, добавить вышестоящую (upstream) ссылку (отслеживание), используемую git-pull[1] без аргументов и другими командами. Для получения дополнительной информации смотрите branch.<имя>.merge в git-config[1].

--thin
--no-thin

Эти параметры передаются в git-send-pack[1]. «Тонкая» (thin) передача значительно уменьшает объем отправляемых данных, когда у отправителя и получателя много общих объектов. Значение по умолчанию — --thin.

-q
--quiet

Подавлять весь вывод, включая список обновлённых ссылок, если не произошла ошибка. Ход выполнения не сообщается в стандартный поток ошибок.

-v
--verbose

Работать подробно (verbose).

--progress

Прогресс по умолчанию направляется в стандартный поток ошибок, если этот поток подключён к терминалу, если не указан параметр -q. Этот флаг принудительно включает отображение прогресса, даже если стандартный поток ошибок не направлен на терминал.

--no-recurse-submodules
--recurse-submodules=(check|on-demand|only|no)

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

check

Git проверит, что все коммиты подмодулей, которые изменились в отправляемых редакциях, доступны хотя бы в одном внешнем репозитории подмодуля. Если каких-либо коммитов не хватает, отправка будет прервана и завершится с ненулевым статусом.

on-demand

все подмодули, которые изменились в отправляемых редакциях, будут отправлены. Если on-demand не смог отправить все необходимые редакции, операция также будет прервана и завершится с ненулевым статусом.

only

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

no

переопределить переменную конфигурации push.recurseSubmodules, когда рекурсия в подмодулях не требуется. Аналогично использованию --no-recurse-submodules.

При использовании on-demand или only, если у подмодуля есть конфигурация push.recurseSubmodules=(on-demand|only) или submodule.recurse, произойдет дальнейшая рекурсия. В этом случае only рассматривается как on-demand.

--verify
--no-verify

Переключить перехватчик (hook) pre-push (см. githooks[5]). Значение по умолчанию — --verify, дающее перехватчику шанс предотвратить отправку. С --no-verify перехватчик полностью игнорируется.

-4
--ipv4

Использовать только IPv4 адреса, игнорируя IPv6 адреса.

-6
--ipv6

Использовать только IPv6 адреса, игнорируя адреса IPv4.

Warning

Missing ru/urls-remotes.adoc

See original version for this content.

ВЫВОД

Вывод «git push» зависит от используемого транспортного метода; в этом разделе описывается вывод при отправке по протоколу Git (локально или через ssh).

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

 <флаг> <сводка> <откуда> -> <куда> (<причина>)

Если используется --porcelain, то каждая строка вывода имеет следующий вид:

 <флаг> \t <откуда>:<куда> \t <сводка> (<причина>)

Статус актуальных ссылок показывается, только если используется параметр --porcelain или --verbose.

<флаг>

Один символ, указывающий статус ссылки:

(пространство)

для успешно отправленной перемотки вперёд (fast-forward);

+

для успешного принудительного обновления;

-

для успешно удалённой ссылки;

*

для успешно отправленной новой ссылки;

!

для ссылки, которая была отклонена или не отправлена; и

=

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

<summary>

Для успешно отправленной ссылки в сводке показываются старое и новое значения ссылки в форме, подходящей для использования в качестве аргумента git log (в большинстве случаев это <старое>..<новое>, а для принудительных обновлений, не являющихся перемоткой вперёд — <старое>...<новое>).

Для неудачного обновления предоставляются дополнительные сведения:

отклонено

Git вообще не пытался отправить ссылку, обычно потому, что это не перемотка вперёд (fast-forward) и вы не применили принудительное обновление.

отклонено внешним репозиторием

Внешняя сторона отказалась от обновления. Обычно это вызвано перехватчиком (hook) на внешней стороне или тем, что во внешнем репозитории действует один из следующих параметров безопасности: receive.denyCurrentBranch (для отправок в переключённую ветку), receive.denyNonFastForwards (для принудительных обновлений, не являющихся перемоткой вперёд), receive.denyDeletes или receive.denyDeleteCurrent. Смотрите git-config[1].

сбой во внешнем репозитории

Внешняя сторона не сообщила об успешном обновлении ссылки, возможно, из-за временной ошибки на внешней стороне, разрыва сетевого соединения или другой преходящей ошибки.

из

Имя отправляемой локальной ссылки без префикса refs/<тип>/. В случае удаления имя локальной ссылки опускается.

в

Имя обновляемой внешней ссылки без префикса refs/<тип>/.

причина

Пояснение, понятное человеку. В случае успешно отправленных ссылок пояснение не требуется. Для неудачной ссылки описывается причина сбоя.

ПРАВИЛА ОТПРАВКИ

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

Поскольку ветки и метки предназначены для разного использования, правила безопасности для отправки в ветку отличаются от правил для отправки в метку. В следующих правилах под «обновлением» понимаются любые изменения, кроме удалений и созданий. Удаления и создания всегда разрешены, если только они не запрещены конфигурацией или перехватчиками (hooks).

  1. Если целевой объект отправки — ветка (refs/heads/*): разрешены только обновления-перемотки вперёд (fast-forward), что означает, что целевой объект должен быть предком исходного коммита. Исходный объект должен быть коммитом.

  2. Если целевой объект отправки — метка (refs/tags/*): все обновления будут отклонены. Исходным объектом может быть любой объект.

  3. Если целевой объект отправки не является ни веткой, ни меткой:

    • Если исходный объект — дерево или blob-объект, любые обновления будут отклонены

    • Если исходный объект — метка или коммит, разрешено любое обновление-перемотка вперёд, даже в тех случаях, когда перематывается вперёд не коммит, а объект-метка, который указывает на новый коммит, являющийся перемоткой вперёд относительно коммита, на который указывала заменяемая последняя метка (или коммит). Замена метки на совершенно другую метку также разрешена, если она указывает на тот же коммит, а также отправка «очищенной» (peeled) метки, т.е. отправка коммита, на который указывает существующий объект-метка, или нового объекта-метки, на который указывает существующий коммит.

Вы можете отменить эти правила, передав --force или добавив необязательный префикс + к спецификатору ссылки. Единственное исключение заключается в том, что никакое принуждение не заставит ветку принять объект, не являющийся коммитом, и принуждение не заставит внешний репозиторий принять отправку, которую он настроен отклонять.

Перехватчики (hooks) и конфигурация также могут отменять или изменять эти правила, см., например, receive.denyNonFastForwards и receive.denyDeletes в git-config[1] и pre-receive и update в githooks[5].

ПРИМЕЧАНИЕ О ПЕРЕМОТКЕ ВПЕРЁД (FAST-FORWARD)

Когда обновление изменяет ветку (или, в более общем смысле, ссылку), указывавшую на коммит A, так что она начинает указывать на другой коммит B, это называется обновлением-перемоткой вперёд (fast-forward) тогда и только тогда, когда B является потомком A.

При обновлении-перемотке вперёд с A на B набор коммитов, на которых основывался исходный коммит A, является подмножеством коммитов, на которых основывается новый коммит B. Следовательно, история не теряется.

В отличие от этого, обновление, не являющееся перемоткой вперёд, приведёт к потере истории. Например, предположим, что вы и кто-то другой начали с одного и того же коммита X, и вы построили историю, ведущую к коммиту B, в то время как другой человек построил историю, ведущую к коммиту A. История выглядит так:

      B
     /
 ---X---A

Предположим также, что другой человек уже отправил изменения, ведущие к A, обратно в исходный репозиторий, из которого вы оба получили исходный коммит X.

Отправка, выполненная другим человеком, обновила ветку, которая ранее указывала на коммит X, чтобы она указывала на коммит A. Это перемотка вперёд.

Но если вы попытаетесь отправить изменения, вы попытаетесь обновить ветку (которая теперь указывает на A) коммитом B. Это не перемотка вперёд. Если вы это сделаете, изменения, внесённые коммитом A, будут потеряны, потому что все теперь начнут основываться на B.

По умолчанию команда не разрешает обновление, не являющееся перемоткой вперёд, чтобы предотвратить такую потерю истории.

Если вы не хотите потерять свою работу (историю от X до B) или работу другого человека (историю от X до A), вам нужно сначала получить (fetch) историю из репозитория, создать историю, содержащую изменения, сделанные обеими сторонами, и отправить результат обратно.

Вы можете выполнить «git pull», разрешить потенциальные конфликты и выполнить «git push» результата. «git pull» создаст коммит слияния C между коммитами A и B.

      B---C
     /   /
 ---X---A

Обновление A полученным коммитом слияния будет перемоткой вперёд, и ваша отправка будет принята.

Кроме того, вы можете переместить (rebase) ваше изменение между X и B на основу A с помощью git pull --rebase и отправить результат обратно. Перемещение создаст новый коммит D, который строит изменение между X и B на основе A.

      B   D
     /   /
 ---X---A

И снова, обновление A этим коммитом будет перемоткой вперёд, и ваша отправка будет принята.

Существует ещё одна распространённая ситуация, когда вы можете столкнуться с отклонением, не являющимся перемоткой вперёд, при попытке отправить изменения, и это возможно даже при отправке в репозиторий, в который никто больше не отправляет. После того как вы сами отправили коммит A (на первой картинке в этом разделе), вы заменяете его с помощью git commit --amend, создавая коммит B, и пытаетесь отправить его, забыв, что вы уже отправили A. В таком случае, и только если вы уверены, что никто тем временем не получил (fetch) ваш более ранний коммит A (и не начал строить на его основе), вы можете выполнить git push --force, чтобы перезаписать его. Другими словами, git push --force — это метод, предназначенный для случаев, когда вы действительно намерены потерять историю.

ПРИМЕРЫ

git push

Работает как git push <внешний-репозиторий>, где <внешний-репозиторий> — это внешний репозиторий текущей ветки (или origin, если для текущей ветки не настроен внешний репозиторий).

git push origin

Без дополнительной конфигурации отправляет текущую ветку в настроенную вышестоящую (upstream) ветку (переменная конфигурации branch.<имя>.merge), если она имеет то же имя, что и текущая ветка; в противном случае завершается с ошибкой без отправки.

Поведение этой команды по умолчанию, если не указан <спецификатор-ссылки>, можно настроить, установив параметр push для внешнего репозитория или переменную конфигурации push.default.

Например, чтобы по умолчанию отправлять только текущую ветку в origin, используйте git config remote.origin.push HEAD. Любой допустимый <спецификатор-ссылки> (например, как в примерах ниже) можно настроить как значение по умолчанию для git push origin.

git push origin :

Отправить «совпадающие» ветки в origin. Смотрите <спецификатор-ссылки> в разделе ПАРАМЕТРЫ выше для описания «совпадающих» веток.

git push origin master

Находит ссылку, соответствующую master, в исходном репозитории (скорее всего, это будет refs/heads/master) и обновляет ею ту же ссылку (например, refs/heads/master) в репозитории origin. Если master не существовала во внешнем репозитории, она будет создана.

git push origin HEAD

Удобный способ отправить текущую ветку с тем же именем во внешний репозиторий.

git push mothership master:satellite/master dev:satellite/dev

Использовать исходную ссылку, соответствующую master (например, refs/heads/master), для обновления ссылки, соответствующей satellite/master (скорее всего, refs/remotes/satellite/master), в репозитории mothership; сделать то же самое для dev и satellite/dev.

Смотрите раздел, описывающий <спецификатор-ссылки>... выше, для обсуждения семантики сопоставления.

Это нужно для эмуляции git fetch, выполняемого на mothership, с помощью git push, который выполняется в противоположном направлении, чтобы интегрировать работу, проделанную на satellite, и часто необходимо, когда соединение можно установить только в одну сторону (т.е. satellite может подключиться по ssh к mothership, но mothership не может инициировать соединение с satellite, потому что последний находится за брандмауэром или на нём не запущен sshd).

После выполнения этого git push на машине satellite вы должны подключиться по ssh к mothership и выполнить там git merge, чтобы завершить эмуляцию git pull, который был бы выполнен на mothership для получения (pull) изменений, сделанных на satellite.

git push origin HEAD:master

Отправить текущую ветку во внешнюю ссылку, соответствующую master, в репозитории origin. Эта форма удобна для отправки текущей ветки без необходимости помнить её локальное имя.

git push origin master:refs/heads/experimental

Создать ветку experimental в репозитории origin, скопировав текущую ветку master. Эта форма нужна только для создания новой ветки или метки во внешнем репозитории, когда локальное имя и внешнее имя различаются; в противном случае будет достаточно самого имени ссылки.

git push origin :experimental

Находит ссылку, соответствующую experimental, в репозитории origin (например, refs/heads/experimental) и удаляет её.

git push origin +dev:master

Обновить ветку master в репозитории origin с помощью ветки dev, разрешая обновления, не являющиеся перемоткой вперёд. Это может привести к тому, что в репозитории origin останутся болтающиеся (dangling) коммиты без ссылок. Рассмотрим следующую ситуацию, когда перемотка вперёд невозможна:

	    o---o---o---A---B  origin/master
		     \
		      X---Y---Z  dev

Вышеуказанная команда изменит репозиторий origin на

		      A---B  (ветка без имени)
		     /
	    o---o---o---X---Y---Z  master

Коммиты A и B больше не будут принадлежать ветке с символическим именем и, следовательно, станут недостижимыми. Таким образом, эти коммиты будут удалены командой git gc в репозитории origin.

БЕЗОПАСНОСТЬ

Протоколы получения (fetch) и отправки (push) не предназначены для предотвращения кражи одной стороной данных из другого репозитория, которые не предназначались для общего доступа. Если у вас есть частные данные, которые необходимо защитить от злонамеренного участника, лучший вариант — хранить их в другом репозитории. Это относится как к клиентам, так и к серверам. В частности, пространства имён на сервере неэффективны для контроля доступа на чтение; вы должны предоставлять доступ на чтение к пространству имён только тем клиентам, которым вы доверили бы доступ на чтение ко всему репозиторию.

Известные векторы атак следующие:

  1. Жертва отправляет строки «have», рекламируя идентификаторы объектов, которые у неё есть и которые явно не предназначены для общего доступа, но могут использоваться для оптимизации передачи, если они также есть у участника. Злоумышленник выбирает идентификатор объекта X для кражи и отправляет ссылку на X, но не обязан отправлять содержимое X, потому что оно уже есть у жертвы. Теперь жертва считает, что у злоумышленника есть X, и позже отправляет содержимое X обратно злоумышленнику. (Эту атаку проще всего выполнить клиенту на сервере, создав ссылку на X в пространстве имён, к которому у клиента есть доступ, а затем получив её. Наиболее вероятный способ для сервера выполнить её на клиенте — «слить» X в публичную ветку и надеяться, что пользователь выполнит дополнительную работу в этой ветке и отправит её обратно на сервер, не заметив слияния.)

  2. Как и в №1, злоумышленник выбирает идентификатор объекта X для кражи. Жертва отправляет объект Y, который у злоумышленника уже есть, а злоумышленник ложно заявляет, что у него есть X, а Y нет, поэтому жертва отправляет Y как дельту относительно X. Дельта раскрывает злоумышленнику области X, похожие на Y.

КОНФИГУРАЦИЯ

Дальнейшее содержание этого раздела, повторяет то, что может быть найдено в git-config[1]:

push.autoSetupRemote

Если установлено в true, подразумевать --set-upstream при отправке по умолчанию, когда для текущей ветки не существует вышестоящего (upstream) отслеживания; этот параметр действует с опциями push.default simple, upstream и current. Это полезно, если по умолчанию вы хотите, чтобы новые ветки отправлялись во внешний репозиторий по умолчанию (как поведение push.default=current) и вы также хотите, чтобы было установлено вышестоящее отслеживание. Наиболее вероятные рабочие процессы, которые выиграют от этого параметра, — это simple централизованные рабочие процессы, где ожидается, что все ветки будут иметь одинаковые имена во внешнем репозитории.

push.default

Определяет действие, которое должно выполняться git push, если не указан спецификатор ссылки (будь то из командной строки, конфигурации или другого места). Разные значения хорошо подходят для конкретных рабочих процессов; например, в чисто централизованном рабочем процессе (т.е. источник получения равен цели отправки), upstream, вероятно, то, что вам нужно. Возможные значения:

nothing

не отправлять ничего (завершиться с ошибкой), если не указан спецификатор ссылки. Это в первую очередь предназначено для людей, которые хотят избежать ошибок, всегда действуя явно.

current

отправить текущую ветку для обновления ветки с тем же именем на принимающей стороне. Работает как в централизованных, так и в нецентрализованных рабочих процессах.

upstream

отправить текущую ветку обратно в ветку, чьи изменения обычно интегрируются в текущую ветку (которая называется @{upstream}). Этот режим имеет смысл только в том случае, если вы отправляете в тот же репозиторий, из которого обычно извлекаете (pull) (т.е. централизованный рабочий процесс).

tracking

это устаревший синоним для upstream.

simple

отправить текущую ветку с тем же именем во внешний репозиторий.

Если вы работаете по централизованному рабочему процессу (отправляете в тот же репозиторий, из которого извлекаете, обычно это origin), то вам нужно настроить вышестоящую ветку с тем же именем.

Этот режим используется по умолчанию, начиная с Git 2.0, и является самым безопасным вариантом, подходящим для новичков.

matching

отправить все ветки, имеющие одинаковые имена на обоих концах. Это заставляет репозиторий, в который вы отправляете, запомнить набор веток, которые будут отправлены (например, если вы всегда отправляете туда maint и master и никакие другие ветки, репозиторий, в который вы отправляете, будет иметь эти две ветки, и ваши локальные maint и master будут туда отправлены).

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

Раньше это было значение по умолчанию, но не начиная с Git 2.0 (simple — новое значение по умолчанию).

push.followTags

Если установлено в true, включить опцию --follow-tags по умолчанию. Вы можете переопределить эту конфигурацию во время отправки, указав --no-follow-tags.

push.gpgSign

Может быть установлен в логическое значение или в строку if-asked. Значение true заставляет все отправки подписываться с помощью GPG, как если бы --signed был передан в git-push[1]. Строка if-asked заставляет отправки подписываться, если сервер это поддерживает, как если бы --signed=if-asked был передан в git push. Значение false может переопределить значение из конфигурационного файла с более низким приоритетом. Явный флаг командной строки всегда переопределяет этот параметр конфигурации.

push.pushOption

Если аргумент --push-option=<параметр> не задан в командной строке, git push ведёт себя так, как если бы каждый <параметр> этой переменной был задан как --push-option=<параметр>.

Это многозначная переменная, и пустое значение может быть использовано в конфигурационном файле с более высоким приоритетом (например, .git/config в репозитории) для очистки значений, унаследованных из конфигурационных файлов с более низким приоритетом (например, $HOME/.gitconfig).

Пример:

/etc/gitconfig
  push.pushoption = a
  push.pushoption = b

~/.gitconfig
  push.pushoption = c

repo/.git/config
  push.pushoption =
  push.pushoption = b

В результате останется только b (a и c будут очищены).
push.recurseSubmodules

Может быть check, on-demand, only или no, с тем же поведением, что и у push --recurse-submodules. Если не установлено, по умолчанию используется no, если только не установлен submodule.recurse (в этом случае значение true означает on-demand).

push.useForceIfIncludes

Если установлено в true, это эквивалентно указанию --force-if-includes в качестве параметра для git-push[1] в командной строке. Добавление --no-force-if-includes во время отправки переопределяет этот параметр конфигурации.

push.negotiate

Если установлено в true, пытаться уменьшить размер отправляемого pack-файла с помощью раундов согласования, в которых клиент и сервер пытаются найти общие коммиты. Если false, Git будет полагаться исключительно на объявление ссылок сервера для поиска общих коммитов.

push.useBitmaps

Если установлено в false, отключить использование битовых карт для git push, даже если pack.useBitmaps имеет значение true, не препятствуя использованию битовых карт другими операциями git. По умолчанию true.

GIT

Является частью пакета git[1]