Chapter 11. Remote Repositories

So far, you’ve worked almost entirely within one, local repository. Now it’s time to explore the much-lauded distributed features of Git and learn how to collaborate with other developers via shared repositories.

Working with multiple and remote repositories adds a few new terms to the Git vernacular.

A clone is a copy of a repository. A clone contains all the objects from the original; as a result, each clone is an independent and autonomous repository and a true, symmetric peer of the original. A clone allows each developer to work locally and independently without centralization, polls, or locks. Ultimately, it’s cloning that allows Git to scale to projects that are large and dispersed.

Essentially, separate repositories are useful:

  • Whenever a developer works autonomously.

  • Whenever developers are separated by a wide area network. A cluster of developers in the same location may share a local repository to amass localized changes.

  • Whenever a project is expected to diverge significantly along separate development paths. Although the regular branching and merging mechanism demonstrated in previous chapters can handle any amount of separate development, the resulting complexity may become more trouble than it’s worth. Instead, separate development paths can use separate repositories, to be merged again whenever appropriate.

Cloning a repository is just the first step in sharing code. You must also relate one repository to another to establish paths for data exchange. Git establishes these repository connections through remotes.

A remote is a reference, or handle, to another repository. You use a remote as a shorthand name for an otherwise lengthy and complicated Git URL. You can define any number of remotes in a repository, thus creating elaborate networks of repository sharing.

Once a remote is established, Git can transfer data from one repository to another using either a push or a pull model. For example, it’s common practice to occasionally transfer data from an original repository to its clone in order to keep the clone in sync. You can also create a remote to transfer data from the clone to its original or configure the two to exchange information bidirectionally.

To keep track of data from other repositories, Git uses tracking branches. Each tracking branch in your repository is a local branch that serves as a proxy for a specific branch in a remote repository.

Finally, you can provide your repository to others. Git generally refers to this as publishing a repository and provides several techniques for doing so.

This chapter presents examples and techniques to share, track, and obtain data across multiple repositories.

Repository Concepts

Bare and Development Repositories

A Git repository is either a bare or a development (nonbare) repository.

A development repository is used for normal, daily development. It maintains the notion of a current branch and provides a checked-out copy of the current branch in a working directory. All of the repositories mentioned in the book so far have been development repositories.

In contrast, a bare repository has no working directory and shouldn’t be used for normal development. A bare repository has no notion of a checked-out branch, either. In other words, you shouldn’t make direct commits to a bare repository.

A bare repository might seem to be of little use, but its role is crucial to serve as an authoritative basis for collaborative development. Other developers clone and fetch from the bare repository and push updates to it.

If you issue git clone with the --bare option, Git creates a bare repository; otherwise, a development repository is created.

By default, Git enables a reflog (a record of changes to refs) on development repositories but not on bare repositories. This again anticipates that development will take place in the former and not in the latter. By the same reasoning, no remotes are created in a bare repository.

If you set up a repository into which developers push changes, it should be bare. In effect, this is a special case of the more general best practice that a published repository should be bare.

Repository Clones

The git clone command creates a new Git repository based on the original you specify. Git doesn’t have to copy all the information in the original to the clone. Instead, Git ignores information that is pertinent only to the original repository.

In normal git clone use, the local, development branches of the original repository, stored within refs/heads/, become remote tracking branches in the new clone under refs/remotes/. Remote tracking branches within refs/remotes/ in the original repository are not cloned. (The clone doesn’t need to know what, if anything, the original is tracking.)

Tags from the original repository are copied into the clone, as are all objects that are reachable from the copied refs. However, repository-specific information such as hooks (see Chapter 14), configuration files, the reflog, and the stash of the original repository are not reproduced in the clone.

Making a Copy of Your Repository showed how git clone can be used to create a copy of your public_html repository:

$ git clone public_html my_website

Here, public_html is considered the original, remote repository. The new, resulting clone is my_website.

Similarly, git clone can be used to clone a copy of a repository from network sites:

# All on one line...
$ git clone 
    git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

By default, each new clone maintains a link back to its parent repository via a remote called origin. However, the original repository has no knowledge of—nor does it maintain a link to—any clone. It is a one-way relationship.[23]

The name origin isn’t special in any way. If you don’t want to use it, simply specify an alternate with the --origin name option during the clone operation.

Git also configures the default origin remote with a default fetch refspec:

fetch = +refs/heads/*:refs/remotes/origin/*

Establishing this refspec anticipates that you want to continue updating your local repository by fetching changes from the originating repository. In this case, the remote repository’s branches are available in the clone on branch names prefixed with origin/, such as origin/master, origin/dev, or origin/maint.

Remotes

The repository you’re currently working in is called the local or current repository, and a repository with which you exchange files is called the remote repository. But the latter term is a bit of a misnomer, because the repository may or may not be on a physically remote or even different machine; it could conceivably be just another repository on a local filesystem.

Git uses both the remote and the tracking branch to reference and facilitate the connection to another repository. The remote provides a friendly name for the repository and can be used in place of the actual repository URL. A remote also forms part of the name basis for the tracking branches for that repository.

Use the git remote command to create, remove, manipulate, and view a remote. All the remotes you introduce are recorded in the .git/config file and can be manipulated using git config.

In addition to git clone, other common Git commands that refer to remote repositories are:

git fetch

Retrieves objects and their related metadata from a remote repository

git pull

Like git fetch, but also merges changes into a corresponding branch

git push

Transfers objects and their related metadata to a remote repository

git ls-remote

Shows references within a remote

Tracking Branches

Once you clone a repository, you can keep up with changes in the original source repository even as you make local commits and create local branches. In fact, you can create a local branch named test without realizing that a developer working in the source, or upstream, repository also created a branch called test. Through a tracking branch, Git allows you to follow development on both test branches.

During a clone operation, Git creates a remote tracking branch in the clone for each topic branch in the original repository. The local repository uses its tracking branches to follow or track changes made in the remote repository. The set of remote tracking branches is introduced in a new, separate namespace that is specific to the remote being cloned.

Tip

You may recall from refs and symrefs of Chapter 6 that a local topic branch that you call dev is really named refs/heads/dev. Similarly, remote tracking branches are retained in the refs/remotes/ namespace. Thus, the remote tracking branch origin/master is actually refs/remotes/origin/master.

Because tracking branches are lumped into their own namespaces, there is a clear separation between branches made in a repository by you (topic branches) and those branches that are actually based on another, remote repository (tracking branches). The separate namespaces are just convention and best practice, designed to help prevent you from making accidental conflicts.

All the operations that you can perform on a regular topic branch can also be performed on a tracking branch. However, there are some restrictions and guidelines to observe.

Because tracking branches are used exclusively to follow the changes from another repository, you shouldn’t merge or make commits onto a tracking branch. Doing so would cause your tracking branch to become out of sync with the remote repository. Worse, each future update from the remote repository would likely require merging, making your clone increasingly more difficult to manage. Proper management of tracking branches is covered in more detail later in this chapter.

To reinforce that making commits directly on a tracking branch isn’t good form, checking out a tracking branch causes a detached HEAD. As mentioned in Detached HEAD Branches, a detached HEAD is essentially an anonymous branch name. Making commits on the detached HEAD is possible, but you shouldn’t then update your tracking branch HEAD with any local commits lest you suffer grief later when fetching new updates from that remote.

If you find you need to keep any such commits, use git checkout -b my_branch to create a new, local branch on which to develop your changes.



[23] Of course, a bidirectional remote relationship can be set up later using the command git remote.

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

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