Collaboration

Git provides collaboration based on two very simple ideas:

Once you've learned to do these two simple things, the rest is a matter of applying what you already know.

The most common scenario is that someone is hosting a Git repository publicly, and you want to work with a copy of that repository.

To do that, first create a new repository:

$ git init

Next, add the repository you want to copy as a remote repository named origin:

$ git remote add origin git://github.com/git/hello-world.git

That command simply adds a name for the url you give it. The name "origin" is special; whenever you try to do something with a remote repository and do not specify its name, Git will assume you mean "origin".

To read from the repository, use the fetch command:

$ git fetch origin

You'll see output like this:

warning: no common commits
remote: Counting objects: 158, done.
remote: Compressing objects: 100% (79/79), done.
remote: Total 158 (delta 54), reused 157 (delta 54)
Receiving objects: 100% (158/158), 15.62 KiB, done.
Resolving deltas: 100% (54/54), done.
From git://github.com/git/hello-world
 * [new branch]      master     -> origin/master

Git has created a new "remote branch" called origin/master.

Much like revisions in the past, you cannot commit to remote branches. In order to make commits or do much of anything useful, you must create a local branch.

To create and move to a local branch named master, based on origin/master, run:

$ git checkout origin/master -b master

Because this was an empty repository, the master branch was already checked out even though it doesn't exist yet. This causes Git to emit the following message, which I assure you is perfectly harmless:

warning: You appear to be on a branch yet to be born.
warning: Forcing checkout of origin/master.
Branch master set up to track remote branch refs/remotes/origin/master.
Already on branch "master"

You can use the "git clone" command as a shortcut to do all of the above. Simply give it a url and a directory, and it will create a new local repository, create a new remote named "origin", fetch from it, and create a local tracking branch.

However, if you have an existing repository that you want to interact with a new remote repository, you must be able to use the above commands.

You can add as many remote repositories as you like. If the url of a remote changes, you can delete the remote and add a new one with the same name and a new url. You can name your local branches whatever you like, regardless of what they are named in the remote repository, but naming them the same makes things a little bit more convenient. Technically, the remotes don't even have to be from the same project, but there's usually no good reason to use a single git repository with multiple projects.

You can update your remote branches at any time by running:

$ git fetch origin

This will move origin/master to match the state of the master branch in the origin repository.

It will not change your local master branch.

To update your local master branch based on origin/master, you can use the rebase command or the merge command.

If you do not make any commits to your local branch, the choice is easy. Both of them will do a fast-forward, moving your local branch to the remote branch.

If you do make commits to your local branch, you'll need to decide whether to use merge or rebase. Their advantages and disadvantages are discussed in part 5.

To throw out any changes you've made (in commits, your index, or in your local tree) and move your local master branch to match origin/master, use the reset command:

$ git checkout master
$ git reset --hard origin/master

If you have write access to a remote, you can update the branches in the remote repository by using the push command:

$ git push origin master:refs/heads/master

The part before the : can be any local revision. The part after the : names a branch in the remote repository to be updated. The "refs/heads/" bit is a way of saying very explicitly that you are giving Git the name of a branch. If you specify refs/heads/, Git will create the remote branch if it does not exist yet (for example, when you're pushing to a new, empty repository).

Usually, you can get away with doing this:

$ git push origin master

If a branch exists in the remote repository called master, Git will assume you mean to push to that branch.

Git push will only modify the remote branch by doing fast-forwards. If the remote branch has commits that are not in your local revision, Git push will fail. This is a safety feature to prevent you from accidentally removing commits from the remote repository.

If you need to override the restriction, you can use the --force switch. If you do a non-fast-forward update, people are likely to notice when they try fetch from your repository. I recommend you avoid non-fast-forward updates to public repositories.

Some strange things happen when you push to a branch that is checked out in the remote repository. The branch is updated, but the index and local tree are not. This is especially problematic when the index or local tree have uncommitted changes.

For this reason, Git hosting services will give you bare repositories. Bare repositories do not have an index or working tree.

You can create a bare repository by using the --bare switch with the init or clone command.

Vincent Povirk