English ▾ Topics ▾ Latest version ▾ git-push last updated in 2.55.0

NAME

git-push - Update remote refs along with associated objects

SYNOPSIS

git push [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
	 [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-q | --quiet] [-v | --verbose]
	 [-u | --set-upstream] [-o <string> | --push-option=<string>]
	 [--[no-]signed | --signed=(true|false|if-asked)]
	 [--force-with-lease[=<refname>[:<expect>]] [--force-if-includes]]
	 [--no-verify] [<repository> [<refspec>…​]]

DESCRIPTION

Updates one or more branches, tags, or other references in one or more remote repositories from your local repository, and sends all necessary data that isn’t already on the remote.

The simplest way to push is git push <remote> <branch>. git push origin main will push the local main branch to the main branch on the remote named origin.

You can also push to multiple remotes at once by using a remote group. A remote group is a named list of remotes configured via remotes.<name> in your git config:

$ git config remotes.all-remotes "origin gitlab backup"

Then git push all-remotes will push to origin, gitlab, and backup in turn, as if you had run git push against each one individually. Each remote is pushed independently using its own push mapping configuration. There is a remotes.<group> entry in the configuration file. (See git-config[1]).

The <repository> argument defaults to the upstream for the current branch, or origin if there’s no configured upstream.

To decide which branches, tags, or other refs to push, Git uses (in order of precedence):

  1. The <refspec> argument(s) (for example main in git push origin main) or the --all, --mirror, or --tags options

  2. The remote.<name>.push configuration for the repository being pushed to

  3. The push.default configuration. The default is push.default=simple, which will push to a branch with the same name as the current branch. See the CONFIGURATION section below for more on push.default.

git push may fail if you haven’t set an upstream for the current branch, depending on what push.default is set to. See the UPSTREAM BRANCHES section below for more on how to set and use upstreams.

You can make interesting things happen to a repository every time you push into it, by setting up hooks there. See documentation for git-receive-pack[1].

OPTIONS

<repository>

The "remote" repository that is the destination of a push operation. This parameter can be either a URL (see the section GIT URLS below), the name of a remote (see the section REMOTES below), or the name of a remote group (see the section REMOTE GROUPS below).

<refspec>...

Specify what destination ref to update with what source object.

The format for a refspec is [+]<src>[:<dst>], for example main, main:other, or HEAD^:refs/heads/main.

The <src> is often the name of the local branch to push, but it can be any arbitrary "SHA-1 expression" (see gitrevisions[7]).

The <dst> determines what ref to update on the remote side. It must be the name of a branch, tag, or other ref, not an arbitrary expression.

The + is optional and does the same thing as --force.

You can write a refspec using the fully expanded form (for example refs/heads/main:refs/heads/main) which specifies the exact source and destination, or with a shorter form (for example main or main:other). Here are the rules for how refspecs are expanded, as well as various other special refspec forms:

  • <src> without a :<dst> means to update the same ref as the <src>, unless the remote.<repository>.push configuration specifies a different <dst>. For example, if main is a branch, then the refspec main expands to main:refs/heads/main.

  • If <dst> unambiguously refers to a ref on the <repository> remote, then expand it to that ref. For example, if v1.0 is a tag on the remote, then HEAD:v1.0 expands to HEAD:refs/tags/v1.0.

  • If <src> resolves to a ref starting with refs/heads/ or refs/tags/, then prepend that to <dst>. For example, if main is a branch, then main:other expands to main:refs/heads/other

  • The special refspec : (or +: to allow non-fast-forward updates) directs Git to push "matching" branches: for every branch that exists on the local side, the remote side is updated if a branch of the same name already exists on the remote side.

  • <src> may contain a * to indicate a simple pattern match. This works like a glob that matches any ref matching the pattern. There must be only one * in both the <src> and <dst>. It will map refs to the destination by replacing the * with the contents matched from the source. For example, refs/heads/*:refs/heads/* will push all branches.

  • A refspec starting with ^ is a negative refspec. This specifies refs to exclude. A ref will be considered to match if it matches at least one positive refspec, and does not match any negative refspec. Negative refspecs can be pattern refspecs. They must only contain a <src>. Fully spelled out hex object names are also not supported. For example, git push origin refs/heads/*' ^refs/heads/dev-*' will push all branches except for those starting with dev-

  • If <src> is empty, it deletes the <dst> ref from the remote repository. For example, git push origin :dev will delete the dev branch.

  • tag <tag> expands to refs/tags/<tag>:refs/tags/<tag>. This is technically a special syntax for git push and not a refspec, since in git push origin tag v1.0 the arguments tag and v1.0 are separate.

  • If the refspec can’t be expanded unambiguously, error out with an error indicating what was tried, and depending on the advice.pushUnqualifiedRefname configuration (see git-config[1]) suggest what refs/ namespace you may have wanted to push to.

Not all updates are allowed: see PUSH RULES below for the details.

--all
--branches

Push all branches (i.e. refs under refs/heads/); cannot be used with other <refspec>.

--prune

Remove remote branches that don’t have a local counterpart. For example a remote branch tmp will be removed if a local branch with the same name doesn’t exist any more. This also respects refspecs, e.g. git push --prune remote refs/heads/*:refs/tmp/* would make sure that remote refs/tmp/foo will be removed if refs/heads/foo doesn’t exist.

--mirror

Instead of naming each ref to push, specifies that all refs under refs/ (which includes but is not limited to refs/heads/, refs/remotes/, and refs/tags/) be mirrored to the remote repository. Newly created local refs will be pushed to the remote end, locally updated refs will be force updated on the remote end, and deleted refs will be removed from the remote end. This is the default if the configuration option remote.<remote>.mirror is set.

-n
--dry-run

Do everything except actually send the updates.

--porcelain

Produce machine-readable output. The output status line for each ref will be tab-separated and sent to stdout instead of stderr. The full symbolic names of the refs will be given.

-d
--delete

All listed refs are deleted from the remote repository. This is the same as prefixing all refs with a colon.

--tags

All refs under refs/tags are pushed, in addition to refspecs explicitly listed on the command line.

--follow-tags

Push all the refs that would be pushed without this option, and also push annotated tags in refs/tags that are missing from the remote but are pointing at commit-ish that are reachable from the refs being pushed. This can also be specified with configuration variable push.followTags. For more information, see push.followTags in git-config[1].

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

GPG-sign the push request to update refs on the receiving side, to allow it to be checked by the hooks and/or be logged. Possible values are:

false
--no-signed

no signing will be attempted.

true
--signed

the push will fail if the server does not support signed pushes.

if-asked

sign if and only if the server supports signed pushes. The push will also fail if the actual call to gpg --sign fails. See git-receive-pack[1] for the details on the receiving end.

--atomic
--no-atomic

Use an atomic transaction on the remote side if available. Either all refs are updated, or on error, no refs are updated. If the server does not support atomic pushes the push will fail.

-o <option>
--push-option=<option>

Transmit the given string to the server, which passes them to the pre-receive as well as the post-receive hook. The given string must not contain a NUL or LF character. When multiple --push-option=<option> are given, they are all sent to the other side in the order listed on the command line. When no --push-option=<option> is given from the command line, the values of configuration variable push.pushOption are used instead.

--receive-pack=<git-receive-pack>
--exec=<git-receive-pack>

Path to the git-receive-pack program on the remote end. Sometimes useful when pushing to a remote repository over ssh, and you do not have the program in a directory on the default $PATH.

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

Usually, git push refuses to update a remote ref that is not an ancestor of the local ref used to overwrite it.

This option overrides this restriction if the current value of the remote ref is the expected value. git push fails otherwise.

Imagine that you have to rebase what you have already published. You will have to bypass the "must fast-forward" rule in order to replace the history you originally published with the rebased history. If somebody else built on top of your original history while you are rebasing, the tip of the branch at the remote may advance with their commit, and blindly pushing with --force will lose their work.

This option allows you to say that you expect the history you are updating is what you rebased and want to replace. If the remote ref still points at the commit you specified, you can be sure that no other people did anything to the ref. It is like taking a "lease" on the ref without explicitly locking it, and the remote ref is updated only if the "lease" is still valid.

--force-with-lease alone, without specifying the details, will protect all remote refs that are going to be updated by requiring their current value to be the same as the remote-tracking branch we have for them.

--force-with-lease=<refname>, without specifying the expected value, will protect <refname> (alone), if it is going to be updated, by requiring its current value to be the same as the remote-tracking branch we have for it.

--force-with-lease=<refname>:<expect> will protect <refname> (alone), if it is going to be updated, by requiring its current value to be the same as the specified value <expect> (which is allowed to be different from the remote-tracking branch we have for the refname, or we do not even have to have such a remote-tracking branch when this form is used). If <expect> is the empty string, then the named ref must not already exist.

Note that all forms other than --force-with-lease=<refname>:<expect> that specifies the expected current value of the ref explicitly are still experimental and their semantics may change as we gain experience with this feature.

--no-force-with-lease will cancel all the previous --force-with-lease on the command line.

A general note on safety: supplying this option without an expected value, i.e. as --force-with-lease or --force-with-lease=<refname> interacts very badly with anything that implicitly runs git fetch on the remote to be pushed to in the background, e.g. git fetch origin on your repository in a cronjob.

The protection it offers over --force is ensuring that subsequent changes your work wasn’t based on aren’t clobbered, but this is trivially defeated if some background process is updating refs in the background. We don’t have anything except the remote tracking info to go by as a heuristic for refs you’re expected to have seen & are willing to clobber.

If your editor or some other system is running git fetch in the background for you a way to mitigate this is to simply set up another remote:

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

Now when the background process runs git fetch origin the references on origin-push won’t be updated, and thus commands like:

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

Will fail unless you manually run git fetch origin-push. This method is of course entirely defeated by something that runs git fetch --all, in that case you’d need to either disable it or do something more tedious like:

git fetch              # update 'master' from remote
git tag base master    # mark our base point
git rebase -i master   # rewrite some commits
git push --force-with-lease=master:base master:master

I.e. create a base tag for versions of the upstream code that you’ve seen and are willing to overwrite, then rewrite history, and finally force push changes to master if the remote version is still at base, regardless of what your local remotes/origin/master has been updated to in the background.

Alternatively, specifying --force-if-includes as an ancillary option along with --force-with-lease[=<refname>] (i.e., without saying what exact commit the ref on the remote side must be pointing at, or which refs on the remote side are being protected) at the time of "push" will verify if updates from the remote-tracking refs that may have been implicitly updated in the background are integrated locally before allowing a forced update.

-f
--force

Usually, git push will refuse to update a branch that is not an ancestor of the commit being pushed.

This flag disables that check, the other safety checks in PUSH RULES below, and the checks in --force-with-lease. It can cause the remote repository to lose commits; use it with care.

Note that --force applies to all the refs that are pushed, hence using it with push.default set to matching or with multiple push destinations configured with remote.<name>.push may overwrite refs other than the current branch (including local refs that are strictly behind their remote counterpart). To force a push to only one branch, use a + in front of the refspec to push (e.g git push origin +master to force a push to the master branch). See the <refspec>... section above for details.

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

Force an update only if the tip of the remote-tracking ref has been integrated locally.

This option enables a check that verifies if the tip of the remote-tracking ref is reachable from one of the "reflog" entries of the local branch based in it for a rewrite. The check ensures that any updates from the remote have been incorporated locally by rejecting the forced update if that is not the case.

If the option is passed without specifying --force-with-lease, or specified along with --force-with-lease=<refname>:<expect>, it is a "no-op".

Specifying --no-force-if-includes disables this behavior.

--repo=<repository>

This option is equivalent to the <repository> argument. If both are specified, the command-line argument takes precedence.

-u
--set-upstream

For every branch that is up to date or successfully pushed, add upstream (tracking) reference, used by argument-less git-pull[1] and other commands. For more information, see branch.<name>.merge in git-config[1].

--thin
--no-thin

These options are passed to git-send-pack[1]. A thin transfer significantly reduces the amount of sent data when the sender and receiver share many of the same objects in common. The default is --thin.

-q
--quiet

Suppress all output, including the listing of updated refs, unless an error occurs. Progress is not reported to the standard error stream.

-v
--verbose

Run verbosely.

--progress

Progress status is reported on the standard error stream by default when it is attached to a terminal, unless -q is specified. This flag forces progress status even if the standard error stream is not directed to a terminal.

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

May be used to make sure all submodule commits used by the revisions to be pushed are available on a remote-tracking branch. Possible values are:

check

Git will verify that all submodule commits that changed in the revisions to be pushed are available on at least one remote of the submodule. If any commits are missing the push will be aborted and exit with non-zero status.

on-demand

all submodules that changed in the revisions to be pushed will be pushed. If on-demand was not able to push all necessary revisions it will also be aborted and exit with non-zero status.

only

all submodules will be pushed while the superproject is left unpushed.

no

override the push.recurseSubmodules configuration variable when no submodule recursion is required. Similar to using --no-recurse-submodules.

When using on-demand or only, if a submodule has a push.recurseSubmodules=(on-demand|only) or submodule.recurse configuration, further recursion will occur. In this case, only is treated as on-demand.

--verify
--no-verify

Toggle the pre-push hook (see githooks[5]). The default is --verify, giving the hook a chance to prevent the push. With --no-verify, the hook is bypassed completely.

-4
--ipv4

Use IPv4 addresses only, ignoring IPv6 addresses.

-6
--ipv6

Use IPv6 addresses only, ignoring IPv4 addresses.

GIT URLS

In general, URLs contain information about the transport protocol, the address of the remote server, and the path to the repository. Depending on the transport protocol, some of this information may be absent.

Git supports ssh, git, http, and https protocols (in addition, ftp and ftps can be used for fetching, but this is inefficient and deprecated; do not use them).

The native transport (i.e. git:// URL) does no authentication and should be used with caution on unsecured networks.

The following syntaxes may be used with them:

  • ssh://[<user>@]<host>[:<port>]/<path-to-git-repo>

  • git://<host>[:<port>]/<path-to-git-repo>

  • http[s]://<host>[:<port>]/<path-to-git-repo>

  • ftp[s]://<host>[:<port>]/<path-to-git-repo>

An alternative scp-like syntax may also be used with the ssh protocol:

  • [<user>@]<host>:/<path-to-git-repo>

This syntax is only recognized if there are no slashes before the first colon. This helps differentiate a local path that contains a colon. For example the local path foo:bar could be specified as an absolute path or ./foo:bar to avoid being misinterpreted as an ssh url.

The ssh and git protocols additionally support ~<username> expansion:

  • ssh://[<user>@]<host>[: