Up to this point we've mostly looked at how things work rather than how they are made. Though we won't start building anything just yet, it is time to take a step in that direction and look at some of the programs we'll be using to build our application.

As you might expect, there are many tools available to accomplish the necessary tasks involved in building a complete web application, but even more numerous are people's opinions about which are best.

The aim of this book is not to convince you that these tools are better than their competitors, but instead to offer suggestions as to dependable options, options that tend to be favorites in the Ruby and Rails communities.

6.1 | Unix

Without question, the most foundational of the preferences in the Rails community is that for Unix-like operating systems in general and for Mac OS X specifically.

Examples of operating systems would be Mac OS X, Microsoft Windows, and Linux.

Personally, I run Linux (Linux Mint 14 MATE 64-bit) and don't have any trouble following along with Rails tutorials and screencasts made by and for people using OS X. The reason for this is that Linux is also a Unix-like operating system and that its default shell, like OS X, is Bash.

More on Bash next section.

So if you're on a Mac, great! You won't have have to configure much.

And if you're on Linux, even better! Because that's what I'm running.

But if you happen to be on Windows, I highly encourage you to create a Virtual Machine (VM) or Live USB (or Live CD) of Linux to follow along. Downloading Linux is free and running it as a VM will let you stay in Windows while using a Live USB will require you to restart your machine and boot Linux off of the USB drive (instead of Windows).

You can even (carefully) install Linux on your machine this way if you like it, but it's not necessary to follow along.

For a detailed walkthrough of how to set up a virtual machine for yourself, please can check out my blog post on the subject.

It should still apply, but downloading and using the latest version of Linux Mint is recommended!

To create a Live USB, I've used a method like the one described in this video, but this looks like a viable alternative.

Having said all of that, you can use both Ruby and Rails in Windows as well as all of the tools in this chapter with the glaring exception of Bash. And though you're certainly welcome to download and install them in Windows on your own, I've never done anything of the sort and won't be able to be of any help.

Additionally, I wrote this book with Unix-like systems in mind, so there may be some things that won't transfer directly to Windows.

6.2 | Bash

So what is Bash?

Bash is the default shell for many Unix-like systems, including OS X and Linux.

Before the advent of the Graphical User Interface (GUI) computer users would have do everything by typing commands to their computer, instead of clicking on something on the screen. There were no windows and no mouse, just text and the keyboard.

The means by which we can interact with our computers have certainly increased and evolved significantly, but we can still access a shell from most any modern operating system today. OS X and Linux in particular, both being Unix-like, stay true to their roots and allow for easy access to a shell (Bash by default) via a terminal application.

Here's me screwing around in a terminal on my machine:

Linux Terminal

The terminal is also referred to as the CLI (Command Line Interface). The term "shell" is different than these terms, but they've come to be used more or less interchangeably.

Also, other shells have grown in popularity, Zsh most notably, but Bash is still the default.

You're encouraged to look around, but an understanding of Bash will cover all the necessary parts of a good shell.

To open a terminal in OS X, it's my understanding that you can go to: Applications -> Utilities -> Terminal

In Linux Mint, I see it under: Main Menu -> Accessories -> Terminal

Your variety of Linux might have it somewhere else, but I've typically seen it under "Accessories" in the distros I've used.

All right, fire up a terminal and let's get started!

You won't need to remember every last thing in this section to get started with Rails, but what you'll see here lays the foundation for working in the command line, which Rails does require.

File System and Navigation

First of all, we're going to need to know how to move around, and to know how to do that it would sure help to know where we are.

Type in pwd and hit ENTER. In my terminal, this prints /home/brad.

What on earth is pwd?

pwd is a Bash command. To figure what it does, let's look at its manpage using the man command:

$ man pwd

Whenever you see $ at the front of a line like this, it indicates that it is intended to be run in a terminal. Most systems will have some kind of special character like $ preceding the flashing cursor where your commands are typed.

Other characters sometimes used for this purpose include % and #.

I won't reproduce the whole manpage here, but just in case you don't have a terminal handy while reading along, the manpage shows "NAME" is shown to be pwd - print name of current/working directory.

Okay... but what is man?

Answering this is easy, if not a little recursive:

$ man man

"man - an interface to the on-line reference manuals"

So man is a command to view the manual page (manpage) for a command.

Let's go back to our results from pwd now. What does /home/brad mean?

Any path in a Unix-like system that leads with a / is an absolute path for that file system. In fact, / all by itself is the path to the top-most directory, which is referred to as the root directory or, more simply, root.

If you're coming from Windows, this may look strange since you're likely used to absolute paths looking like C:\Users\Brad\My Documents\. Unix-like systems don't use the physical drive prefix (like the C:\ in Windows) due to the way they allow for the mounting of partitions.

Though interesting, the details of this difference are not strictly necessary to understanding what we're doing here.

Additionally, home and brad are both names of directories, with home containing brad. These names demonstrates a convention in these systems for lowercase directory names; that is, though uppercase characters are permitted in directory names, they are discouraged.

Another convention is to avoid spaces in these names, but if you insist of using them you'll have to escape the spaces with a \ like so: My\ Documents.

Any path without a leading / is a relative path; that is, a path relative to the working directory. For instance, if our current directory was /home then brad would be a relative path back to where we were (/home/brad).

Actually, let's give that a try.

First, let's change to the absolute path /home:

$ cd /home
$ pwd
/home

then let's go back to /home/brad/ using the relative path brad:

$ cd brad
$ pwd
/home/brad

Your home directory will obviously be named something else. ...unless you're also a Brad.

cd stands for "change directory" and it's our primary means of getting around.

So now that we can move around between directories, let's create a new directory using mkdir (as in "make directory"):

$ mkdir rails

Notice that we are using the mkdir command and passing it the argument rails which will be treated as a string. Equivalently, we could have done $ mkdir "rails", but Bash already treats anything surrounded by spaces as a string.

Again, to use a literal space we would have to escape with a backslash like $ mkdir awful\ dir\ name or we could skip the backslash and just use quotes like $ mkdir "still an awful dir name".

Furthermore, passing a literal string argument like this works to alleviate any issues that would be caused by special characters that hold some meaning in Bash.

Now let's check that we actually created something by listing the contents of the current directory using ls (as in "list"):

$ ls
rails

This will print rails to the screen all by itself if the directory is otherwise empty.

If cd serves as our legs in Bash, then ls would certainly be our eyes.

The ls command will take arguments, but it also accepts flags (as do many other commands). Flags are used to set options for a command as it is run.

For example, if we wanted more detailed information about the contents of the directory, we could use the -l flag (which stands for "long listing") to accomplish this: $ ls -l. Some flags are preceded instead by two hyphens and spell out what they're used for, like this: $ ls --help.

Let's jump into our new directory with cd and list its contents with ls:

$ cd rails; ls

Here we see that we can execute several commands in one line if we separate them with a ;. This is because Bash, like JavaScript, ends lines with a semicolon.

Okay, so we're in our /home/brad/rails directory now. How would we go back up to /home/brad?

Well, we could certainly do $ cd /home/brad but that seems a bit excessive when all we really want is to simply "go back".

To look for a way out, let's add an extra flag to an ls that will display all the contents of the current directory:

$ ls -a
.  ..

You'll see that this prints . and .. which we didn't create ourselves. These two are special. . means "this directory" and .. is a reference to the parent directory.

Let's use it with cd to get back to /home/brad and then pwd to check where we are:

$ cd ..; pwd
/home/brad

Some systems will recognize ~ as your home directory, meaning that in my case, ~ will be equivalent to /home/brad. So if we specifically wanted to go to our home directory instead of just "back", we could have used $ cd ~.

Awesome. Now let's test the . theory and see if it really references the current directory.

First, let's do a regular old ls.

$ ls
rails

Makes sense.

Now, let's pass ls an argument for the path of the directory whose contents we want listed.

$ ls /home/brad
rails

Same output, good deal.

So passing it as an argument, let's see if . gives us the same thing for "the current directory".

$ ls .
rails

It sure does.

We can also use ./rails to mean "the rails directory in the current directory" and even to execute certain files.

File Basics

To create some files to play around with, we'll first need to understand standard output (stdout). So far when we've been using commands like pwd and ls that print to the terminal, what they're actually doing is printing to stdout. Bash will print this to the terminal by default, but we can also redirect it, into files for example.

First, let's take a look at a command that simply prints its arguments to stdout named echo.

$ echo foobar
foobar

So that simply prints foobar in the terminal, via stdout.

The beauty of doing things in the command line though is that we have several means of redirecting this stdout. One such redirection is to a file, using > and designating a filename.

If no file exists for that filename, one will be created and the stdout then added to it.

Let's give it a try:

$ echo "This will end up in a file." > test

You may also see > test written equivalently as >test. I kind of prefer the space for some reason.

We can even put it in front of the argument, as in $ echo >test "Text to be echoed.".

Also, notice that even though the file just contains plain text, the filename is simply test and not test.txt. Unix-like systems don't get confused by filenames without extensions, but feel free to add them if you like.

Did it work?

Well let's look. We can use cat to check the contents of our new file.

cat's manpage reads cat - concatenate files and print on the standard output.

$ cat test
This will end up in a file.

And there's our text. Perfect.

Oh, and be careful with >, because it will overwrite the entire file. Check it out:

$ echo "This will be the entirety of the new file text." > test; cat test
This will be the entirety of the new file text.

What if we want to add on to a file?

In that case, we would use >> instead because it appends to a file. As seen here:

$ echo "Restart file" > test
$ echo "Add to file" >> test
$ cat test
Restart file
Add to file

There's also another fairly common, yet strange technique used to create an empty file. It uses the touch command:

$ touch foobar

Run ls to see that a new file foobar has indeed been created. touch, much like cat, will create a file for you to perform its task if the file does not yet exist.

Why on earth would you want to create an empty file?

Can't think of an example, but I know I use it for this pretty frequently.

So what is the task we're asking touch to perform?

touch is used to update the timestamps for a given file, to the current time by default. To test this out, try the following:

$ ls -l; touch test; ls -l
-rw-r--r-- 1 brad brad 0 Sep 26 01:21 test
-rw-r--r-- 1 brad brad 0 Sep 26 01:22 test

After running these commands, notice that the timestamps for the file test were updated for the second ls.

The -rw-r--r-- out front has to do with file permissions. We won't have to mess with these, but it's possible to adjust them using chmod.

The first spot, here -, indicates that test is not a directory (i.e. a file). If it were instead a directory, it would be a d.

The rest are grouped in threes for user, group, and other. From left to right it is possible to have rwx which stands for read, write, and execution.

Thus, from the output about we can see that test is a file, readable and writable to the user that created it (brad), and readable by anyone else.

Another useful tool in Bash is the wildcard character *, for globbing files. To better demonstrate this, first we'll want some more files:

$ touch test1.txt test2.txt

Now, let's say we want to list only the files in the current directory whose names start with "test":

$ ls test*
test  test1.txt  test2.txt

You can read this in English as "list all the files [in the current directory] whose names begin with test", which is what we're looking for here.

If we wanted files whose names even just had test somewhere in them we could use *test* instead of test*.

We could also search for all the files in the current directory that ended in ".txt" with this:

$ ls *.txt
test1.txt  test2.txt

And what about deleting files?

For that, we use rm ("remove"). If we wanted to delete all the files ending in ".txt", it would look like this:

$ rm *.txt
$ ls test*
test

Be cautious with this command, as it will delete the files when you hit ENTER and it will not ask if you are sure that that's what you wanted to do.

If this bothers you, you're going to love the next section on Git which, among a multitude of other things, can help us to live without fear of blowing away files accidentally.

We can also move files with mv and copy them with cp:

$ cd rails   # change into rails for an empty directory

$ touch foo  # create a file to play with

$ ls
foo

$ mv foo bar # move `foo` file to `bar` (rename the file)

$ ls
bar

$ cp bar foo # copy `bar` file to `foo`

$ ls
bar  foo

Anything following a # on a line in Bash is a comment and will not be run.

Also, notice that mv can be used to rename files by way of moving them.

Variables

Bash also offers variables, somewhat similar to what we saw in JavaScript. We'll see this used in passing when we see some of the command line tools for Rails, but otherwise won't really need to use Bash variables.

In fact, Bash offers if's, for's, and other language functions that we won't need to understand in this book, but they are available.

These language features may not make sense in the terminal, but Bash can be saved to file as a shell script (commonly with the extension .sh) and run later.

We can use lowercase characters in Bash variable names, but the convention is definitely to use uppercase characters. Setting variable can be done simply with = like so:

$ FOO=bar

To access the value of a variable, we then have to use $, as seen in this example with echo:

$ echo $FOO
bar

Pipes

Another type of redirection available in Bash is the pipe. Pipes let you send the output from one command in as the input for another.

...and so on and so on, ad nauseam.

To make this interesting, let's combine some things from earlier with some new commands in an example.

While writing this book, I kept track of my total words written for the chapters as a basic benchmark for progress. To calculate this, I used the program wc (word count) like this:

$ wc -w chapters/*

where chapters is the name of the directory where all the individual chapter files are, chapters/* is a glob of all the files in chapters, and -w is a flag to just give the word count.

And not the byte and newline counts.

At time of me writing this, the output looks like:

1363   chapters/00
2562   chapters/01
14787  chapters/02
3909   chapters/03
1522   chapters/04
2275   chapters/05
2396   chapters/06
28814  total

Chapter 2 is a beast, isn't it? And I still haven't finished the JavaScript section yet...

Proofreading Brad-of-the-future here, I totally finished Chapter 2 now. And it's well over 20k words!

You can see that each line has the name of the file it represents at the end, except for the last line, which is a total.

The thing is, I really only care about that last line, so how could I just print that?

Actually, there's probably a flag for wc to do that, but for this example, we're going to pretend like I forgot about man and just started reinventing the wheel like a digital barbarian.

One tool that comes to mind to accomplish this is grep. The term "grep" has a rather interesting history, but for our purposes the manpage gives a fitting description: print lines matching a pattern.

There is much, much more complicated stuff that can be done with grep, but in this case, we could consider the "pattern" we are looking for to be the word "total". Put simply, we only want to print lines from the output of wc that contain the word "total".

First, let's use grep on a regular file, then we'll see how we can pipe wc to it to filter its output.

You'll remember that our test file contains the text:

Restart file
Add to file

To print only the lines in the file that contain the text "Add", we could use grep like this:

$ grep Add file
Add to file

The first argument we pass to grep is the pattern to try to match and the second is the file to look in. And it works as advertised.

Derail: equivalently, we could use the <, the standard input operator, to pass the file to grep via stdin.

$ grep Add 

But the text we want to match for wc is being sent to stdout, not a file, so how to we send it to grep instead of just outputting it to the terminal?

Well, we can pipe it into stdin for grep with | like this:

$ wc chapters/* | grep total

This line might read in English something like: "calculate the word count for all of the files in the chapters directory then search those for lines that contain the pattern total and send those to stdout".

In short, the | above passes the output from wc into grep.

sudo

Sometimes, you'll want to accomplish something in the command line and only to find yourself be stopped and effectively asked for your credentials.

A classic example of this is the installing of new programs with apt-get in Ubuntu Linux derivatives, like Linux Mint.

The first argument you pass apt-get is the action you want it to perform, which in following case is install, and the rest of the arguments are interpreted as the names of the programs you want that action performed on.

So let's pretend I don't have vim, my dearest text editor, installed on my system

...and that I occupy some kind of hellish, parallel dimension where I am required to use a mouse to do everything on my computer.

An initial attempt to install vim might look like this:

$ apt-get install vim

E: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied)
E: Unable to lock the administration directory (/var/lib/dpkg/), are you root?

There's a "Permission denied" in there along with the interrogative: "are you root?"

Not to be confused with the "root directory", "root" here refers instead to the root user (or super user) which is an account within a Unix-like system used for administrative purposes. This root user is capable of doing things that lesser users in the system cannot, such as installing new programs. If you own the machine you're on and are running a Unix-like system, chances are your user account is a super user account.

So why am I being asked if I am root?

Because Bash doesn't grant super user permissions to a terminal by default. Ostensibly, this is to prevent you from doing something accidentally or a malicious passerby from doing something intentionally to damage your system.

It can also just generally get in your way if you just want to install a new program.

"It's me, yes, go, install." - Brad Chase

If you are sure that what you typed is what you wanted to do, you can easily prove yourself authorized to do so by prefixing the same command with sudo and then entering your password.

sudo stands for "super user do".

Let's try installing vim again, once more, with feeling. ...kidding, this time with sudo:

$ sudo apt-get install vim
[sudo] password for brad:

There, now all is well with the world.

Actually, if you've decided to work through the rest of the book using some variety of Debian Linux (e.g. Ubuntu, Linux Mint, Debian), there some dependencies you should install with apt-get to avoid problems later on when we're playing with Rails. Just run the following in your terminal:

$ sudo apt-get install curl sqlite3 libsqlite3-dev nodejs g++ libpq-dev

If you copy and paste the Bash above, be sure to remove the $ from the front of the line.

You'll also want to install Chrome within Linux. You can download an installer here. If you're using a Debian distribution, you can just click the completed download (a .deb file) and then Install Package.

more and less, head and tail

If you want to view the contents of a text file in the terminal, often times cat will be a poor choice since it will output the entirety of the file to the terminal. This functionality is great for writing to file and piping, not so much for reading.

One tool that would help here is more.

Initially, more will display only as much of the top of the document as can be displayed in the terminal. To see more of the document, you can press SPACE to move down. Pressing q will exit and get return back to a Bash prompt.

One quirk of more is that you can only move down the document, not up. Luckily there is also a program named less, which works almost identically, except that you can use UP, DOWN, PgUp, and PgDn to move either direction in the document.

Still other times, you'll know that what you're looking for is at the very top of a text file and really just want to see that.

In this case, we'd be well served to use the head command, which will print the first ten lines of a file.

What if wee want more? Say, twenty lines?

Then we'd specify that like so: $ head -20 foo.txt

As you might expect, there is an opposite to this named tail that will print the last ten lines of a text file (or however many you tell it to, same as you would with head).

These programs are useful all on their own, but they are very handy to pipe to as well.

When I have some piece of Ruby throwing a tremendously long error trace, I'll pipe it to less so I can easily scroll through it with the arrow keys, like this: $ rake --trace db:setup | less.

Multiline Bash

Hitting ENTER after a \ will not run the current line, but allow that particular Bash statement to continue onto the next of line of the terminal.

For example, the following are equivalent:

$ touch foo bar
$ touch \
foo \
bar

Ctrl-c and Ctrl-d

Some programs will run and run until you tell them to stop.

Our Rails server will prove to be an example of this later.

Ctrl-c (Ctrl and c) will send an interrupt signal that tells a program to stop what it's doing and close.

Ctrl-c in this context is often represented as ^C.

Ctrl-d represents EOF (End Of File) and will cause certain programs to close. In fact, this works as a quick way to close out of a Bash terminal.

Things like EOF and signals are something worth understanding, but well out of scope for us in this book. All we really need to know for now is that ^C closes things.

Tab completion

You might end up with some pretty long file names and program names that can be a pain to type out. To help keep this from driving you crazy, try tab completion.

Let's say we have a crazy long file name:

$ touch crazylongfilename

If we wanted to cat the contents of this (empty) file, we could type cat c then hit TAB and have the rest of the filename filled in for us.

Now let's see what happens if the name isn't as unique for the directory:

$ touch crazy

Try to tab complete with cat c like we did before. You'll see that the terminal finishes crazy for you, but what about crazylongfilename?

Hit TAB twice and you'll see both filenames listed.

Note that if there is ambiguity in the completion, no space will be left after the text.

For example, $ cat crazy[] implies that the completion is ambiguous and not complete, whereas $ cat crazylongfilename [] implies that there was only one possible completion and it was made (where [] is the cursor).

This difference is subtle, but easy to pick up on if you're looking for it.

Emacs Bindings

By default, Bash will respond to Emacs key bindings. Here are a few that I find most useful:

Command Result
Ctrl-p previously run line
Ctrl-n next line (if used after a Ctrl-p)
Alt-f/Alt-b move cursor forward/back through a word
Ctrl-f/Ctrl-b move cursor forward/back one character
Ctrl-k kill (cut) from the cursor until the end of the line
Ctrl-y yank (paste) text that was last "killed"
Alt-d delete word under/in front of cursor (this text can also be yanked)
Ctrl-d delete character under cursor

Clearing the Terminal

After typing in a terminal for a while, you'll end up with your prompt at the bottom of the screen. If this gets on your nerves, as it does mine, just hit Ctrl-l to clear the terminal and put you back up at the top.

Bash History and Ctrl-r

As you might have guessed after playing around with Ctrl-p (previously run line), Bash will keep track of what you have previously executed.

This is made even more useful with Ctrl-r which serves as a sort of autocomplete on your Bash history.

For example, remember my $ rake --trace db:setup | less from earlier?

Well, it's a pain to type repeatedly. And it might not be something I ran recently, so instead of Ctrl-ping back through all of my commands, I might simply remember that I ran this recently and that it contains the text "setup". To run it again, I could simply hit Ctrl-r, type setup, make sure that the line it brings up is in fact the one I want to run, and then hit ENTER.

Be sure to check that you've got the line you want. ...I've run things I didn't intend to using this method on more than one occasion.

Wrap-up

So that's a Bash intro and then some!

Again, don't worry if you didn't catch every last thing above because we'll really only need to understand the absolute basics of the command line to use Rails later.

There's always more to learn here though, so make a point of circling back to this if you feel so moved.

Some other interesting topics include alias/.bash_aliases, .bashrc, $PATH, and, ^Z/fg.

6.4 | Text Editors

This is one rare point in the book where I am going to cop out and not give you even a brief tutorial on a topic.

The reason for this is that I believe choosing a text editor to be an entirely subjective matter of personal preference, something that I wouldn't dare try to choose for you.

Having said that, I acknowledge that you deserve to be provided with options. And that I can do.

As noted in the previous section, I'm a fanatic user of Vim. Vim takes a different approach to text editing (modal editing) and has a purportedly steep learning curve because of this. Unfortunately, I can't honestly speak to the difficulty of learning Vim because I mostly remapped my editing habits from Emacs when I switched to Vim.

I migrated from Emacs to Vim because Emacs was making my hands hurt on an almost daily basis. I blamed this on the the fact that it requires a lot of use of modifier keys like Ctrl and Alt, but I don't know if this was true.

I still have this problem with Vim from time to time on days of particularly heavy typing, but otherwise it (and a different keyboard) has seemed to do the trick. I was also pleasantly surprised to find that my thinking largely aligns with the way things are done in Vim, so I'm glad I made the switch.

Having said all that, Vim and Emacs are definitely worth taking a look later if you're interested. Additionally, they're both free, so that's great.

They are, however, not recommended for use in this tutorial. They are topics unto themselves and there is plenty of other things to pay attention to first.

So for the sake of maintaining forward motion, let's see some text editors that are super intuitive and user-friendly.

Text Editor Suggestions

If you are working on a Mac, an immensely popular text editor for OS X is TextMate.

This one is paid.

If you are working in some variety of Debian Linux (high five!), an easy and free choice is something like gedit or mate-text-editor.

Yet another option is the cross-platform Sublime Text. I've never personally tried it, but it is used and loved by a colleague of mine.

This one has a free evaluation but is eventually paid.

Another free one I've used on and off over the years for basic editing is jEdit.

These last two options work on Windows.

So, it doesn't matter what you choose, except that it does.

Speaking in the long term, you don't want to stick with a text editor you don't like just the same as you wouldn't want to buy a pair of shoes and continue to wear them after they don't fit.

But right this minute, anything that can open, edit, and save text files will do.

Don't I need an IDE (Integrated Development Environment)?

Long story short: no.

Building Rails applications requires the use of a command line and the creation and editing of text files, nothing more.

Also, much of the time spent programming is spent editing code rather than writing code. The IDE's I have had the misfortune of using have largely ignored this, whereas the text editors I've used shine here.

Furthermore, I think that the text editor is the most organic relationship that a programmer can possibly have with their code. It's abstract enough that we need not be bothered with the writing bytes to spinning, magnetic disks, yet basic enough that we are fully responsible for the syntactic correctness of our typing as well as its semantic relationship to the code around it.

I believe the text editor, in its simplicity, grants to a programmer the awareness and accountability that one should have over their own work.

...but that's really just my opinion. Please feel free to use an IDE to follow along if you've found one you like.

6.3 | Git

Remember our talk about Version Control Systems?

Well, the unquestionable favorite VCS for Rails programmers is Git. And for good reason; it does its job very well.

Git was actually started by the creator of Linux, Linux Torvalds, and is used to this day in the continued development and maintenance of the Linux kernel.

So it also has that going for it.

We'll be making basic use of Git later on in our Rails tutorial, and will only need to understand a handful of steps to accomplish what we need it for. The steps are as follows:

  1. create a new Git repository for a directory
  2. add files in that directory that we want the repo to track
  3. commit our changes to those files
  4. add a remote repository
  5. push our changes to that remote repository

Git is a yet another topic best illustrated by example, so let's jump right in.

Oh, and make sure you have Git installed before moving on.

In the terminal try running:

$ git

If this complains No command 'git' found, then you don't have Git installed.

On Debian Linux variants you can install it simply with:

$ sudo apt-get install git

Otherwise, you can get it here.

The Local Repo

First, we need a directory to hold the files we want to track. Let's create and move into a new directory:

$ mkdir project; cd project

Then we'll make some files:

$ touch file1 file2

Now it's Git's turn.

To start, we need to tell Git that we would like to create a repository for the current directory:

$ git init
Initialized empty Git repository in /home/brad/project/.git/

This initializes a Git repo for the current directory, but note that it is an empty one.

Why didn't it just put the files into the new repo?

Because sometimes there are files that we don't want Git to track, such as files that contain passwords, secret keys, sensitive logs, etc.

We can even tell Git to ignore certain files using a .gitignore file.

What did Git actually do to create this new repo?

All it really did was create a new directory: .git.

$ ls
file1  file2

I don't see it. Where is this .git?

Try again with the -a flag.

$ ls -a
.  ..  file1  file2  .git

.git is a hidden directory, because Bash will hide any file or directory with a . at the very beginning of its name.

We never want to directly mess with anything in this directory, but it is where Git is keeping track of things.

So the repo is there but empty. Let's add our files to it.

We could do this by selecting only the files we want to add:

$ git add file1 file2

or by adding everything in the directory:

$ git add .

Adding files like this tells Git that we want it to track changes to those files, but we have not yet committed the changes we've made. To demonstrate that this is the case, we can use git status to see the status of our changes:

$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached ..." to unstage)
#
# new file:   file1
# new file:   file2
#

I prefer the abbreviated formatting of git status -s myself though:

$ git status -s
A  file1
A  file2

As you can see here, Git is watching the files and sees that there are Changes to be committed, namely that there are two new files.

In Git, a commit is something like a checkpoint that we create. We can move on, making changes and more commits for those changes, but anywhere along the way we can go back to any of the previous commits; that is, we can ask Git to change the contents of the tracked directory back to the state it was in when that commit was made.

Let's make our initial commit now:

$ git commit -m 'initial commit'
[master (root-commit) 46d917e] initial commit
 0 files changed
 create mode 100644 file1
 create mode 100644 file2

We have to include a message with the commit, and so we might as well do this right along with our git commit by using the -m flag followed by our commit message.

As noted earlier, we'll only be covering Git knowledge that is needed for later, so we won't be looking at how to go back to a previous commit.

Even so, it makes sense to see how things progress locally from here while working with Git, so let's make a change to a file and commit the changes.

In the real world, we'd almost certainly have made some kind of change from our text editor, but since we really only need a file to be different for the sake of example, let's just echo something into file1:

$ echo >file1 foo

The file has changed, so let's see if Git noticed:

$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
# modified:   file1
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git status -s
 M file1

The output above lists our options, but let's take a look at what we might and might not want.

If we want all of the changes we've made to go in a new commit, the easiest way to do this would be to add the -a flag on another git commit, like this:

$ git commit -am "updated file1"
[master e65a3bc] updated file1
 1 file changed, 1 insertion(+)

This flag automatically stages all changes made to tracked files for the commit.

We could also accomplish the exact same thing with another add:

$ git add .
$ git commit -m "updated file1"
[master e65a3bc] updated file1
 1 file changed, 1 insertion(+)

Sometimes, we won't want all of the changes to go though. In this case we would just git add the files we want staged for the commit:

$ git add file1
$ git commit -m "updated file1"
[master e65a3bc] updated file1
 1 file changed, 1 insertion(+)

These are all equivalent since we've only changed one file, but do note that we don't have to stage all changes for the next commit.

The Remote Repo and GitHub

Git does a great job versioning changes locally, but it also makes it easy to store your code remotely, share your code with the world, and collaborate with others. There are a number of ways to do this, but one of the most enjoyable ways is to use GitHub (pronounced "get-hub").

GitHub is for Git what Facebook is for faces.

GitHub offers free (public) remote Git repositories along with a bunch of other helpful tools. Feel free to look around at all they have to offer, but we'll be focusing on the fact that they'll grant us a free remote repo.

First, you'll need to sign up.

Then, you'll need to create a new repository.

After you create the repo, the folks at GitHub give you some incredibly timely information, telling you how to Push an existing repository from the command line.

Follow what you see displayed there, but it looked something like this for me:

$ git remote add origin git@github.com:bchase/reponame.git
$ git push -u origin master
Counting objects: 9, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (9/9), 683 bytes, done.
Total 9 (delta 0), reused 0 (delta 0)
To git@github.com:bchase/reponame.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

We don't really need to understand all of that (I don't), but these two lines pretty straightforward:

  1. add a remote repo (git@github.com:bchase/reponame.git) named origin
  2. perform an initial push to the remote repo origin of our changes to the master branch

We haven't covered branches, but suffice it to say that our changes earlier ended up in the master branch by default.

After this if we add and commit changes, we can push them up to this remote repo much more easily with just:

$ git push

More Git

So that concludes the amount of Git knowledge we will need later and covers most of the absolute basics.

If you're interested in learning more about Git, this is a terrific resource put together, as it happens, by the good people at GitHub.

6.5 | Stack Overflow and Google

So far it's been all sunshine and rainbows talking about these different languages and tools, but the truth is: sometimes things are confusing and, perhaps more often, they break.

If you run into an error or problem that you can't figure out, try googling it.

"No, really!?"

Chances are, if your query has to do with programming terms, you'll find a Stack Overflow question in the top results.

The site gets its name from the largely unhelpful error message "stack overflow". We won't be seeing in Ruby or JavaScript, but it's one that programmers of C will be familiar with.

Stack Overflow is a site that allows users to ask questions and then lets their peers answer and vote for the best answer among those given. This system works better than anything else I've seen and I cannot recommend it highly enough.

And do be sure when using Stack Overflow to first search for a question similar to yours before asking your own. People do not take kindly to seeing duplicate questions and you will likely hear about it.

Wrap-up

Well, that concludes the non-Ruby tools we'll be needing to build our Rails app.

Why not cover the Ruby tools here too?

Because they're in the very next chapter!