Git Notes

These are updated by me periodically. I have tried my best to illustrate common use cases, and the motivation for doing things the “Git” way.

Example Set Up

I’ll use this setup scenario frequently. In a suitable scatch repository (i.e. git-sandbox), make a fake remote:

mkdir fake-remote
cd fake-remote
git init --bare
cd ..

Now, clone it, pretending you are two developers:

git clone fake-remote jerry-repo
git clone fake-remote kramer-repo

Let’s assume you’re Jerry and Kramer is another programmer in your group. As Jerry, let’s make some changes:

cd jerry-repo
echo "an example file" > file.txt
git add file.txt
git commit -am "initial import"
git push origin master
cd ..

Now, let’s pretend we’re Kramer and grab that recent commit:

cd kramer-repo
git pull origin master
cd ..

Git Remote Tracking Branches

Git remote tracking branches are similar to local branches (i.e. the kind you interact with git checkout -b branch-name and see with git branch). However, you don’t work on the remote branch directly, you work on a local branch that’s tracking this remote branch. For example, the most common workflow is to track a remote branch, then push your commits to it or pull commits down from it. Even though it’s a “remote” tracking branch, the branch is stored locally (this branch doesn’t disappear if you can’t connected to the remote).

Git remote tracking branches always have the format remote-repo/remote-branch. After cloning a repository, you can set it to track a remote tracking branch with the -u option of git push, e.g. git push -u origin master. From now on, you can just use git push when on this branch; this branch is tracking origin’s master branch.

git branch shows local branches; to see remote branches use git branch -r, and to see all branches, use git branch -a.

Remote tracking branches are also what determine what is pulled/pushed when using git pull and git push without a remote repository and refspec (i.e. git push origin master).

If the current branch is new-feature, which tracks origin/new-feature, then any branches checked out from new-feature will also track the remote too, unless --no-track is added.

Git Fetch and Merge vs. Git Pull

Recall the above point that remote tracking branches are local, so (unlike Subversion) they function even when you’re not able to connect to the remote. This gives an example of how elegant Git is: being so similar to regular branches, Git remote tracking branches can be merged into local branches. This is precisely what goes on behind the scenes with git pull. Here’s an example. First, let’s set it up such that a developer in your group, Kramer, made some changes, committed them, then pushed them to the remote.

# assuming you're in the right directory
cd kramer-repo
echo "kramer adding gibberish" >> file.txt
git commit -am "I added some gibberish"
git push
cd ..

Now, imagine you (Jerry) have made some commits but want to see what the status of the remote looks like. git remote show can be used to see if the local remote tracking branch is out of date.

vinceb@poisson$ git remote show origin
* remote origin
  Fetch URL: /Users/vinceb/Desktop/git-sandbox/fake-remote
  Push  URL: /Users/vinceb/Desktop/git-sandbox/fake-remote
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (local out of date)

So we are out of date! We can see these commits before merging them in with git fetch. git fetch updates your remote tracking branch with the new changes, allowing you to diff branches just as you would with two regular branches.

vinceb@poisson$ git diff master origin/master
diff --git a/file.txt b/file.txt
index 4e850ce..34ceb34 100644
--- a/file.txt
+++ b/file.txt
@@ -1 +1,2 @@
 an example file

git log origin/master master also works. git log origin/master ^master shows us just the new commits. We could really explore these commits by checkout out the remote tracking branch (but consider this to be “taking a visit”; don’t commit anything). Suppose we did, and we decide we want to merge them with our current branch. For this, we just use git merge: remember remote tracking branches are just branches!

vinceb@poisson$ git branch ## always check what branch you're on!
* master
vinceb@poisson$ git merge origin/master
Updating ee922a9..8c8c240
Fast-forward
 file.txt |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

Note that git pull basically is git fetch && git merge.

Great resources