Referencing Other Repositories

To coordinate your repository with another repository, you define a remote. A remote is a named entity stored in the config file of a repository. It consists of two different parts. The first part of a remote states the name of the other repository in the form of a URL. The second part, called a refspec, specifies how a ref (which usually represents a branch) should be mapped from the namespace of one repository into the namespace of the other repository.

Let’s look at each of these components in turn.

Referring to Remote Repositories

Git supports several forms of Uniform Resource Locator (URL) that can be used to name remote repositories. These forms specify both an access protocol and the location or address of the data.

Technically, Git’s forms of URL are neither URLs nor URIs, because none entirely conform to RFC 1738 or RFC 2396, respectively. However, because of their versatile utility in naming the location of Git repositories, Git’s variants are usually referred to as Git URLs. Furthermore, the .git/config file uses the name url as well.

As you have seen, the simplest form of Git URL refers to a repository on a local filesystem, be it a true physical filesystem or a virtual filesystem mounted locally via the Network File System (NFS). There are two permutations:

/path/to/repo.git
file:///path/to/repo.git

Although these two formats are essentially identical, there is a subtle but important distinction between the two. The former uses hard links within the filesystem to directly share exactly the same objects between the current and remote repository; the latter copies the objects instead of sharing them directly. To avoid issues associated with shared repositories, the file:// form is recommended.

The other forms of the Git URL refer to repositories on remote systems.

When you have a truly remote repository whose data must be retrieved across a network, the most efficient form of data transfer is often called the Git native protocol, which refers to the custom protocol used internally by Git to transfer data. Examples of a native protocol URL include:

git://example.com/path/to/repo.git
git://example.com/~user/path/to/repo.git

These forms are used by git-daemon to publish repositories for anonymous reads. You can both clone and fetch using these URL forms.

The clients that use these formats are not authenticated, and no password will be requested. Hence, whereas a ~user format can be employed to refer to a user’s home directory, a bare ~ has no context for an expansion; there is no authenticated user whose home directory can be used. Furthermore, the ~user form works only if the server side allows it with the --user-path option.

For secure, authenticated connections, the Git native protocol can be tunneled over an SSH connection using the following URL templates:

ssh:///[user@]example.com[:port]/path/to/repo.git
ssh://[user@]example.com/path/to/repo.git
ssh://[user@]example.com/~user2/path/to/repo.git
ssh://[user@]example.com/~/path/to/repo.git

The third form allows for the possibility of two different usernames. The first is the user under which the session is authenticated, and the second is the user whose home directory is accessed. You can find a use of simple SSH URLs in Repositories with Controlled Access.

Git also supports a URL form with scp-like syntax. It’s identical to the SSH forms, but there is no way to specify a port parameter:

[user@]example.com:/path/to/repo.git
[user@]example.com:~user/path/to/repo.git
[user@]example.com:path/to/repo.git

HTTP and HTTPS URL variants are also fully supported, although neither one is as efficient as the Git native protocol:

http://example.com/path/to/repo.git
https://example.com/path/to/repo.git

Finally, the rsync protocol can be specified:

rsync://example.com/path/to/repo.git

The use of rsync is discouraged because it is inferior to the other options. If absolutely necessary, it should be used only for an initial clone, at which point the remote repository reference should be changed to one of the other mechanisms. Continuing to use the rsync protocol for later updates may lead to the loss of locally created data.

The refspec

refs and symrefs explained how the ref, or reference, names a particular commit within the history of the repository. Usually a ref is the name of a branch. A refspec maps branch names in the remote repository to branch names within your local repository.

Because a refspec must simultaneously name branches from the local repository and the remote repository, complete branch names are common in a refspec and are often required. In a refspec, you typically see the names of development branches with the refs/heads/ prefix and the names of tracking branches with the refs/remotes/ prefix.

The syntax of a refspec is:

[+]source:destination

It consists primarily of a source ref, a colon (:), and a destination ref. The whole format may be prefixed with an optional plus sign (+). If present, the plus sign indicates that the normal fast-forward safety check will not be performed during the transfer. Furthermore, an asterisk (*) allows a limited form of wildcard matching on branch names.

In some uses, the source ref is optional; in others, the colon and destination ref are optional.

The trick to using a refspec is to understand the data flow it specifies. The refspec itself is always source:destination, but the role of source and destination depends on the Git operation being performed. This relationship is summarized by Table 11-1.

Table 11-1. Refspec data flow

OperationSourceDestination
pushLocal ref being pushedRemote ref being updated
fetchRemote ref being fetchedLocal ref being updated

A typical git fetch command uses a refspec such as:

+refs/heads/*:refs/remotes/remote/*

This refspec might be paraphrased as follows:

All the source branches from a remote repository in namespace refs/heads/ are (i) mapped into your local repository using a name constructed from the remote name and (ii) placed under the refs/remotes/remote namespace.

Because of the asterisks, this refspec applies to multiple branches as found in the remote’s refs/heads/*. It is exactly this specification that causes the remote’s topic branches to be mapped into your local tracking branches and that separates them into subnames based on the remote name.

Although not mandatory, it is convention and common best practice to place the branches for a given remote under refs/remotes/remote/*.

Tip

Use git show-ref to list the references within your current repository. Use git ls-remote repository to list the references in a remote repository.

Refspecs are used both by git fetch and by git push. Because git pull’s first step is fetch, the fetch refspecs apply equally to git pull.

Multiple refspecs may be given on the git fetch and git push command lines. Within a remote definition, multiple fetch refspecs, multiple push refspecs, or a combination of both may be specified.

Tip

You should not make commits or merges onto a tracking branch identified on the righthand side of a pull or fetch refspec. Those refs will be used as tracking branches.

During a git push operation, you typically want to provide and publish the changes you made on your local topic branches. To allow others to find your changes in the remote repository after you upload them, your changes must appear in that repository as topic branches. Thus, during a typical git push command, the source branches from your repository are sent to the remote repository using a refspec such as:

+refs/heads/*:refs/heads/*

This refspec can be paraphrased as:

From the local repository, take each branch name found under the source namespace refs/heads/ and place it in a similarly named, matching branch under the destination namespace refs/heads/ in the remote repository.

The first refs/heads/ refers to your local repository (because you’re executing a push), and the second refers to the remote repository. The asterisks ensure that all branches are replicated.

..................Content has been hidden....................

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