What is Git?
Git is a VCS, or Version Control System. Version Control Systems record changes made to files so that you can compare and track changes over time, revert single files to a previous state, or even revert an entire project to an earlier version.
There are two good ways to install Git on Windows.
- The official build is available at git-scm.com/download/win.
- You can also use the GitHub GUI tool at windows.github.com. During the installation of this tool you can choose to install command-line tools as well (i.e. Git's command-line interface).
There are three ways to install Git on Mac.
- A git installer is available at git-scm.com/download/mac.
- You can download the GitHub GUI tool at mac.github.com. During the installation of this tool you can choose to install command-line tools as well (i.e. Git's command-line interface).
- You can install the Xcode Command-Line Tools. On Mavericks (10.9) or above you can do this simply by trying to run git from the Terminal the very first time. If you don’t have it installed already, it will prompt you to install it.
You can use the package management system that comes with your distribution.
On Debian based distributions like Ubuntu, use
sudo apt-get install git-all
See Git - Installing Git for more detailed information.
Basic Command-Line Git Usage
Initializing your project
Creating a project from scratch
(On Mac OSX and Linux use the terminal, on Windows use Git Bash)
For this example, we'll create a project to keep track of a todo list, and we'll do it entirely from the command line. The first thing we need is a place to store our todo file, so let's create a new directory. Use the
cd command to navigate to the directory you want the project in, and then use the command
mkdir todo to create a directory called
cd todo to navigate inside our project directory. This way when we initialize the git project it will be in the proper location.
git init to initialize the project. This creates a directory called
.git. Everything git needs in order to keep track of the project will be stored inside this directory. (A nice side effect of this is that if you ever want to remove your project from git, all you need to do is
Your first commit
Before we can commit something to this project, we need to have something to commit!
Let's create the text file we'll put our todo list in. Type
touch todo.txt. The
touch command creates a file, but does not open a text editor (like
Next we need to track
todo.txt in git. If you type the command
git status, git will tell you the current status of the project. At this point you should see something like this:
On branch master Initial commit Untracked files: (use "git add <file>..." to include in what will be committed) todo.txt nothing added to commit but untracked files present (use "git add" to track)
git add . to add all files in the current directory (represented as
. in the filesystem) to the git project, and stage them as changes in the commit. You will need to use
git add each time you commit in order for your new/modified files to be committed. You can use this to your advantage to only commit certain files in any given commit. Now if you run
git status, then you should see this:
On branch master Initial commit Changes to be committed: (use "git rm --cached
..." to unstage) new file: todo.txt
Now that we are tracking our files with git, we can save our changes by committing. Type
git commit -m "Initial commit" to commit our added files with the message
"Initial commit". If you do not use the
-m flag, you will be taken to a text editor to write your commit message. Just write your message and save the file to commit.
So we have our project all set up, and we've made our first commit, but what if we want to add this project to GitHub? Luckily, it's super easy.
Go ahead and create a new repository on GitHub (preferably named the same as your project directory). Then, copy the clone URL.
Type the command
git remote add origin <your clone url here>. This adds the remote repository on GitHub as a source for our local repository. Now we can pull from and push to this repository, and potentially collaborate with others on our project.
origin is a user-defined name, meaning you can call it whatever you want. This comes in handy for telling multiple remote repositories apart.
git pull origin master. This downloads any new/changed files in the remote repository to our local repository. This means that we'll get those nice
LICENSE files that we created in GitHub.
origin master means the remote repository
origin (which we defined earlier), and the branch
master within that repository.
Now that we have an up-to-date project, type
git push origin master. This pushes our new/changed files to the remote repository on branch
# Create project directory mkdir todo # Navigate to project directory cd todo # Initialize the git repository git init # Create our first file touch todo.txt # Track the file (and the contents of todo with git) git add . # ^ Add the remote repository as a source git remote add origin email@example.com:YourUsername/example-project-url.git # Download the GitHub created files git pull origin master # Upload todo.txt git push origin master
Cloning a project from another source (e.g. GitHub)
Cloning an existing project is super easy. All you have to do is navigate to the directory where you want the project, and then run
git clone <your clone url here>. A directory will be created with your project name.
cd into your project and you can use git normally.
Git can be used as a one-person VCS, but it is also an incredibly powerful collaboration tool. This section elaborates on some of git's collaboration features.
git pull, and the difference between
git merge and
Git pull is used to download changes from a remote repository. The situation in which you would mostly use this is for grabbing changes your teammates have made.
git pull actually aliases to two other commands:
git fetch and
git merge, in that order. In contrast, the command
git pull --rebase aliases to
git fetch and then
git fetch downloads the changes, but does not integrate them into the repository.
git merge and
git rebase integrate the changes into the repository in two different ways.
git merge creates a new "merge commit" that ties the local and remote changes together.
git rebase adds the commits from the remote project onto the end of the local project.
A git branch is just another line of development. Git branches allow you to work on a copy of the repository while you're adding a feature/fixing a bug/etc., and then merge those changes back into the main project once that feature is done. By using branches, you don't have to worry about conflicts during the actual development of the feature, and no unstable code is ever committed to the
When you're pulling changes from your teammates, all you're doing is merging their branches into yours.
git branch foo will create a new branch called
git checkout foo will update your project to reflect the changes in branch
foo, as well as point the
HEAD to branch
foo. You need to do this in order to make changes to branch
git checkout -b foo will run
git branch foo and then
git checkout foo.
git branch -d foo will try to delete the branch. If the branch has unmerged changes it will fail.
git branch -D foo will force delete the branch, even if there are unmerged changes.
git branch -m foo will rename the branch.
git merge foo merges branch
foo into the current branch.
How branches really work
In most other VCSs, branches are actual physical copies of the entire project. In git, however, branches are just pointers to commits. By default, there is only one branch (
master), and therefore only one pointer, and it always points to the latest commit. The
HEAD is just git's way of referring to whatever the current branch is. When you
git checkout foo, the
HEAD points to
foo. When you create a new branch the only thing that happens is a new pointer is created (pointing to the most recent commit).
Things get a little more tricky when you start committing to new branches.
Say we have two branches,
foo. You want to start working on a new feature, so you
git checkout foo, and begin editing files. Once you've made your changes, you
git commit -m "Made some changes". Now the two pointers (
foo) are pointing to different commits.
master is one commit behind, while
foo has changes and is one commit ahead.
At this point, there are a couple things that can happen.
If there were no changes to the
master branch while we were working in
foo, then a fast-forward merge takes place. The
master pointer is simply updated to point to the most recent commit in
foo, thereby syncing the branches.
If there were changes to
master while we were working on
foo, then a 3-way merge takes place. Git uses the two existing branch tips to create a third commit composed of the merged changes from both branches (hence the name 3-way merge).
Creating a branch, making changes, and merging it to
These are the commands you would run if you were to create a new branch called
new-feature, add a feature to
ImportantClass.php, and then merge the branch back to
git checkout -b new-feature
vim ImportantClass.php # make changes to a file
git add .
git checkout master
git commit -m "Added some feature"
git checkout master # so we can merge and delete
git merge new-feature
git branch -d new-feature # delete branch
new-feature since we no longer need it