After this lesson, students will be able to:
- Explain basic git commands like init, add, commit, push, pull and clone
- Distinguish between local and remote repositories
- Create, copy, and delete repositories locally, or on Github
- Fork and clone remote repositories
Before this lesson, students should already be able to:
- Use the command line
- Use a text editor
First things first - Git is not Github. This is a common mistake that people make.
Git is:
- A program you run from the command line
- A distributed version control system
Programmers use Git so that they can keep the history of all the changes to their code. This means that they can rollback changes (or switch to older versions) as far back int time as they started using Git on their project.
A codebase in Git is referred to as a repository, or repo, for short.
Git was created by Linus Torvalds, the principal developer of Linux.
Github is:
- A hosting service for Git repositories
- A web interface to explore Git repositories
- A social network of programmers
- We all have individual accounts and put our codebases on our Github account
- You can follow users and star your favorite projects
- Developers can access codebases on other public accounts
- GitHub uses Git
Think about this quote: “Git is software. GitHub is company that happens to use Git software.” So yes, you can certainly use Git without GitHub!
Version control is a kind of software used to record and re-use changes (or versions) on files so that an history of the file content can be reviewed.
There are two main types of version control:
- Centralized
- Distributed
Centralized version control (CVCs) has one central repository that is shared among all team members.
Schema from IBM Developer works
The main concept of a centralized system is that it works in a client and server relationship. The repository is located in one place and provides access to many clients. It’s very similar to FTP in where you have an FTP client which connects to an FTP server. All changes, users, versions of your project and information must be sent and received from this central repository.
The primary benefits of a Centralized Version Control is:
- It is easy to understand
- You have more control over users and access (since it is served from one place)
- Simple to get started
At the same time, Subversion has some drawbacks:
- Dependent on access to the server (requires internet connection)
- Hard to manage a server and backups
- It can be slower because every command connects to the server
- Branching and merging tools are difficult to use
Popular centralized version control systems (CVCSes) include:
- Subversion
- CVS
Distributed version control systems are a newer option. In distributed version control, each user has their own copy of the entire repository, not just the files but the history as well. Think of it as a network of individual repositories.
Schema from IBM Developer works
The primary benefits of a Distributed Version Control is:
- More powerful and detailed change tracking, which means less conflicts
- No server necessary – all actions except sharing repositories are local (commit offline)
- Branching and merging is more reliable, and therefore used more often
- It’s fast
At the same time, Distributed Version Control do have some drawbacks:
- The distributed model is harder to understand
- The revisions are not incremental numbers, which make them harder to reference
- It can be easier to make mistakes until you are familiar with the model
Popular distributed version control systems include:
Git is tricky to understand because describing 'how' it works would require the use of strange and technical-sounding words like:
- Directed acyclic graph
- SHA-1
- blob
- tree
However, you don't actually need to know how it works under the hood in order to use it.
Even though you don't need to know how they work, it is useful to know that your local repository consists of three "trees" maintained by Git.
- Working Directory: which holds the actual files.
- Index: which acts as a staging area
- HEAD: which points to the last commit you've made.
There are also a lot of commands you can use in git. You can take a look at a list of the available commands by running:
$ git help -a
Even though there are lots of commands, on the course we will really only need about 10.
To understand how Git works, we need to talk about the lifecycle of a Git-tracked file.
Schema From git-scm.com
There are 4 main stages of Git version controlled file:
- Untracked: The file will not be added in the next commit
- Staged: Staged files have not yet been committed to memory but they are "on deck" so to speak for your next commit
- Unmodified: The file has already been committed and has not changed since the last commit
- Modified: You have changes in the file since it was last committed, you will need to stage them again for the changes to be added in the next commit
Once you have committed a file and it becomes "unmodified" then it's contents are saved in Git's memory.
- Not saved in git memory: Your file is not saved until you commit the file to Git's memory
- Saved in git memory: Only once you have committed a file, it becomes saved in Git's memory
First, create a directory on your Desktop:
$ cd ~/Desktop
$ mkdir hello-world
You can place this directory under Git revision control using the command:
$ git init
Git will reply:
Initialized empty Git repository in <location>
You've now initialized the working directory.
If we look at the contents of this empty folder using:
ls -A
We should see that there is now a hidden folder called .git
this is where all of the information about your repository is stored. There is no need for you to make any changes to this folder. You can control all the git flow using git
commands.
Let's create a new file:
$ touch a.txt
A small cross should show next to your prompt!
git:(master) ✗
If we run git status
we should get:
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
a.txt
nothing added to commit but untracked files present (use "git add" to track)
This means that there is a new untracked file. Next, tell Git to take a snapshot of the contents of all files under the current directory (note the .)
$ git add .
This snapshot is now stored in a temporary staging area which Git calls the "index".
To permanently store the contents of the index in the repository, (commit these changes to the HEAD), you need to run:
$ git commit -m "Please remember this file at this time"
You should now get:
[master (root-commit) b4faebd] Please remember this file at this time
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a.txt
If we want to view the commit history, we can run:
git log
You should see:
* b4faebd (HEAD, master) Please remember this file at this time
To exit this view, you need to press:
q
Now let's open a.txt in Sublime:
$ subl a.txt
Inside the file, write something.
If you press return
in the terminal, you will now see that you have untracked changes.
Running git status
again will show you that a.txt has been modified.
Let's now make a second commit.
$ git add .
$ git commit -m "Second commit"
Checking git log
will show you 2 commits with different ids:
* 6e78569 (HEAD, master) Second commit
* b4faebd Please remember this file at this time
We can revert the file back to the first commit using it's specific commit id with:
$ git reset --soft b4faebd
This will do a soft reset, where the changes in the file we made are still there - the changes are staged but not committed anymore.
If we want to revert the file back and disregard any changes (dangerous!), we can use:
$ git reset --hard b4faebd
Let's do this together:
- Go to your Github account
- In the top left, hit the + button and select
New repository
- Name your repository
hello-world
- Initialize this repository with a README (So that we can
git pull
) - Click the big green Create Repository button
We now need to connect our local Git repo with our remote repository on GitHub. We have to add a "remote" repository, an address where we can send our local files to be stored.
git remote add origin [email protected]:github-name/hello-world.git
In order to send files from our local machine to our remote repository on Github, we need to use the command git push
. However, you also need to add the name of the remote, in this case we called it origin
and the name of the branch, in this case master
.
git push origin master
This should fail due to new files on the remote repo.
As we added the README.md in our repo, we need to first pull
that file to our local repository to check that we haven't got a 'conflict'.
git pull origin master
Once we have done this, you should see the README file on your computer. Now you can push your changes:
git push origin master
Refresh your GitHub webpage, and the files should be there.
Now that everyone has their first repository on GitHub, let's clone our first repository!
Cloning allows you to get a local copy of a remote repository.
Navigate back to your Desktop and delete your hello-world repository:
cd ~/Desktop
rm -rf hello-world
Now ask the person sitting next to you for their github name and navigate to their repository on github:
https://www.github.com/<github-username>/hello-world
On the right hand side you will see:
Ensure that you have SSH checked and copy this url.
To retrieve the contents of their repo, all you need to do is:
$ git clone [email protected]:alexpchin/hello-world.git
Git should reply:
Cloning into 'hello-world'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
Checking connectivity... done.
You now have cloned your first repository!
The fork
& pull
model lets anyone fork an existing repository and push changes to their personal fork without requiring access be granted to the source repository.
Most commonly, forks are used to either propose changes to someone else's project or to use someone else's project as a starting point for your own idea.
When you fork a repository, you make a new remote repository that is exactly the same as the original, except you are the owner. You can then clone
your new fork and push
and pull
to it without needing any special permissions.
When you clone a repository, unless you have been added as a contributor, you will not be able to push your changes to the original remote repository.
When you want to propose a change to a repository (the original project) that you have forked, you can issue a pull request. This basically is you saying:
"I've made some changes to your repository, if you want to include them in your original one then you can pull them from my fork!"
Before you can open a pull request, you must create a branch in your local repository, commit to it, and push the branch to a repository or fork on GitHub.
-
Visit the repository you pushed to
-
Click the "Compare, review, create a pull request" button in the repository
-
You'll land right onto the compare page - you can click Edit at the top to pick a new branch to merge in, using the Head Branch dropdown.
-
Select the target branch your branch should be merged to, using the Base Branch dropdown
-
Review your proposed change
-
Click "Click to create a pull request" for this comparison
-
Enter a title and description for your pull request
-
Click 'Send pull request'
Use the internet and what you've learned today to answer the following questions with a partner:
- How do I send changes to the staging area?
- How do I check what is going to be committed?
- How do I send the commits to Github?
- How do I go back to the previous commit?
- How do I check the configuration on a specific machine?
- How does github know that I am allowed to push to a specific repo?
As a developer, you'll have to use Git pretty much everyday, the learning curve is steep and all the principles of version control can be a bit blurry sometimes, hence why we ask students to push their homework everyday and to commit regularly during project time.
Don't be frustrated by all the new commands because we will definitely have the time to practice during this course.
- Explain the difference between forking and cloning.
- Describe the steps to initialize a Git repository and link your local repository to a GitHub remote location.