Managing remote repositories

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.

Note

There are also two legacy mechanisms to store repository shorthand:

  • A named file in .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.
  • A named file in .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.

The origin remote

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.

Listing and examining remotes

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.

Adding a new remote

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

Updating information about remotes

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 remotes

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.

Changing the remote URLs

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.

Tip

Multiple URLs for a remote

You can set multiple URLs for a remote. Git will try all those URLs sequentially when fetching, and use the first one that works; when pushing, Git will publish to all URLs (all servers) simultaneously.

Changing the list of branches tracked by remote

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.

Setting the default branch of remote

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.

Deleting remote-tracking branches

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.

Support for triangular workflows

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/*
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset