Inspecting Remote Data
So, what exactly did we achieve by connecting this new remote? Let's look at the list of branches:
$ git branch -va contact-form 56eddd1 Add new contact form page * master 56eddd1 Add new contact form page remotes/origin/HEAD -> origin/master remotes/origin/master 2b504be Change headlines for about and imprint
Well, apparently not much happened: still our two local branches ("master" and "contact-form") and two items from our "origin" remote ("remotes/origin/HEAD" and "remotes/origin/master"). So why don't we see any data from our new "crash-course-remote"? Because, with the "git remote add" command, we have only established a relationship - but no data was exchanged so far.
Remote Data is a Snapshot
Git stores information about remote data (like branches, commits, etc.) in your local repository for you. However, there is no "live" connection to your remote. E.g. you will not automatically see new commits or branches that your teammates published on a remote - because you have to explicitly tell Git to update!
The information about remote branches, remote commits, etc. is only as fresh as the last snapshot that you requested. There is no "automatic" update in the background.
To update the information about a remote, you have to explicitly request this data. Most notably, a "Fetch" operation does this for you:
$ git fetch crash-course-remote From https://github.com/gittower/git-crash-course-remote * [new branch] faq-content -> crash-course-remote/faq-content * [new branch] master -> crash-course-remote/master
Fetch will not touch any of your local branches or the files in your working copy. It just downloads data from the specified remote and makes it visible for you. You can decide later if you want to integrate new changes into your local project.
After updating our information about the "crash-course-remote", let's take another look at the available branches:
$ git branch -va contact-form 56eddd1 Add new contact form page * master 56eddd1 Add new contact form page remotes/crash-course-remote/faq-content e29fb3f Add FAQ questions remotes/crash-course-remote/master 2b504be Change headlines f... remotes/origin/HEAD -> origin/master remotes/origin/master 2b504be Change headlines for about and imprint
Now we also get information about the branches on "crash-course-remote".
Let's start working on that "faq-content" branch. Currently, however, this is only a remote branch pointer. To be able to work with this branch - to have our working copy populated with its files - we need to create a new local branch that's based on this remote branch. We're telling the "git checkout" command which remote branch we want to have:
$ git checkout --track crash-course-remote/faq-content Branch faq-content set up to track remote branch faq-content from crash-course-remote. Switched to a new branch 'faq-content' $ git branch -va contact-form 56eddd1 Add new contact form page * faq-content e29fb3f Add FAQ questions master 56eddd1 Add new contact form page remotes/crash-course-remote/faq-content e29fb3f Add FAQ questions remotes/crash-course-remote/master 2b504be Change headlines f... remotes/origin/HEAD -> origin/master remotes/origin/master 2b504be Change headlines for about and imprint
This command does a couple of things for us:
- (a) It creates a new local branch with the same name as the remote one ("faq-content").
- (b) It checks this new branch out, i.e. it makes it our local HEAD branch and populates our working copy with the associated files from that branch's latest revision.
- (c) Since we're using the "--track" flag, it establishes a so-called "tracking relationship" between the new local branch and the remote branch it's based on.
In general, branches have nothing to do with each other. However, a local branch can be set up to "track" a remote branch. Git will then inform you if one branch contains new commits that the other one doesn't have:
- If your local branch contains commits that haven't been published / pushed to the remote repository, your local branch is "ahead" of its remote counterpart branch by some commits.
- If your teammates, on their part, have uploaded commits to the remote, the remote branch will have commits that you haven't downloaded / pulled to your local branch, yet. Your local branch is then "behind" its remote counterpart branch.
In case such a tracking relationship exists, Git will inform you about any discrepancies when performing "git status":
$ git status # On branch dev # Your branch and 'origin/dev' have diverged, # and have 1 and 2 different commits each, respectively. # nothing to commit (working directory clean)
When creating a new local branch that is based on an existing remote branch, establishing a tracking connection is easy: simply use the "git checkout" command with the "--track" flag set.
With a new local branch "faq-content" checked out, we're ready to contribute to this feature. Let's make some modifications to the "faq.html" file that you now have on your disk (I leave the details of these changes to your imagination...):
$ git status # On branch faq-content # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working # directory) # # modified: faq.html # no changes added to commit (use "git add" and/or "git commit -a") $ git add faq.html $ git commit -m "Add new question" [faq-content 814927a] Add new question 1 file changed, 1 insertion(+)
Now it's time to share these brilliant changes we've just made with our colleagues:
$ git push
On your machine, this "git push" command will not work because you don't have write access to our course remote repository. If you want to follow along and execute this command yourself, I recommend you create your own remote repository, for example on GitHub or Beanstalk.
The "git push" command uploads all the new commits from our current HEAD branch to its remote counterpart branch.
Tracking Connections Revisited
By default, the "git push" command expects us to provide it with two things:
- (a) To which remote repository we want to push.
- (b) To which branch on that remote repository we want to push.
The full command, therefore, looks something like this:
$ git push crash-course-remote faq-content
With the tracking connection that we've set up already, we've defined a "remote counterpart" branch for our local branch. Git can then use this tracking information and lets us use the "git push" and "git pull" commands without further arguments.