I am neither a command line wiz or a git expert, but learning a few commands in the terminal and learning the basics of Git has changed my workflow forever!
Here is the scenario that I’ve run into more times than I care to count. While working on a new feature for a project you find it necessary to submit a patch that conflicts with the files you are modifying for the new feature. What is the solution? In the past, this meant undoing all the progress on the new feature request so that nothing is accidentally deployed, writing the patch, deploying, and then try to paste in or rewrite all of the work you just undid. This is uncool and very inefficient.
Or how about this: your client requests a new feature that spans several files, but once it is completed decides that the site audience is not ready for it. Now what do you do? There are more features that need to be developed but how do you continue on without trashing the feature that is now on hold?
Let me introduce you to a better way.
Version Control – Your new best friend
Version Control has been around for a long time. In fact, if you have ever saved multiple versions of a file (i.e. logo-draft.psd, logo-final.psd, logo-final-2.psd, logo-final-final.psd…) then you were manually version controlling your documents.
Version Control Systems (VCS) have been developed to automate this process. There are many different flavors of Version Control Systems, but they all fall into one of the following categories:
- Local Version Control System, like Time Machine on OS X.
- Centralized Version Control System, like SVN which is used for WordPress core and plugin repositories.
- Distributed Version Control Systems, like Git.
For the purpose of this post, we are going to focus Git, a Distributed Version Control System. This system maintains a complete repository on each client which not only enables for full control over a local repository, but it creates the ability to collaborate with multiple contributors on the same repository.
For more information on the different kinds of Version Control, please see this article.
GUI vs CLI
I have recently become a big fan of the Mac OS X Terminal and hope to make the command line a little less intimidating with this post. I realize however that the command line is not for everyone and wanted to point out that there are several GUI interfaces for Git available a few of which I have listed below.
- Tower – http://www.git-tower.com/
- GitHub – mac.github.com, windows.github.com
- See more
Getting Started with the Command Line
If you are anything like I was a few months back, then the command line scares you to bits! If you are already a command line ninja, you can skip down to the next section, otherwise I want to teach you the 3 basic commands that you will need to rock git.
cd (Change Directory)
Navigating between files in the command line is pretty easy if you know a few tricks.
My favorite trick is tab for auto complete. Start typing the name of the file or directory that you intend to navigate to and press tab and the command line will auto complete the name for you.
cd .. (cd.. on Windows)
Use cd .. to move to the previous directory. Alternatively, string them together to go back several directories
Access the root
Navigate to the base of your user directory with cd ~/ or to the base directory of your system with cd /.
ls (dir on Windows)
Use ls to list the contents of a directory. I use this if I am unsure of the name of the file that I am navigating to.
pwd (Present Working Directory)
List the path of the present working directory. I use this together with cd to navigate.
Getting Started with Git
Alright, now we get down to the fun stuff.
There are several ways to install Git. Here are the easiest in my opinion:
- Mac – http://code.google.com/p/git-osx-installer
- Windows – http://msysgit.github.com/
If you want to curl or apt-get, then follow the instructions here.
The Git Tree – understanding the basics
Imagine a tree when you think about the structure behind Git. There is a master branch, which is like the trunk, and off of the master branch can come any number of different branches that can be developed in parallel with the master branch. As a general rule, actually, I recommend never developing in the master branch. Instead try to separate the different features of you code into different branches and then merge them into the master branch when you are ready to make them live.
Now that we have Git installed and have a basic concept of how it is supposed to work, let’s take a look at some of the commands we will be using on a daily basis.
Navigate to any directory and git init will initialize a new repository in that directory.
Use git add to stage a given file to be committed. Use git add . –all to stage all files to be committed.
git commit [-a] [-m]
Commit all staged changes. Essentially, this is pushing the save button on the repository and you can revert back to this commit at any time. Use [-m] to specify a commit message and [-a] to commit all files, staged and unstated.
git commit -m “This is a message for a commit that commits all staged files”
git commit -a -m “This is a message for a commit that stages and commits all pending files.”
Use git checkout to switch between different “branches” of the repository.
To create a new branch add the -b flag followed by the new branch name.
git checkout -b new-branch
When you are ready to apply the modifications you’ve made in a branch to the master branch (or to any other branch for that matter), use git merge <branch-name>.
Note that you can also merge the master branch back to any of the development branches. This is particularly useful when you want to test a feature against some newly updated code that was just pushed to master.
Check the the files that are staged and not staged for committing. Use this to see what files have been changed and added since the last commit.
git diff [first-branch second-branch]
Use git diff to see the differences in the files since the last commit. This can also show the differences between different branches by using git diff first-branch second-branch.
git [command] –help
If you are unsure what command to use, run git –help. If you know the command but are not sure about the variables run git [command] –help.
Working with a Remote Repo
So far, we have only been working on a local repository. This is great for local workflows, but what if we are collaborating with someone on Github or Beanstalk? Or perhaps we need to collaborate using SVN because we are working on a plugin. We’ll look at how to do that next.
Sometimes when collaborating on a project, there are files and / or directories that are specific to the users instance or machine. This may include operating system files such as .DS_Store or program specific files like .idea. We can control the files that Git will process with .gitignore.
The .gitignore file is not auto created when you initialize a repository like the .git file is, so if you have not done so already, add a file called .gitignore to the root directory of your repository (this will be the same directory that the .git directory is in). Add a line separated list of any items that you want git to ignore to the .gitignore file, make the items relative to the root directory of the repository. Git will reference this file for any files or directories that it is supposed to ignore.
Cloning is the process of copying a remote repository to your local machine. Use the following commands to clone and work with remote repositories.
Use git clone <url> to create a local copy of a remote repository where <url> is the location of the remote repository.
git remote add
To add a remote repository that you would like to sync with your local repository, use git remote add <name> <url> where the <name> is an identifier that you choose and <url> is the path to the remote repository. If you used git clone then there is already a remote repository defined. To view all remote repositories, use git remote -v.
To pull changes from a remote repository, use git pull <remote> <branch> where <remote> is the name of the remote repository and <branch> is the remote repository branch you are pulling from and the local repository you are pulling to.
To push changes to a remote repository, use git push <remote> <branch> where <remote> is the name of the remote repository and <branch> is the remote repository branch you are pushing to and the local repository you are pushing from.
Note, always git pull before you git push, git likes to handle content merging locally.
Integrating with SVN
If you are working on a WordPress plugin or something else that uses SVN as the version control, don’t worry, you can still use Git to manage your local workflow.
The first step is to add .svn to the .gitignore file (we covered this process earlier).
Now we need to tell SVN to ignore all Git files, but SVN is a little different from Git, however. Instead of adding a file to ignore assets, we need to use svn propedit. To ignore all git files we will use the following code:
svn propedit svn:ignore .git*
This is telling SVN to ignore all files and folders that start with ‘.git’. This will cover the .git folder and the .gitignore file.
That’s all! Now you can manage your development with Git branches and when they are complete, merge them into the master branch and svn commit.
I hope you enjoyed this article and are inspired to be daring with your code now that you know how to do so safely. I’d love to hear your thoughts, so please leave a comment below. If you would like more information on Git, I recommend checking out http://git-scm.com/.