Thursday, December 31, 2009

I wanted to try out git on the Mac. I'm reading the book Pragmatic Version Control Using Git by Travis Swicegood. There's a forum discussing this book on the Pragmatic Programmer's site, http://forums.pragprog.com/forums/64. The forum seems to be more focused on reviewing the book than discussing git issues, however.

Installing and Configuring

I have a Mac Book Pro (Intel) with Snow Leopard. To get MacPorts I went to the site http://www.macports.org/install.php and clicked on Snow Leopard.




Once MacPorts is installed, I issued the command

newtricks:~ ted$ sudo port install git-core +svn +doc

There's a Pragmatic Programmer forum entry that discusses how this macport installation of git did not work, but it worked fine for me. I can tell git is installed and working by checking its version.

newtricks:~ ted$ which git
/opt/local/bin/git
newtricks:~ ted$ git --version
git version 1.6.5.7
newtricks:~ ted$

There are only two required configuration values: user.email and user.name. Here's how you set them; they are silent commands.

git config --global user.name "Ted Kubaska"
git config --global user.email "ted.kubaska@gmail.com"

Although not required, the configuration value color.ui is useful. It color codes various git output. I'll show some examples later.

Display the configuration as follows.

newtricks:~ ted$ git config --global --list
user.name=Ted Kubaska
user.email=ted.kubaska@gmail.com
color.ui=auto
newtricks:~ ted$

Creating a Git Repository

Creating a git repository is pretty easy, in fact trivial. Just make a directory, enter it, and issue a git init. Then you can add files into this repository with git commit. This directory will be the working tree of code you check out from the repository. The repository metadata is in the directory/.git, and, guess what, its contents don't look like CVS.

So I do this ...

newtricks:GitRepo ted$ mkdir tedsrepo
newtricks:GitRepo ted$ cd tedsrepo/
newtricks:tedsrepo ted$ git init
Initialized empty Git repository in /Users/ted/GitRepo/tedsrepo/.git/
newtricks:tedsrepo ted$ ls -a
. .. .git
newtricks:tedsrepo ted$ pwd
/Users/ted/GitRepo/tedsrepo
newtricks:tedsrepo ted$

Then, in that directory, make a file (call it hello.html) to add to the repository.

newtricks:tedsrepo ted$ git add hello.html
newtricks:tedsrepo ted$ git commit -m "Initial checkin for hello.html"
[master (root-commit) f2c49ba] Initial checkin for hello.html
1 files changed, 6 insertions(+), 0 deletions(-)
create mode 100644 hello.html
newtricks:tedsrepo ted$ git log
commit f2c49baf3abafefb03b941db75ae4c026b0c877e
Author: Ted Kubaska <ted.kubaska@gmail.com>
Date: Tue Dec 29 21:07:15 2009 -0800

Initial checkin for hello.html
newtricks:tedsrepo ted$

Make a change in hello.html. Before you can commit the changed file, you must stage it. This is something that seems unique to git. You edit a file, and then you can't just commit it ... you must stage it first.

newtricks:tedsrepo ted$ git status
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: hello.html
#

no changes added to commit (use "git add" and/or "git commit -a")
newtricks:tedsrepo ted$

Notice that a modified, but unstaged file is shown in red. This is a result of that color.ui configuration value.

So stage the file before committing. Stage with git add. Note that the filename becomes green.

newtricks:tedsrepo ted$ git add hello.html
newtricks:tedsrepo ted$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: hello.html
#
newtricks:tedsrepo ted$

Then, commit.

newtricks:tedsrepo ted$ git commit -m "added head and title"
[master 4b7d2f1] added head and title
1 files changed, 3 insertions(+), 0 deletions(-)
newtricks:tedsrepo ted$

Branches

With CVS, I've always been very careful not to proliferate branches. But I think (from what I've read so far) that branches are key to the way people use git.

The name of the default branch in git (the branch you start with, the mainline, if you will) is called master. Master in Git is what I would call HEAD in CVS.

I thought it was interesting that you can create a branch, checkout the branch, edit a file and commit it to the branch. Then, checkout the master and edit and commit. You now have one version of the file in the branch and another in the master. Now if I rebase the master, the file in master has the changes that were made in the branch as well as the changes made on master. This sounds like a merge to me, although it's not technically a merge because there is a merge command. I suppose I'll see the difference when I start using the merge commands.

Here's what I mean in more detail. The following figure illustrates the actions I'm describing.



Let's say I'm on the master branch of my git repository. I put three lines in that file. I commit the file, then make a branch called R1.0. I edit the file again while still on master (the file now has four lines) and commit it.

Master line 1
Master line 2
Master line 3
Master line 4 <-- this is the line I added on master (not the branch)

Then, I checkout the branch and edit/commit the file.

Master line 1
Release line 1 <-- this is the line I added on the branch (not master)
Master line 2
Master line 3

Then, I checkout the master and rebase master with the branch. My file now has the changes from both the branch and master.

Master line 1
Release line 1
Master line 2
Master line 3
Master line 4

Here's the output I got from the rebase command.

newtricks:tedsrepo ted$ git rebase R1.0
First, rewinding head to replay your work on top of it...
Applying: added 4th master line
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging hello.txt
newtricks:tedsrepo ted$ git branch -d R1.0
Deleted branch R1.0 (was f3a999b).

As I said, it looks like a merge to me, but I've more to learn.

What is also interesting is that (with the branch checked out), you can tag it. Then, you can checkout master, rebase master with the branch, and actually delete the branch. You can restore the branch by make a new branch from the tag, like ...

newtricks:tedsrepo ted$ git branch R1.0 1.0

where 1.0 is the tag. I made the tag when the branch (called R1.0) was checked out as

newtricks:tedsrepo ted$ git tag 1.0 R1.0



Git
12/31/2009 4:32:37 PM (Pacific Standard Time, UTC-08:00)  #    Disclaimer  |  Comments [0]  |  Trackback
Related Posts:
Using Textmate's Git Bundle
The Git GUI

Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):