+
+
+
Using git
++ First you need to tell git who you are. These commands will + write to ~/.gitconfig, and will be used to identify you when + you commit changes. Plus, I like color. +
+ +% git config --global user.name "John Doe"
+% git config --global user.email "john@doe.com"
+% git config --global color.ui=always
+
+ + Now we will clone the repository, which involves downloading + about 2MB of files. Git repositories are very compact. We + will clone the repository from github. This takes a minute or + so. +
+ +% cd
+% git clone git://github.com/pbeckingham/task.git task.git
+% cd task.git
+
+ + You just pulled the entire history of task changes since it + was uploaded to github. That will be missing about a year and + a half of prior changes, which were in Subversion. Let's + build task: +
+ +% autoreconf
+...
+% ./configure --prefix=/usr/local
+...
+% make
+...
+
+ + The task binary will be in the src directory. If you run: +
+ +% sudo make install
+
+ + Then task will be copied to /usr/local/bin, according the + --prefix argument used above. /usr/local is the default + prefix, so that argument wasn't necessary, but illustrates + it's use. +
+ ++ Meanwhile, you have just created a local copy of the + repository. You can do anything to this copy except push to + github. Only the repository owner can push to github, or + additional users identified by the owner (with additional + monthly github fee). In order to get your changes back to + github, they have to go through the owner, either in the form + of a patch via email, or by creating your own github account, + pushing to you own task repository clone (github calls it a + fork), then asking the owner to pull directly from your + repository. +
+ ++ You only need to clone once, unless you feel like starting + over, or creating additional clones. Ordinarily, you update + your local copy by pulling changes from github with: +
+ +% git pull
+
+ + Right now, nothing new should be pulled, because you just + cloned. Sometimes you'll see changes that have either been + made by the owner, or merged in from others, by the owner. + Let's take a look at the commit history: +
+ +% git log
+
+ + You see a whole series of commits. Each commit is a set of + file changes that were made somewhere. Let's look at branches. + Try this: +
+ +% git branch
+* master
+
+ + This is telling you that you have only one branch, called + master. The asterisk tells you that this is your current + branch, which is redundant because you only have one. But + there are other branches on github. See those with: +
+ +% git branch -a
+* master
+ remotes/origin/1.6.1
+ remotes/origin/1.7.0
+ remotes/origin/HEAD -> origin/master
+ remotes/origin/master
+
+ + A remote is what git calls another repository. The origin + remote is the repository that this clone originated from. + This output tells you that there is a 1.6.1 branch on github, + a 1.7.0 branch on github, and a master branch on github. It's + not obvious, but your local master (the first one shown) is + tracking remotes/origin/master, which means changes on the + remote will get merged to the local tracking branch on pull. +
+ ++ The convention used by task is to create a new branch whenever + work begins on a new version. When that version is released, + the branch is merged to master, but retained. At time of + writing, 1.6.1 is the currently released version of task, and + so remotes/origin/1.6.1 and remotes/origin/master are + currently identical, with all new development happening on the + 1.7.0 branch. When 1.7.0 is released, it will get merged to + master, and the 1.6.1 branch will be deleted. Nothing will be + lost, because 1.6.1 is already merged to master. Let's look + at tags: +
+ +% git tag
+...
+v1.4.3
+v1.5.0
+v1.6.0
+v1.6.1
+
+ + Those tags are just labels that represent the last commit for + that version. You may notice that a change in the tag naming + convention, that occurred when the owner realized that git + will not allow a tag and a branch of the same name at the same + time, so now there is a "v" in the tags. +
+ ++ Let's make a branch called 1.7.0 that tracks changes to + remotes/origin/1.7.0. That means you can pull 1.7.0 changes + from github into your local branch, to keep up to date. +
+ +% git checkout -b 1.7.0 origin/1.7.0
+Branch 1.7.0 set up to track remote branch 1.7.0 from origin.
+Switched to a new branch '1.7.0'
+
+% git branch -a
+* 1.7.0
+ master
+ remotes/origin/1.6.1
+ remotes/origin/1.7.0
+ remotes/origin/HEAD -> origin/master
+ remotes/origin/master
+
+ + Now you can see that 1.7.0 is your current branch (*). That + means you are looking at the 1.7.0 codebase. Let us now + assume you intend to make a change, and submit the patch. We + will add Solaris 8 as a supported OS. This will affect two + files. First check status: +
+ +% git status
+# On branch 1.7.0
+nothing to commit (working directory clean)
+
+ + No changes. That's what we expect. Now make the changes (any + editor will suffice, but assume vi): +
+ +% vi NEWS
+% vi html/task.html
+
+ + Now we expect to see changes. Status says: +
+ +% git status
+# On branch 1.7.0
+# 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: NEWS
+# modified: html/task.html
+#
+no changes added to commit (use "git add" and/or "git commit -a")
+
+ + Git sees that those two files have changed, but as git states, + they are not added to the commit. Git allows you to stage + changes, then commit the staged changes - a two-step process + that gives you complete control. Git also allows you to + commit all changes and bypass the staging, but that's a + shortcut that is risky, because you can inadvertently commit + things you didn't want to. Let's see what git thinks changed: +
+ +% git diff
+diff --git a/NEWS b/NEWS
+index 74adecd..30d4f8f 100644
+--- a/NEWS
++++ b/NEWS
+@@ -12,6 +12,7 @@ Task has been built and tested on the following configurations:
+ - Ubuntu 8.10 Intrepid Ibex
+ - Ubuntu 9.04 Jaunty Jackalope
+ - Arch Linux
++ - Solaris 8
+ - Solaris 10
+ - Cygwin 1.5.25-14
+
+diff --git a/html/task.html b/html/task.html
+index 66ee777..a2254f6 100644
+--- a/html/task.html
++++ b/html/task.html
+@@ -193,6 +193,7 @@
+ <li>Ubuntu 8.10 Intrepid Ibex
+ <li>Ubuntu 9.04 Jaunty Jackalope
+ <li>Arch Linux
++ <li>Solaris 8
+ <li>Solaris 10
+ <li>Cygwin 1.5.25-14
+ </ul>
+
+ + Git has correctly spotted the changes. The "git diff" command + always tells you the difference between the last commit and + the current state. Now we will stage the two changes: +
+ +% git add NEWS html/task.html
+% git diff
+
+ + No changes are reported. That's because if files are staged, + then diff shows the difference between the staged files and + the current state. We staged all changes, hence no diff. If + we wanted to see the difference between the last commit and + the staged files, try this: +
+ +% git diff --cached
+(same as unstaged diff)
+
+ + Now the status shows that the files are staged: +
+ +% git status
+# On branch 1.7.0
+# Changes to be committed:
+# (use "git reset HEAD <file>..." to unstage)
+#
+# modified: NEWS
+# modified: html/task.html
+#
+
+ + Now a commit command will commit the staged files: +
+ +% git commit -m "Added Solaris 8 as a supported platform"
+[1.7.0 03308eb] Added Solaris 8 as a suported platform
+ 2 files changed, 2 insertions(+), 0 deletions(-)
+
+ + Now make a patch: +
+ +% git format-patch HEAD^
+0001-Added-Solaris-8-as-a-supported-platform.patch
+
+ + HEAD is a label that means the current head of the branch, or + in other words, what was last committed. HEAD^ means the + commit before that. HEAD~2 is the one before that, HEAD~3 + etc. When we say create a patch of HEAD^, it means the same + as: +
+ +% git diff HEAD^
+
+ + Which means show the difference between the previous commit + and the current commit, but the patch has extra identifying + information in it. Take a look at that patch file. If you + ran: +
+ +% git format-patch HEAD~10
+
+ + Git will create 10 patch files, one for each commit. To get + the patch applied to the repository, email it to the owner. + The owner will then apply the patch with: +
+ +owner> git apply 0001-Added-Solaris-8-as-a-supported-platform.patch
+
+ + Then push the changes with: +
+ +owner> git push
+
+ + And that makes them available on github, which means in turn + that the next time you run: +
+ +% git pull
+
+ + Your changes will have come full circle. +
++
+
+ Copyright 2006-2009, P. Beckingham. All rights reserved. +
+