Let's face it - anyone with anything more than a passing interest in the Drupal community is probably aware that we're in the midst of embracing Git, "the fast version control system". As with just about everything else in our community, we are continuously jettising outdated technology and replacing it with modern solutions. Leaving CVS was a rip-off-the-bandaid sort of moment for the community - one day it was there, the next day it was gone.
In this article, I'll share my starting point - my experiences with different version control systems as of about two weeks ago - and describe the process I took to learn the basics of Git, up to the point where I was able to (ridiculously easily) update a small module I maintain on Drupal.org. This article isn't going to attempt to explain how to understand or use Git (you're welcome for that) - rather it is going to explain how I learned to understand and use Git - an important distinction. Hopefully this will help other developers travel along the same path.
As a Drupal developer with 5+ years under my belt, I've learned to co-exist with CVS (when I had to), but ultimately chose (like many others) Apache Subversion (SVN) as my day-to-day version control system. I became a master of "svn add" and "svn commit", but anything past that almost always required a trip to to the online handbook (or requests for help from my command-line-guru friends). When it was announced last year that Drupal was moving to Git, I decided that I would jump in with both feet - not only would I perform my due diligence to get up-to-speed with it for working within the community, but also for personal and client work.
I want to embrace Git more than I've embraced SVN - I want to understand it so that I'm comfortable explaining it to others (the true test of knowledge, in my opinion) as well as using it day-to-day.
I've spent a good portion of my spare time in the last couple of weeks reading about Git from a number of different sources. I'm a firm believer that different people learn in different ways, so I rarely read just a single source in an attempt to learn about a specific topic. A few months ago, I saw a tweet from a friend of mine that Rockable Press's Getting Good with Git eBook was being offered temporarily for free (it is currently $19). I snapped it up knowing that the Drupal community was moving in that direction. It's a great, gentile introduction that doesn't dive too deep, but provides a nice basis for working with Git. While it barely covers working with remote repositories (a must for working with Drupal.org or in a team situation), the writing style put me at ease.
The next resource that I found is guides.github.com - this free resource is broken up into various sections, with the first couple having corresponding screencasts. It appears to be a community effort, but the diagrams and text are well thought out and definitely allowed me to build upon what I read in "Getting Good with Git". The screencasts are must-sees for Git newbies.
At this point, I felt like I was ready to go. I wanted to install Git on my MacBook Pro (running OS X 10.6.6) and follow along with the lessons I was reading. I followed the link from the first lesson of learn.github, selected "OS X" and arrived at this download page. Wha? Which version do I want?
I was able to narrow it down pretty quickly by deciding that I wanted the latest stable version (126.96.36.199), but I was flummoxed by the "i386" vs. "x86_64" choice (I know, I just lost a little bit of geek cred). I decided on the "x86_64" version - not because I had any special knowledge, searched google, or asked a more nerdy friend, but because I am aware that my laptop has an Intel chip (that's the x86 part, right?) and I assumed that the "64" referred to 64-bit (which is always better than 32-bit - it's twice as much!) Luckily, my logic was bulletproof, and the installer ran without a hitch (phew).
Sorry to my Windows and *nix friends - I can't help you in choosing an installer - maybe you'll get lucky like I did. Also, I'm aware that if you have MacPorts installed on a Mac, getting Git is a single commandline line affair, but I didn't have MacPorts installed was looking for a simple installer.
Alrighty, so now I had Git installed. Now what?
I went back to Getting Good with Git and guides.github.com and started working my way through the lessons. In some cases, Git commands are one-to-one with SVN, at other times, it's a whole different mindset. For a beginner, I think that if you're comfortable with the basics of SVN, you'll be comfortable with the basics of Git.
I went ahead and created a Git repository to play with, I added, removed, and modified files. I branched, made changes to the branch, checked out the master, saw that the changes weren't there, then checked out the branch and saw the changes magically re-appear. One of the nice things about Git is that branches don't get their own directory path, they are stored internally in the Git repository. When you check out a branch, Git replaces your working copy with it. When you change to another branch, or go back to the master, the same working copy is updated with the appropriate code. You don't ever have to worry about the directory you're in, only the branch that is currently checked out.
I was at about this point when uber-Drupal developer chx tweeted about "The 'wonder' git documentation" - Chx claimed that "you can only really use Git if you understand how Git works". Those that only memorize commands are weak and puny and Chx has no time for you (paraphrasing). Seeing how I respected chx's work in the community and have always tried to catch his sessions at varous DrupalCons (he's not presenting in Chicago? Is that true?) in order to realize how inferior my coding skills actually are, I took his tweet as a personal challenge.
Chx was right (duh, of course). I quickly digested the first five-sixths of the documentation ("rebasing" still makes my head hurt a bit). I learned about objects, heads, SHA1 names, and how commits are related to one another. It really cemented everything I had read in Getting Good with Git and on learn.github. For anyone serious about understanding Git, it's a must-read.
Updating a Contrib Module
Now that I (mostly) felt comfortable with the Git workflow on my local machine, it was time to figure out how to use Git to have a local repository interact with a non-local repository. In other words, I wanted to grab a copy of the Git repository of a small module that I maintain on Drupal.org, make some changes, then push those changes back up to Drupal.org. This is a process that all Drupal contributors will need to be able to perform moving forward.
Luckily, members of the Drupal community (Damien Tournoud, Angie Byron, Peter Wolanin, Melissa Anderson, Randy Fay, Fabian Franz, Dan O'Brien Muzyka, and others) did an outstanding job writing up a Git handbook on Drupal.org with both general Git information and Drupal.org specific topics. I also found Jeff Geerling's blog post about getting started with Git on Drupal.org to be helpful (short and to the point) as well.
If you're not a maintainer of a contrib module on Drupal.org, while you won't have "git push" access to any contrib modules, you'll still be able to utilize the Drupal.org Git sandbox. This is a new feature (not available in the CVS days) where all Drupal.org registered users have access to their own Git sandbox on Drupal.org. This means that you can create Git repositories on your local machine, push them up to your sandbox on Drupal.org, and share your code and repository with other members of the community. This is HUGE.
Since I was planning on performing some updates to my contrib module, I also needed to set up my SSH keys so that I didn't have to enter my Drupal.org password every time when pushing code back up to the server. Using the Authenticating with Git documentation on Drupal.org, this was a fairly straight-forward process that took about 5 minutes.
At this point, I was ready to download ("git clone") my contrib project from Drupal.org and start making changes. I started with the OG Invite Restrict module. This small (and rarely used) module limits the Organic Groups invitation page to only current site members. It also adds autocomplete and RealName support to the OG invite form. There were a couple of small issues in the queue that I knew I could take care of relatively quickly, so I figured this was a good place to start.
Every contrib project on Drupal.org now has a new "Git instructions" local task (tab) - this replaced the old "CVS instructions". The instructions on the page are slightly different depending on if you're a module's maintainer or not (the image above is my view of the page as a maintainer). I have a relatively clean (not too many modules or customizations) up-to-date version of Drupal 6 on my local machine that I use to test-drive modules, it is here that I wanted to clone the OG Invite Restrict repository from Drupal.org so that I could make changes. Using the commandline, I navigated to sites/all/modules, then ran the Git command to clone the OG Invite Restrict repository as shown on the "Git instructions" page:
git clone --branch 6.x-1.x [email protected]:project/og_invite_restrict.git
The "git clone" command grabs the entire repository for the branch specified and automatically remembers where it came from (Git calls the source the "origin" - this will be important in a few minutes). Within a few seconds the repository was downloaded and appeared as sites/all/modules/og_invite_restrict. I navigated into the directory and did an "ls -al" to ensure that there was, in fact, a .git directory - this contains the entire repository - not just the most recent version. The entire commit history for the branch I cloned of OG Invite Restrict (this is one of the wonders of Git) was now on my local machine. Sweet.
At this point, I was ready to make my code updates - I actually fulfilled two issue requests as well as re-running the code through the most-excellent Coder module. For each fix, I committed the changes to the repository (using "git commit"). It wasn't necessary for me to create a new branch or tag (to mark a release), so the process was really straight-forward.
Once I was satisfied with the changes, it was time to "git push" the changes back to up Drupal.org where the magic packaging script would see them, and create a new (-dev) release for the module. Again, the "Git instructions" page of the project had everything I needed to know. All I had to do from the command line (from sites/all/modules/og_invite_restrict) was:
git push origin 6.x-1.x
This command pushes all of my commits to the "6.x-1.x" branch to Drupal.org.
It was crazy-easy for me to do, and took me way less time and effort than I origially thought. Once I updated the open issues in the issue queue, there was nothing left to do but to wait for the magic packaging script to come by and see that there was some new code to wrap up in a nice little downloadable package. Then next morning, I checked the project page, and the -dev version was updated (as evidenced by the "March 1, 2011" date)!
As I said at the outset, this wasn't going to be a "how to use Git" article. Clearly, there are a number of steps that I left out in order to keep this article to a reasonable length (stop laughing). Hopefully I've encouraged other contrib module maintainers to give Git a try - it's really not nearly as high a hurdle as you think.
Nice summary of git resources!
I will like to add this to the list: Learn by doing http://gitimmersion.com
and this pdf : Git from the bottom up http://ftp.newartisans.com/pub/git.from.bottom.up.pdf
Good call on the Git Immersion link - I had actually checked that one out but I must have failed to save it. Thanks.
The "Git from the Bottom Up" PDF looks very useful as well - I can't wait to check it out.
I am curious about your workflow: Say you are updating a module like you illustrated. Do you git clone somewhere in your htdocs and work right from there or are you cloning, copying your work into your htdocs and then copying it back to your local git and then committing and pushing the changes?
When I'm updating an existing contrib module, I normally git clone into an existing Drupal installation that I use for testing/evaluating modules. This installation is normally relatively "clean" - it doesn't have any custom modules doing anything wacky, nor is it an existing client site. I tend to start with a fresh install of Drupal every few months for this "play" area.
So, I'm doing a "git clone" right into sites/all/modules, I make my changes (committing locally as necessary), then I either create a patch or "git push" (if I have permission).
Thanks for this introduction. I also scooped up the Rockable book during the free offer. It's a great intro.
What I did first though, which I highly recommend (especially for anyone who hasn't used version control beyond the basics) is to read The Git Parable (http://tom.preston-werner.com/2009/05/19/the-git-parable.html) and then read it again, until you understand the concepts and terminology. Has really helped me.
Very helpful article ... I would also like to recommend the book "Pro Git" which can be bought in hardcopy or it can be read for FREE online as webpages at http://progit.org/book ... this book uses colored diagrams to explain difficult to grasp concepts ... for example go to chapter 1, page 3 (online) and scroll to the bottom of the page where figure 1-6 illustrates the concept of checkout/stage/commit sweetly. Added to this article these are great places to start learning Git.
PS: I was told it is *never* spelled "GIT" (all caps) because it is not an acronym for anything .. use "Git" or "git" if you want to sound like you know what you are talking about. :)
Good call on the Git Immersion link - I had actually checked that one out but I must have failed to save it. Thanks.