Git is a system for storing changes to files in a repository consisting of one or more branches.
Let's briefly define what each of these terms mean.
A repository is basically just metadata for a directory (or folder) on your local file system. Just like you can have many directories on your file system, you can have many git repositories on your computer. You can think of a repository as a way to store information about the contents of a particular directory (and the changes made to those contents over time).
Use git init
to create an empty repository under the current working directory.
When you make changes to files (including creating them), you have to add the changes and commit the changes to store them in the local git repository.
You add changes (or stage them) to prepare them for committing via the git add $files
command.
Changes that have been added can be committed for permanent storage in the current branch (more on this later) via the git commit
command. When you commit a change, you should include a message to describe the change and why it was made. Include a message using the -m "This is my message"
option for the git commit
command.
Each commit has an author, and git identifies authors by their email address. So before you make any commits, you should tell git what your email address is via git config --global user.email "$your_email"
. You only need to do this once.
Changes are stored in a "timeline" or "history" called a branch.
A branch? Why a branch? Well, picture a tree. It has a trunk that extends out to many branches, and each branch can extend out to many other branches. In fact, we can even think of the trunk as just a big, central branch. It's the same in git. A branch is a timeline of committed changes. By default, every repository starts with a single branch called master
, which you can think of as the tree trunk, and you can easily create branches off of master
.
But why create branches? What's the point? Branches allow us to capture a set of changes (one or more) and keep them organized and separate from any other changes. Any time you commit file changes to a git repository, those changes belong to a branch. If you create a repository and never create any branches, all changes will be stored under the default master
branch.
Branching has many uses:
- It allows us to easily switch or compare between different versions of the same file
- It allows us to organize changes per intent
- It allows us to merge a whole group of changes from one branch to another all at once
- It allows us to propose and review a group of changes together before merging/accepting them
Branches are "logical" rather than "physical", meaning you only have one copy of each file on your file system at a time, regardless of how many branches you have. When you switch branches, git will automatically update the files on your file system to match the current state of the branch. This makes branches (in git) lightweight and cheap.
You can list all local branches with the git branch
command.
You can create a new branch (which branches off of the current branch you're in) via git branch $new_branch_name
or git checkout -b $new_branch_name
.
You can switch between branches using the git checkout $branch_name
command.
Use git log
to view the history of a branch (exit with the q
key).
By default, a git repository only exists on your local file system, which doesn't do a whole lot of good if your hard disk crashes. Fortunately, it's really easy to copy your local repository to a remote location for redundant storage and even for sharing your work.
Copying changes from a local repository to a remote repository is called pushing. Copying changes from a remote repository to a local repository is called pulling (which uses fetching and merging behind the scenes).
If you're ok with sharing your repository for the whole world to see, you can use GitHub to store your repositories remotely for free! To do so, create a repository on GitHub (typically using the same name as the directory on your local file system), add the new remote to your local repository via the git remote add $name $url
command, and then git push
your changes to the remote destination.
When you do a push, you should specify the remote to push to and which branch you want to push. Otherwise, git will just push everything to a remote named origin
.
A typical workflow for making any changes that you plan to commit looks like this:
- Create a new branch to represent your upcoming changes
- Make your file changes and commit them against the new branch
- Push the new branch to a remote (typically named
origin
and pointing to a provider like GitHub or Bitbucket) - Open a pull request on the remote system using your web browser
- Review and merge the pull request remotely using your web browser
- Pull the branch that was updated remotely (the branch your changes were merged into, which is typically
master
) - Delete the branch remotely (using your web browser) and locally (using
git branch -d $branch_name
andgit remote prune $remote_name
)
Note that a pull request is a feature of git hosting systems like GitHub or Bitbucket and is not an inherent part of git itself.
You can learn the most common git commands using Codecademy's online tutorial starting here: https://www.codecademy.com/learn/learn-git
Code School and GitHub also teamed up to provide this neat tutorial: https://try.github.io/
$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"
$ mkdir new-repo
$ cd new-repo
$ git init
$ git status
$ git branch -a
$ git remote -v
$ git checkout -b $branch_name
$ git checkout $branch_name
The "safe" way (will only delete if the branch has been merged):
$ git checkout master
$ git branch -d $branch_name
The "unsafe" way (will delete regardless):
$ git checkout master
$ git branch -D $branch_name
$ git add $files
$ git commit -m 'put a useful message here'
$ git checkout -- $files
$ git remote add $remote_name $remote_url
Your main remote should be use the name origin
.
$ git push -u --follow-tags $remote_name $branch_name
e.g.
$ git push -u --follow-tags origin master
If the branch already exists locally:
$ git checkout $branch_name
$ git pull $remote_name $branch_name
Or if the branch does not yet exist locally:
$ git fetch $remote_name $branch_name:$branch_name
$ git checkout $branch_name
$ git remote prune $remote_name
e.g.
$ git remote prune origin
Rlly helpful.