Jump Start PHP Environment (2015)

Chapter 5 Versioning Systems

In this chapter, we’ll cover versioning systems. In particular, we’ll be talking about Git and GitHub, as those are by far the most popular two tools in use as far as versioning and code sharing are concerned.

If you’re an active user of Git and/or GitHub and are familiar with both the importance and use of versioning systems in general, feel free to skip this chapter. Otherwise, I strongly advise you to read it as it’s easy to absorb, and absolutely essential in your future work.

If you didn’t read the previous chapter―though it is recommended that you do, so please don’t skip it―install the following tools before proceeding:

·        Vagrant, from https://www.vagrantup.com/

·        VirtualBox, from https://www.virtualbox.org/

·        Git, from http://git-scm.com/downloads

Versioning Basics

In software development, the term versioning or, more accurately, version control refers specifically to the ability to:

·        track the changes of files over time and label those changes with helpful change messages

·        revert those files to any of their previous versions (an infinite number of “undo” operations)

·        share those changes with others in a way that’s visible and immediately clear to every team member

·        enable more than one person to edit the same file at the same time, and being able to sync those changes

·        have a central location for all source code from which all other team members (and sometimes random enthusiasts) can grab your code and work on it

Conceptually, version control in software development is similar to applying version control in other programs, such as tracking people’s contributions in Google Docs documents, using the undo operation in Photoshop, and so on.

While version control is important in any kind of development, it is especially precious in teamwork. In the past, teams working on the same codebase would share code snippets over email (so-called “patchbombs”), which required a lot of manual synchronization and administrative overhead in accepting changes and updates.

With tools such as Git and GitHub, this changed.

Git and GitHub

Git is an application for version control, or what is generally called a version control system (VCS). It handles all the points listed under what constitutes versioning, and more. GitHub is a variety of social network for coding, powered by Git.

Git

Git is a command-line application that’s generally without a GUI. It’s used strictly from the terminal or from within Git Bash, a tool that becomes automatically available on Windows when you install Git.

Helper tools with graphical user interfaces do exist—partially removing the need for manually punching in commands―but in the vast majority of use cases we require a version of the terminal. From now on in this book, whenever there’s an instruction like “execute the command git push”, it’s assumed we are using the terminal or Git Bash to enter the command.

Through Git, we can easily download repositories such as Homestead Improved from the last chapter without having to use the Download button. Instead, we use a command called clone, like so:

git clone https://github.com/swader/homestead_improved

Notice that we used GitHub in the URL. We’ll explain that in the GitHub section shortly.

How does it work?

In a nutshell, Git uses a hidden .git folder inside your project’s folder to track all the changes and previous versions of the files. Whenever you make a new commit (that’s a specifically flagged point in time when something changed in a given file or set of files), Git will store a copy of the old version and new version in the .git folder so that we can later refer to them if needed. That way, if we need to undo a change, we just tell Git to reset to a previous point in time with, for example, git reset 47298720dbf, where the code at the end is the name or flag of the commit. We'll link to a more comprehensive Git guide at the end of this chapter. Reading it will make you a Git master within a day or two, tops.

Alternatives

Git is far from being the only VCS. There are others such as Mercurial, SVN, CVS, and many, many more, but Git is the most widely used one. It is the VCS to use if you want to contribute to open-source projects today, as the vast majority of them use it. It is also what mostly powers GitHub, so you’ll be part of the pack from the get-go.

GitHub

When using Git, you have the ability to clone repositories from any remote endpoint, provided the code is there. For example, if I have some source code and I put it on a live server (one accessible to the Internet), then configure this server to accept remote Git calls, anyone who has Git installed can clone this source code by running:

git clone https://myserver/myrepo.git

However, not everyone has the time, money, know-how, or patience to set up a server just to host code for others to access. This is where GitHub comes in.

GitHub is a website on which people can host their repositories for free, but there’s a catch―all repositories are immediately accessible to everyone. They’re public. Private repositories are supported, but cost money. This is ideal when developing projects for clients that should be kept private—especially from the client’s competition. For free private repos, there are alternative websites such as GitLab and Bitbucket, but those aren’t nearly as popular as GitHub, hence why we’ll use GitHub in this book. In your own adventures, feel free to use any service you like.

But why would one even want to use a service such as GitHub for their code? Apart from the obvious answer of being able to share your code with others easily and for free, services such as GitHub can be lifesavers when your machine dies and you lose all its content. If you regularlypushed (a Git term for “upload”) to the repository’s remote origin—meaning its GitHub URL—you’re safe from disaster: your entire file history is preserved and you can continue where you left off on another computer. Furthermore, many other companion services exist that integrate automatically with GitHub. One example would be Travis CI, a service that runs checks on the code to make sure it all still works whenever changes to a GitHub repository are detected. If something is wrong, Travis notifies you via email and updates a little badge on the repo’s main web page warning users about the latest version.

Now that we’ve covered the theory of Git and GitHub, how about seeing it in action?

Git in Action

Let’s learn using a practical example. I recommend (and will assume) you put your projects into your home folder, the path for which the shortcut is ~. If you opt to use a different one, please adapt the code that follows.

Preparing the Environment

As we’ve done in previous chapters, we first need to configure a VM in which we’ll do our experiments. We could do all this on our host machine, but remember that the end goal is to keep the host machine as clean as possible, all while using a fully discardable and experiment-friendly environment for all the playing around we can think of. Here’s what to do:

1.    Open Git Bash on Windows or Terminal on OS X/Linux.

2.    Go into your home folder by executing the command cd ~.

3.    Clone the homestead_improved repository into a folder named hi_phpenv with the command: git clone https://github.com/swader/homestead_improved hi_phpenv. You’ve just learned about git clone!

4.    Enter the newly made folder with cd hi_phpenv.

5.    Execute bin/folderfix.sh

6.    Open Homestead.yaml and change the sites block so that it looks like this:

7.  sites:

8.       - map: phpenv.app

9.         to: /home/vagrant/Code/phpenv

10.Add a new hosts entry:

11.192.168.10.10 phpenv.app

If you’re unfamiliar with this step, please see the section Hosts and Virtual Hosts in Chapter 3.

12.Finally, run vagrant up in the hi_phpenv folder. This will boot up the VM, and you should be able to access http://phpenv.app/ in your browser and see the message No input file specified.

This is a procedure you’ll have to repeat with every new project. After all, every project deserves a fresh environment, oblivious to the mistakes and changes of the last one. But fear not, in due time the procedure will become muscle memory, and you’ll get from start to finish in a minute flat. To save you from having to remember the procedure or continuously refer to this chapter, you can find a helpful guide at http://www.sitepoint.com/quick-tip-get-homestead-vagrant-vm-running/.

Creating a “Hello World” page

With our environment ready, the path to learning about Git and GitHub is clear:

1.    In the hi_phpenv folder, create a new folder named phpenv. You can do this either through your host machine’s file explorer or via the Terminal / Git Bash with mkdir phpenv. Change into the directory with cd phpenv.

2.    Make a new file called index.php and give it the contents:

3.  <?php echo "Hello World";

4.    Try visiting http://phpenv.app/ in the browser to make sure it works.

We now have our “Hello World” page. We’re proud of our code and want to share it with the world. Let’s use Git and GitHub to do that.

Git

Before we put anything on GitHub, we’ll tell Git to turn our source code into a repository.

Repo Initialization

·        While in the phpenv folder (that’s hi_phpenv/phpenv), run git init. This is an initialization command that will create an empty .git folder. It is hidden by default, but you can see it if you execute ls -a.

·        When developing with the power of a version control system such as Git, you might want to ensure certain files are never added to a repository. For example, if you had a database password in a configuration file, it would be unwise to let this file be accessible online, as it would leak your password to everyone looking at your repo. For this purpose, ignore files exist. These are special files for Git with the filename being .gitignore and contents that list files to ignore line-by-line, like so:

·        mypassword.php

·        sensitive-folder/*

This piece of code will make sure the file mypassword.php and everything inside the folder sensitive-folder is never added to a repository, nor ends up in anyone else’s clone of your code.

If you’re using an IDE to write this code, and I hope you are (see Chapter 2), you’ll find that it likes to put its own helper files into the project’s root. For example, PhpStorm loves to make an .idea folder and place some configuration values inside that pertain to the current project. I definitely want to avoid having anyone who clones my code be forced to also copy my IDE configuration, so let’s use an ignore file to prevent this.

Create a .gitignore file in the folder with the command touch .gitignore, or from within your IDE. Then edit it and give it the contents of the file at https://gist.github.com/Swader/7844111 , which is an ignore file that takes into account all the various IDE and OS configurations you can run into when working on PHP projects.

Another way of making sure you never have to add this to a project’s .gitignore file again is by adding it to your global .gitignore. To see how, check out this handy guide from GitHub: https://help.github.com/articles/ignoring-files/.

·        With both our code and our .gitignore file ready, we’ll need a readme file. A readme file is the first file a GitHub repo displays to visitors, so it’s good to include some useful information about the author, the purpose of the code, ways to use it, ways to contribute to it, and so on. Make a README.md file in the phpenv folder via your IDE or the Terminal with touch README.md and give it some content such as:

·        # Hello World

·         

·        This is a README file from the Jump Start PHP Environment book.

·        Learning about Git and GitHub!

The .md extension indicates that this is a Markdown (MD) file―one type of file GitHub uses to display the readme content in a pretty, formatted manner. Knowing MD isn’t necessary in order to understand the rest of the content in this book; however, it is important in coding life, so I recommend you take a look at https://guides.github.com/features/mastering-markdown when you find the time.

Adding and Committing

To add all the files in our project to our repository, execute git add -A. The add command tells Git to add any changes that were made to the repo’s history track. The -A flag means “add new files, add changes to existing files, and add file deletions (that is, make note of all the files that were removed)”.

What this actually did, though, was merely tell that Git we’ll be tracking the changes to all the files it just added some time in the future. To actually make a commit, and by that create a restorable point in our project’s life cycle, we need to use the commit command: git commit -m 'Added my first files!'. The -m means “commit message” and it’s where you label your changes. Anyone coming into your project will be able to look at that exact point in time and see your message, instantly knowing why you did what you did. Execute this now.

Now that our files are added and committed, let’s introduce a change. Open index.php again and change “Hello World” to “Hello Bob” so that the file looks like this:

<?php echo "Hello Bob";

Then make another add and commit: first git add -A, then git commit -m 'Changed World to Bob'.

Visit the page in the browser again via http://phpenv.app/ and notice how it now says “Hello Bob.”

Reset

We really like Bob, but our boss doesn’t, and asks us to change it back to “World.” We could make a change and commit, and be done with it. But in complex projects with many files, reverting changes by manually changing files back to the state they were in before will just fail to work. That’s why we have the reset command. To reset back to the previous commit, we need to find out the ID of that commit.

We can do this with:

git log

In my case, as you can see in Figure 5.1, the ID of the commit before the most recent one is b6adf1756bb9b94fcf9b46c6121180dc12b96176.

Finding the ID of our commit

Figure 5.1. Finding the ID of our commit

To reset to it, we execute:

git reset --hard b6adf1756bb9b94f

Notice how we used a shorter hash than what git log gave us. That’s a feature of Git―just the first ten or so characters of a hash are enough to identify the correct commit we're looking for.

Our entire Bob modification is removed and it’s as if nothing ever happened. A refresh of http://phpenv.app will confirm this.

It can be tedious to find out the exact commit ID, so shorthand identifiers such as HEAD~1 are supported, too. HEAD is “current commit” and ~1 tells Git to go one parent into the past. Doing git reset --hard HEAD~1 would have worked, too.

The --hard option tells Git “no matter what changes we have pending, this reset is more important than anything, so just do it―no questions asked.” Without --hard, Git would have complained if we had made any other uncommitted changes.

GitHub

Now that we’re happy with our source code again, let’s put it online for others to clone and inspect. Sign up for a GitHub account if you haven't already, at https://github.com.

1.    In the top-right corner, click the Create New > New repository button, shown in Figure 5.2.

Creating a new repository

Figure 5.2. Creating a new repository

2.    Give it a name of your choice, such as “phpenv,” and leave all other options on their default value.

3.    On the next screen, you’re given instructions on how to place some existing code online, seen in Figure 5.3.

Instructions on adding code to the repository

Figure 5.3. Instructions on adding code to the repository

Let’s follow these instructions, and in our Terminal/Git Bash execute (don’t forget to modify USERNAME in the URL to match yours, of course):

git remote add origin git@github.com:USERNAME/phpenv.git

git push -u origin master

The remote add command tells Git “this repository has a copy that isn’t on this machine. The copy’s URL is this, and we can refer to it as 'origin' in the future.” The push command tells Git to “upload all the changes we've made so far to the URL you know as 'origin'.” The -u flag allows you to just say git push in the future, without origin master, but needs to be specified during the first run. master refers to the branch name, but diving into branches is outside the scope of this book for now (see the section called “Useful Resources” at the end of the chapter for more information). The output produced by these commands should resemble the following:

Counting objects: 5, done.

Delta compression using up to 8 threads.

Compressing objects: 100% (4/4), done.

Writing objects: 100% (5/5), 713 bytes | 0 bytes/s, done.

Total 5 (delta 0), reused 0 (delta 0)

To git@github.com:Swader/phpenv.git

 * [new branch]      master -> master

Branch master set up to track remote branch master from origin.

4.    Visit the URL of your repository in your GitHub account, and you should see the files you created residing there, as depicted in Figure 5.4.

Our files are now in the repository

Figure 5.4. Our files are now in the repository

To share this code with others, send them the link. They can then use the git clone command to clone it to their computers, or download it as a zip archive as we did in the previous chapter.

Finally, let’s add one more change and push it to the GitHub repo for all to see.

Modify the index.php file so it contains the following:

<?php

echo "Hello ".(isset($_GET['name']) ? $_GET['name'] : "World");

This code, when run with PHP, allows the visitor to input their name like this http://phpenv.app?name=Bob and see the message “Hello Bob.” Go ahead and test it out.

Now let’s add and commit:

git add -A

git commit -m 'Name is now dynamic!'

Note: Be Careful with Quotes

If you receive a warning saying -bash: !": event not found, it’s because you’re using double (") rather than single quotes ('). Make sure that you use single quotes with your commit messsage.

Finally, let’s push the code:

git push

If we now refresh the GitHub page, we should see the updated state of our code as shown in Figure 5.5.

The updated repository

Figure 5.5. The updated repository

Notice how the commit message next to index.php is different from the others? This indicates that it’s the only file that changed in the latest commit.

Go and explore GitHub’s interface. Click on the files, overviews, statistics, and various commits. See what GitHub offers in terms of information about your project―you’ll be using it a lot in your future career. If you like, feel free to also explore some of the GUI tools for Git. A comprehensive list is available at the following URL: https://git-scm.com/downloads/guis.

Useful Resources

To learn more about Git, see SitePoint’s Jump Start Git, or Apress’s Pro Git. Both are newbie-friendly.

If you don’t feel like taking the time to read an entire guide, there are helpful illustrated guides at GitHub that cover both Git and GitHub in a very approachable manner. Even though we basically covered both in our usage example before, I recommend going through at least the “Hello World” and “Getting Your Project on GitHub” guides before proceeding with this book. Consider it homework.

Summary

In this chapter, we looked at version control systems and explained how they work and why they exist. We used an example project to briefly demonstrate what they can do, and suggested some additional learning materials.

In the next chapter, we’ll talk about hosting, explaining where to find a server, what to use and what to avoid, how to deploy code to a live server, and more.