GitHub

Registering

Go to https://github.com and register for an account. Make sure to choose a username that's professional and recognizable, since this will be your username even if you switch around jobs.

For purposes of this book, you can go with the free plan. This means all your repositories will be public. If you want to work in privacy, you can sign up for a paid plan and create a private repository as well. The steps and processes will be the same for public or private repositories.

Creating a Repo

Now that you have set up your GitHub account, it is time to learn how to use it. Whenever you are logged in to the GitHub website, you will see a plus icon in the upper right corner. When you click on that, you will see a menu that includes a New Repository link. Click on that link.

Choosing a repository name comes next. There are two general rules to follow:

  1. The repository name has to be unique to your account. That means that someone else can have a repository on GitHub named my-awesome-repo, and you can have one as well. You cannot however have two repos by the same name under your account.

  2. Choose a descriptive name based on your project. As far as naming conventions, some people separate words with hyphens and some use underscores. This is personal preference, and you may separate your words with any character you want except a space or tab.

In this guide, we are going to create a remote repository on GitHub.com where we can push the local repository that we created in the last chapter.

As you will see in this example, your local and remote repos do not have to have the same name. We will use my-first-repository as the name of our remote repository on GitHub.

You will notice that GitHub has added a green checkmark in the text field where we typed our repo name. That tells us that our repo name has no problems and can be used. If you have spaces in your repo name, GitHub will automatically replace them with hyphens.

The next thing we need to look at is the Initialize this repository with a README checkbox. This is a very important step in creating your remote repo.

  • If you check the box, it will automatically create and commit a README file in your remote repo. Before you can push any commits to the newly created remote repo, you will need to pull the code from your remote repo into your local repo. You will learn more about this later in the chapter.

  • If, however, you do not check the box, you will be given instructions for creating and linking a local repo with the newly created remote repo.

You will usually create your local repo first, so you will rarely check this box. Whether you initialize the GitHub repository with a README file or not, you need to understand conceptually the consequences.

For our example, do not initialize a README file, then click the Create repository button to create a remote repo on GitHub.com.

Connecting to GitHub Repo

Now you should see instructions on how to connect your local repo to the remote one you just created on GitHub. Looking at just the first option, the set of git commands should look very familiar, we have already done the first four commands. We only need to perform the last two commands in order to link our local repository with the remote one.

In the command line, execute the following command. You will need to insert your GitHub username:

git_basics/ $ git remote add origin https://github.com/<GitHub username>/my-first-repository.git

What did we just do?

Before we move on, let's take a look at the command we just executed.

git remote add origin url_to_remote_git_repo

The primary git command we issued is git remote. You use this command to work with remote repositories. If you just issued git remote by itself, git will list all the remote repositories that your local repository knows about. If you pass additional sub-commands to the git remote command, you can further add, remove, and modify the remote repos that your local repo is linked to. Knowing that, you can guess that we're using the add sub-command to add a remote repository to the local repository.

That explains the git remote add parts of the command, but what about origin and url_to_remote_git_repo? Both of those things refer to the remote repository. The latter, the url_to_remote_git_repo, is pretty self explanatory: it's the URL to the remote git repository, which should end with a .git extension.

The origin is what we call an alias. The alias is the name that you will use locally to interact with this remote repo. You can have as many remote repos linked to your local repo as you want, but they must all have unique aliases. The instructions generated by GitHub always use origin as the alias. Any interaction that you have between your local repo and a remote repo will need to include this alias. You can name it whatever you like, but it must follow git naming conventions (no spaces, for example), but most developers use origin to mean the central repository where we're keeping the master copy of our codebase. More often than not, that implies a remote repo hosted on Github.com.

If you open ~/git_basics/.git/config in a text editor, you will see how git stores the information we just added. Recall that the .git/config file is where all the configuration settings for your local repository are held, and overrides any global settings. Note that your .git/config file may not necessarily look like the one below, which already contains an example remote repository called "origin".

[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://github.com/joesmith2444/my-first-repository.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master

The entries under [remote "origin"] are settings specific to that remote. The settings under [branch "master"] set up the tracking. For example, remote = origin tells your local repo to use the origin remote as the default remote for the local master branch to push and pull against.

git push

You can cause a branch on your local repo (remember, every repo starts with a master branch by default) to track a branch on your remote repo. When you use a command that interacts with a remote repo, and do not specify which branch to interact with, the tracked branch will be used.

Now that we have laid all of the groundwork necessary to push our code to GitHub, let's do that!

In the command line, type the following:

git_basics/ $ git push -u origin master

Notice we used the -u flag. That flag sets the upstream repo, which causes our local master branch to track the master branch on the remote repo which is aliased as origin. We can now use just the git push command and it will know where to push it, because we set our upstream branch.

If you have never pushed to GitHub before, you will now be seeing a login prompt.

git_basics/ $ git push -u origin master
Username for 'https://github.com':

After you successfully login, you will see a message saying that your objects have been written. You will also see a message saying that you have set up your local master branch to track the remote master branch, thanks to the -u flag.

git_basics/ $ git push -u origin master
Username for 'https://github.com': joesmith2444
Password for 'https://joesmith2444@example.com':
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (5/5), 368 bytes | 0 bytes/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://github.com/joesmith2444/my-first-repository.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

Once again, here's a breakdown of the command.

git pull

Sometimes the code in your remote repository will contain commits you do not have in your local repository. In those situations, you will need to pull the commits from the remote repository into your local repository. There are four basic scenarios when you will run into this:

  1. You work on a team, and multiple people pushed code to the remote repository.
  2. You pushed to the remote repository from a different machine.
  3. Your project is public on GitHub and somebody contributed to it.
  4. You made a change to a file directly on GitHub.com.
Github.com allows you to modify files directly on the website, but behind the scenes, it's packaging that edit into a commit on the remote repository directly. This is not a good habit to get into and is only recommended for very special situations.

The first two scenarios are by far the most likely scenarios, while scenario #3 and #4 are pretty rare.

Although it is not recommended to make changes using the GitHub editor, we will use this method to simulate and work through this workflow.

The first thing we need to do is view the remote repo. To do that, visit https://github.com. On the bottom right section of the screen, you will see a list of the repos that you currently have stored on GitHub.com.

Click on the my-first-repository repo, and you will see the files that we pushed earlier in this chapter.

Notice that the contents of the README.md file are shown below the file list. This allows you to easily create documentation for your project, which GitHub will automatically display.

Now we need to make a change to a file. Click on README.md and then click on the pencil icon which is shown above the file's contents.

Modify the contents of the file using the editor and then scroll down. You will see two input fields. These fields allow you to create commit messages for the remote repo just like the git commit -m command did for our local repo. Type in a commit message and then click the Commit changes button.

While GitHub gives us a nice UI for editing files, committing a change in their UI has the same effect on the remote repository that modifying a file locally and then using git add and git commit does on our local repo. Once again, we're editing files directly on GitHub for purposes of this book only, as this is something you rarely want to do in real projects.

Next, we switch back to our terminal and work with our local repository. We need to check our remote repo for changes. The first thing we need to do is fetch the repo, which will download the commit data for each branch that the remote repo contains. Because we are currently working with our local master branch, the git fetch command will fetch the commits from the remote repo containing the tracked remote branch.

In the command line, type:

git_basics/ $ git fetch

You should see some messages related to git downloading the remote changes. If you do not see any messages, your remote repo has no changes.

git_basics/ $ git fetch
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/joesmith2444/my-first-repository
   5afaf12..9389be5  master     -> origin/master

The next thing we need to do is look at what has changed. We do that using the diff command.

In the command line, type:

git_basics/ $ git diff master origin/master

This command tells git to compare the local master branch to the master branch on the remote repo which is aliased origin. Put another way, we're comparing the commits in our local repository with the commits in the remote repository.

git_basics/ $ git diff master origin/master
diff --git a/README.md b/README.md
index 0647d92..56289ec 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,3 @@
 # README #
+
+This is my first GitHub Repository!

The output from the git diff command shows some changes in our README.md file. After you verify that you want to pull the changes into your local repo, type:

git_basics/ $ git pull

Since the local master branch has been configured to track the origin/master branch, you do not have to specify what branch to pull from.

Note that you can also type git pull origin master if you want to specify exactly from which remote repository (using the alias) and which remote branch you want to pull. The commits will be pulled and merged into the current branch you're on in your local repository.
git_basics/ $ git pull
Updating 5afaf12..9389be5
Fast-forward
 README.md | 2 ++
 1 file changed, 2 insertions(+)

Now if we open our local README.md file in a text editor, we will see the changes that we made on our remote repo using GitHub's editor.

# README #

This is my first GitHub Repository!

Your local repo is now identical to the remote repo, and you can start working on files locally again. You can make changes to the readme file, commit the changes and push them to github again.

git clone

What is git clone

So far, we have been talking about connecting an existing remote repository with an existing local repository. But what if we don't have an existing local repository, and just want to pull down all the contents of a remote repository? This is where git clone comes in. It makes an exact clone of an existing remote repository, and copies it onto your local machine. The cloned local repository will include all the files, commit history, branches, and everything else associated to that git repository.

The git clone command has several options, but most of the time you will only need its basic usage. Here is what it looks like:

$ git clone <remote repository url> <local directory name>

Here's what it looks like in action:

$ git clone https://github.com/bob/example.git my_amazing_project
Cloning into 'my_amazing_project'...
remote: Counting objects: 218, done.
remote: Total 218 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (218/218), 180.21 KiB | 0 bytes/s, done.
Resolving deltas: 100% (54/54), done.
Checking connectivity... done.
$ ls
my_amazing_project/

In the one command above, several things happened:

  1. A new local git repository was created in a directory called my_amazing_project.
  2. All contents in the remote repository github.com/bob/example.git were downloaded into the newly created local repository.
  3. A remote was added to the local repository's configuration, pointing to the remote repository URL, aliased as origin. This is the same thing as issuing git remote add origin https://github.com/bob/example.git from within the local repository directory.

This means that you can now git push or git pull from the newly created local repository to/from the remote repository.

When to use 'git clone'

git clone is used mainly when you need to work with a remote repository, and do not yet have a local repository created. For example, if you just joined a new project, the first thing you'd likely do is git clone the project in order to start working on it locally.

Another common use case is if you want to pull down an open source project. For example, if you wanted to check out the source code for the popular open source web development framework, Ruby on Rails, you can issue this command:

$ git clone https://github.com/rails/rails.git

Notice that we didn't specify a second parameter, the directory name. If you don't specify a directory name, like we did here, then the default behavior is that a new directory will be created with the same name as the cloned repo. In this case, the directory will be called rails.

After running this command, you should have a directory called rails, which is a local git repository containing all the code and contents of the official Rails repository. Further, this local repo will have a remote called origin that points to the official Rails repository. Unfortunately, this doesn't imply you can now push commits to the official Rails codebase. Though you can set it as a remote in your local repo, you still need permission to push to the actual remote repository, which you don't have. You can, however, poke around and make changes to your local repo.

A note on git init and git remote

The three commands, git init, git clone and git remote add origin <remote repo> may seem very similar at first, so let's take a look at when you should use them.

Command When To Use
git init Create a new local repository.
git remote add origin <remote url> Add an existing remote repo as a remote of existing local repo.
git clone <remote url> Pull down contents of existing remote repo into a new local repo, and add a remote to the local repo pointing to remote repo.

Summary

Let's rehash what just happened in this chapter:

  • First, we created repository on Github.com, and chose not to initialize it with any files, leaving it a blank slate.
  • Next, we made our local repo aware of our newly created remote repo with git remote add origin <url>.
  • Then, we pushed some commits from our local repo to our remote Github.com repo using git push.
  • We then made a modification on Github.com directly, simulating a coworker pushing commits to our remote Github.com repo.
  • Finally, we pull those commits down to our local repository using git pull, syncing up our local repo with our remote repo.
  • We also learned what git clone is, and how you would use it to work on an existing git repository.

As you can see from the above steps, working with git requires very detailed orchestration to make sure all repositories -- your local, your teammates', your other machines, and finally the central repo -- are all synchronized.

You may already see that there are many potential problems lurking just around the corner, but don't worry about that yet. You'll learn how to deal with conflicts and work with advanced git workflows over time. For now, just focus on working with git and Github on a one-person project.