When collaborating on any project managed with Git, you will interact often with a constant set of other repositories; for example, in an integration-manager workflow it would be (at least) the canonical blessed repository of a project. In many cases, you will interact with more than one remote repository.
Git allows us to save the information about a remote repository (in short: remote) in the config
file, giving it a nickname (a shorthand name). Such information can be managed with the git remote
command.
There are also two legacy mechanisms to store repository shorthand:
.git/remotes
—the name of this file will be shorthand for remote. This file can contain information about the URL or URLs, and fetch and push refspecs..git/branches
—the name of this file will be shorthand for remote. The contents of this file are just an URL for the repository, optionally followed by #
and the branch name.Neither of those mechanisms is likely to be found in modern repositories. See the Remotes section in the git-fetch(1)
manpage for more details.
When cloning a repository, Git will create one remote for you—the origin remote, storing information about where you cloned from—that is the origin of your copy of the repository (hence the name). You can use this remote to fetch updates.
This is the default remote; for example git fetch
without the remote name will use the origin remote; unless it is specified otherwise by the remote.default
configuration variable, or unless the configuration for the current branch (branch.<branchname>.remote
) specifies otherwise.
To see which remote repositories you have configured, you can run the git remote
command. It lists the shortnames of each remote you've got. In a cloned repository you will have at least one remote: origin
.
$ git remote origin
To see the URL together with remotes, you can use -v
/ --verbose
option:
$ git remote --verbose origin git://git.kernel.org/pub/scm/git/git.git (fetch) origin git://git.kernel.org/pub/scm/git/git.git (push)
If you want to inspect remotes to see more information about a particular remote, you can use the git remote show <remote>
subcommand:
$ git remote show origin * remote origin Fetch URL: git://git.kernel.org/pub/scm/git/git.git Push URL: git://git.kernel.org/pub/scm/git/git.git HEAD branch: master Remote branches: maint tracked master tracked next tracked pu tracked todo tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up-to-date)
Git will consult the remote configuration, the branch configuration, and the remote repository (for an up-to-date status). If you want to skip contacting the remote repository and use cached information instead, add the -n
option to git remote show
.
As the information about remotes is stored in the repository configuration file, you can simply examine .git/config
:
[remote "origin"] fetch = +refs/heads/*:refs/remotes/origin/* url = git://git.kernel.org/pub/scm/git/git.git
The difference between local and remote branches (and remote tracking branches: local representations of remote branches) will be described in Chapter 6, Advanced Branching Techniques, together with an explanation of
refspecs, as in +refs/heads/*:refs/remotes/origin/*
in the preceding example.
To add a new remote Git repository and to store its information under a shortname, run git remote add <shortname> <URL>
:
$ git remote add alice https://git.company.com/alice/random.git
Adding remote doesn't fetch from it automatically—you need to use the -f
option for that (or run git fetch <shortname>
).
This command has a few options that affect how Git creates a new remote. You can select which branches in the remote repository you are interested in with the -t <branch>
option. You can change which branch is the default one in the remote repository (and which you can refer to by the remote name), using the -m <branch>
option. Or you can configure the remote repository for mirroring rather than for collaboration with --mirror=push
or --mirror=fetch
.
For example, running the command:
$ git remote add -t master -t next -t maint github https://github.com/jnareb/git.git
will result in the following configuration of the remote:
[remote "github"] url = https://github.com/jnareb/git.git fetch = +refs/heads/master:refs/remotes/github/master fetch = +refs/heads/next:refs/remotes/github/next fetch = +refs/heads/maint:refs/remotes/github/maint
The information about the remote repository is stored in three places: in the remote configuration: remote.<remote name>
, in remote-tracking branches, in remote-HEAD (refs/remotes/<remote name>/HEAD
is a symref
that denotes the default remote-tracking branch; that is, the remote tracking branch that <remote name>
used as a branch expands to), and optionally the per-branch configuration: branch.<branch name>
.
You could manipulate this information directly—either by editing the appropriate files or using manipulation commands such as git config
and git symbolic-ref
—but Git provides various git remote
subcommands for this.
Renaming remote—that is, changing its nickname—is quite a complicated operation. Running git remote rename <old> <new>
would not only change the section name in remote.<old>
, but also the remote-tracking branches and accompanying refspec, their reflogs (if there are any—see the core.logAllRefUpdates
configuration variable), and the respective branch configuration.
You can add or replace the URL for a remote with git remote set-url
, but it is also quite easy to simply directly edit the configuration.
You can also use the insteadOf
(and pushInsteadOf
) configuration variables. This can be useful if you want to temporarily use another server, for example if the canonical repository is temporarily down. Say that you want to fetch Git from the repository on GitHub, because https://www.kernel.org/ is down; you can do this by adding the following text to the config
file:
[url "https://github.com/git/git.git"] insteadOf = git://git.kernel.org/pub/scm/git/git.git
Another use case for this feature is handling repository migration; you can use insteadOf
rewriting in the per-user configuration file ~/.gitconfig
(or ~/.config/git/config
) without having to change the URL in each and every per-repository .git/config
file. In the case of more than one match, the longest match is used.
A similar situation to changing the URL is with changing the list of branches tracked by a remote (that is, the contents of fetch
lines): you can use git remote set-branches
(with a sufficiently modern Git), or edit the config file directly.
Note that freeing a branch in a remote repository from being tracked does not remove the remote tracking branch—the latter is simply no longer updated.
Having a default branch on remote is not required, but it lets us use the remote name (for example, origin
) to be specified in lieu of a specific remote-tracking branch (for example, origin/master
). This information is stored in the symbolic ref <remote name>/HEAD
(for example, origin/HEAD
).
You can set it with git remote set-head
; the --auto
option does that based on what is the current branch in the remote repository:
$ git remote set-head origin master $ git branch -r origin/HEAD -> origin/master origin/master
You can delete the default branch on the remote with the --delete
option.
When a public branch is deleted in the remote repository, Git nevertheless keeps the corresponding remote-tracking branch. It does that because you might want to do, or might have done, your own work on top of it. You can however delete the remote tracking branch with git branch -r -d
, or you can ask Git to prune all stale remote tracking branches under the remote with git remote prune
. Or you can configure Git to do it automatically on fetch, as if git fetch
were run with the --prune
option, by setting the fetch.prune
and remote.<name>.prune
configuration variables.
You can check which remote tracking branches are stale with the --dry-run
option to git remote prune
, or with the git remote show
command.
Deleting remote as a whole is as simple as running git remote delete
(or its alias git remote rm
). It also removes remote-tracking branches for the deleted remote.
In many collaborative workflows, like for example the maintainer (or integration manager) workflow, you fetch from one URL (from the blessed repository) but push to another URL (to your own public repository). See Fig 4: the developer interacts with three repositories—he or she fetches from the blessed repository (light red) into the developer private repository (darker), then pushes his or her work into the developer public repository (lighter).
In such a triangular workflow (three repositories), the remote you fetch or pull from is usually the default origin
remote (or remote.default
). One option for configuring which repository you push to is to add this repository as a separate remote, and perhaps also set it up as the default with remote.pushDefault
.
[remote "origin"] url = https://git.company.com/project fetch = +refs/heads/*:refs/remotes/origin/* [remote "myown"] url = [email protected]:user/project fetch = +refs/heads/*:refs/remotes/myown/* [remote] pushdefault = myown
You could also set it as pushremote
in the per-branch configuration:
[branch "master"] remote = origin pushremote = myown merge = refs/heads/master
Another option is to use a single remote (perhaps even origin
), but set it up with a separate pushurl
. This solution however has the slight disadvantage that you don't have separate remote-tracking branches for the push repository (and thus there is no support @{push}
notation in addition to having @{upstream}
as a shortcut for specifying the appropriate remote-tracking branches; however, the former has only been available since Git 2.5.0):
[remote "origin"] url = https://git.company.com/project pushurl = [email protected]:user/project fetch = +refs/heads/*:refs/remotes/origin/*