On Github kroysemaj / git-GDI
If you haven't already, go to github.com and create a new account
It works the same as making an account for any other service
If you haven't already, go to
Choose your platform and install git
If you are running an older version of Mac OSX (10.5 or lower) this won't work. Raise your hand and we'll try to figure out an alternative.
Find your command prompt
I will be spoon-feeding you terminal commands today. When I do, they will look like this:
$ git example-command --flag -f
(The dollar sign ($) is your terminal's prompt. You don't need to type that. That's just a convention.)
$ type these commands exactly $ # Anything after a hashtag is a comment
When I give you more than one command, you will enter each command and press enter at the end of each line
To make sure you have git properly installed, run this command in your terminal:
$ git --version
If you don’t get an error, you’re good
If you do get an error, raise your hand
First let's set some config options for git These will tell git what details to use on the commits we make.
$ git config --global user.name "Your Name" $ git config --global user.email "Your Email"
If you're on a mac...
$ git config --global color.ui true
To make interacting with github a little easier, we will set up SSH for our Github accounts.
This is kind of like a doing a TSA Pre-Screen at the airport. It's more work up front but it makes it easier for us to work with our github repos without needing to put in our passwords over and over again.
First, we need to generate an SSH key.
$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com" $ # Creates a new ssh key, using the provided email as a label
When it prompts you to enter a file, just leave it blank and hit enter to accept the default.
$ Enter a file in which to save the key: # Press Enter
When it prompts you to enter a passphrase, just leave it blank also, then confirm.
$ Enter passphrase (empty for no passphrase): # Press Enter $ Enter same passphrase again: # Press Enter
Now we need to make sure our computer knows about the key we just made.
$ eval "$(ssh-agent -s)" $ # Agent pid 59566 $ ssh-add ~/.ssh/id_rsa
Now that we have an SSH Key on our computer we need to tell Github about it.
First let's copy our SSH key into our clipboard.
$ pbcopy < ~/.ssh/id_rsa.pub # Copies the contents of the id_rsa.pub file to your clipboardThe pbcopy command may not work for the Windows users.
Now, in your browser, click on your profile pick and select Settings from the drop down.
In the Settings panel, select the SSH keys from the sidebar.
From the SSH keys panel, click new SSH key.
Enter a description of this ssh key in the Title field (i.e. "work laptop"). Then paste the SSH key into the Key text area.
Click Add SSH key. It will ask for your password.
(We're almost there)
All we need to do now is test that everything worked.
Back in your terminal try this command:
$ ssh -T git@github.com
Hopefully, you'll get a slightly scary looking message that looks something like this.
The authenticity of host 'github.com (192.30.252.1)' can't be established. RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48. Are you sure you want to continue connecting (yes/no)?
Just type yes
Then you should see something like this:
Hi <username>! You've successfully authenticated, but GitHub does not provide shell access.
That means it all worked!
Let's demystify the command line
(It's not as scary as you think)
From Wikipedia
The command line interface (CLI or Terminal) is a means of interacting with a computer program where the user issues commands to the program in the form of successive lines of text (commands).
The command line is just another way to interact with your computer and give it commands like the mouse and the graphical user interface (GUI) that you're probably used to.
CLI commands look a little funny at first. But you get used to them pretty quickly. Most are some kind of extreme abbreviation of whatever task you want the computer to do.
ex. Change directory is cd
This was the way folks used computers for a long, long time. It still works great. I use the command line for almost everything now.
This is how the pros work. We're all pros. So this is how we'll work.
These commands are all for Unix / Linux and OSX.
A lot of these will work in a Windows terminal but not all.
But fear not! When we start working with git later, we will use an alternate terminal for Windows that will allow all these Unix commands.
I will be giving you the commands you need for today in the slides. However, if you want something to refer back to, this is a great reference for terminal commands. This list is for OSX but most of them will work in the Git Bash terminal for Windows.
What is it?
Version control (also sometimes known as source control) is a system that manages changes to a program, website, or other collection of documents.
Documents? You mean I can use this with any file or collection of files like Word docs or image assets?
Version Control solves two problems for a team of developers
Version control allows you to work on the same project simultaneously with other people, and helps you to avoid and manage conflicting changes
I work as a freelancer or am not on a team. What can version control do for me? ..lately
Version control systems allow easy viewing of previous changes, and makes it easy to undo a change set or revert documents back to a previous state
there was a kind of Save Button on Steroids™ that could save a project's state at various points and serve as a reliable backup...
Without needing to maintain multiple copies of the project in various places.
Guess what, there is!
There are two major types of version control
Centralized version control systems are run on one central server, and each collaborator checks out the code from and merges changes into the main server
Distributed version control systems allow each collaborator to maintain a separate repository of the code, which can be periodically reconciled with the main server
First things first:
git !== github
Git is an open source distributed source control tool.
Github is a social coding website for managing software projects that use git as their source control
If you don't have a working laptop, see if a neighbor will let you sit in with them. Talk is cheap and it's important to get your hands dirty with this stuff.
Git tracks changes by taking 'snapshots' of a project. You can think of this much like a snapshot in the real world.
When you change a file in a git repo (and save it), it now differs from git's snapshot. Git can now tell that there is a difference. But it only cares about the differences. Sort of like those 'Spot the difference' puzzles
This is how git would see these two files:
We are going to cover lots of git commands today. This handy cheat sheet will help you keep a lot of them straight and give you a simple quick reference.
Now that we are ready to start using git, we need a project to use it on. We wil create all the files and folders we need using the command line.
This is the procedure you would go through to create a new repo from scratch on a new project.
We will create a directory in which to keep all our work from today. To make sure we all stay together, we will start from the same place.
$ cd ~ #moves us to the HOME directory
Now create a new directory for all the projects from this class.
$ mkdir gdi-git
Now no matter where we navigate during class we can easily return to this folder using this command.
$ cd ~/gdi-git #moves us to our class work folder
Okay we have a folder for our class but we're going to be making several projects in this class. So let's create another directory for this first project. Then we'll make a file that will be our first project's source. First let's make a javascript file.
$ mkdir git-cmd-demos $ cd git-cmd-demos $ touch helloWorld.js
We will not be doing any programming in this workshop. However we will need to make some simple changes to some files so our version control can take notice and track those changes when we tell it to do so.
Open your helloWorld.js file in a simple text editor. I like Sublime Text but you can use the text editor of your choice.
TextEdit for OSX || Notepad for Windows.
helloWorld.js
console.log('Hello World!');
Creates a new git repository in the current folder including ALL child folders
ProTip: Do NOT run in your root folder.
To create a new git repo. Run this command in the root directory of your project
$ git init #from your git-cmd-demos folder
(seriously thats it)
So now you have a brand new repository. With nothing in it.
Reports the current status of the repo, such as whether any files have been modified or new files have been created
You can check the status of your repo to see that git can see all the files in the project but they are not being currently tracked.
$ git status
You should get a listing of any untracked files in the repo. Right now none of your files are tracked so you should get a list that includes all of the files in the repo.
If you don't get something that looks like this, raise your hand.
Adds an untracked file to the repo.
To add a new file to your git repo, you would use the command
git add <filepath>
$ git add helloWorld.js
If you check your status again you should see that the file is now being tracked (or staged) and is ready to be committed.
So far we've created the repo, created, and staged some new files. But we haven't actually 'saved' them to the repo. Right now they're just what we refer to as Staged.
There are basically 4 states in which a file can exist.
Untracked (not included in the repo) Tracked Changed Staged Commited (same as #2)Once you’ve got code staged you can commit that change. This creates a fixed point that you can build from or return to if needed.
ProTip: Don’t forget the -m to add your commit message. If you forget it, git will throw you into VIM and that will ruin your whole day.
So far, we've created and then added a file to our repo. But it hasn't been commited yet. To commit the new file to your git repo use the command
git commit -m “<message>”
$ git status $ git commit -m "Initial commit"ProTip: I always like to check my status before I commit just to make sure I’m not committing something I don't want to. If you haven’t noticed, git status is a command you’ll use a lot
Now that git is tracking our file. We can make changes to it and git will notice.
In your text editor, change helloWorld.js then save:
helloWorld.js
var name = 'Jimmmy'; console.log('Hello ' + name);
Then add and commit
$ git status $ git add helloWorld.js $ git commit -m "I made some changes!"
You can add new files to the project:
Let's create a file called <your-name>.js in our git-cmd-demos repo, add it to the repo (stage it), and commit it. While we're at it, let's put it in its own new directory.
$ mkdir names $ touch names/james.js
Just like before we need to put something in our file:
james.js
console.log("James");
Then add and commit
$ git status $ git add names/james.js $ git commit -m "I added a new file!"
So why stage AND commit? It seems redundant, right?
This is part of git's philosophy that source control should stay out of your way until you're ready to deal with it.
Let's say you are working in a project and you are working with the three different files:
The changes in blinky.js and inky.js are related to each other, but the changes in pinky.js are not related to the others.
You could do the following (don't type these commands):
$ git add blinky.js $ git add inky.js $ git commit -m "changes for blinky and inky" $ git add pinky.js $ git commit -m "unrelated change to pinky.js"
Now you have 2 tidy commits that are all grouped together logically rather than in one lump. By separating staging and commiting, you have greater control over what goes into each commit.
cd to our top-level folder for this class
$ cd ~/gdi-git #moves us to our class work folder
You can check where you are by using the pwd command
$ pwd #print working directory
You should see something like this...
/Users/jyork/Documents/git/gdi-git
As long as you have that gdi-git on the end you're in good shape
Allows you to look back over the commit history of your project to see who, when, and what someone commited to a repo.
Using this command is very simple.
$ cd ~/gdi-git #back in our class project folder $ git log
Pressing enter will allow you to see more of the log line by line.
In some terminals you may have press q to exit the log. If you don't have your terminal prompt ($ or >), try pressing q.
git log comes with a whole bunch of options to configure how the log information is displayed
Try this:
$ git log --pretty=oneline
Or these:
$ git log --pretty=oneline --max-count=2 $ git log --pretty=oneline --since='5 minutes ago' $ git log --pretty=oneline --until='5 minutes ago' $ git log --pretty=oneline --author=<your name> $ git log --pretty=oneline --all
So what's so great about being able to look back over your history?
A couple of things:
A hash (in computer science) is a fingerprint made of alphanumerics given to a piece of data to make it uniquely identifiable.
Whenever you make a commit, git makes a very long hash that can be used to target it. This will become useful in just a moment.
Every commit you make in a repo becomes an anchor point in that project's history. You can revisit these anchor points by 'checking out' that commit.
Here's how it works. When you run git checkout <hash>, git copies the snapshot of the referenced commit into your working directory.
To checkout a previous commit you need to know its hash (just the first 6 or 7 characters is enough). Let's create a new change and view it using git checkout.
$ git log $ git checkout b4b109 #your hashes will differ
When you checkout a commit you enter what's called 'detached HEAD state'. You can't keep any commits in this state as you're not on a branch (more on that later). So any commits you make while checking out a past commit will be marooned unless you stash them (more on THAT later) or move them to another branch.
So what is a branch anyway? Think of your project as a tree, the main course of development is its trunk. Smaller offshoots of development such as new features, bug fixes, etc. can be developed on a branch (off the main trunk so as not to conflict) and be integrated when needed.
git stash allows you to temporarily store all of your changes to be retrieved later.
When last we left our intrepid heroes they were off checking out old commits. Let's bring them home, make some changes, and stash them to see what happens.
$ git checkout master #sets you back to master
Let's change our helloWorld.js file:
helloWorld.js
this won't even compile!
(Make sure to replace the entire contents of the file)
Now we'll stash our awful changes.
$ git stash
Now look at the helloWorld.js file again.
helloWorld.js
var name = 'Jimmy'; console.log('Hello ' + name);
You're back to the working directory's last commit before any changes. And free to go off on a completely different, not terrible, path if needed.
So let's say you do some work and then need those stashed changes back. We can get them back, it's super easy!
$ git stash apply
Now check your helloWorld.js
helloWorld.js
this won't even compile!
Our terrible code is back!
If you didn't write over all the contents of the file when you changed helloWorld.js your stashed changes might cause a merge conflict.
Don't Panic! If you're on an unfamiliar screen, raise your hand and a trained professional will fix it. Not to fret! It's scary for us too. We will be learning to deal with merge conflicts later in the workshop.
cd to our top-level folder for this class
$ cd ~/gdi-git #moves us to our class work folder
Remember how to check where you are by using the pwd command
$ pwd #print working directory
/Users/jyork/Documents/git/gdi-git
10 minutes
10 minutes
We've already seen git checkout used to revisit old commits. You can also use this command to undo unwanted changes to a file or collection of files. You may have noticed that git actually tells you this when you check your status.
git checkout -- helloWorld.js would set the file back to the way it is in the repo's most current snapshot.
Back in our git-cmd-demos folder!
$ cd ~/gdi-git/git-cmd-demos
Let's create, add, commit, then change a new file.
$ touch beatles.js $ git add beatles.js $ git commit -m "added a file"
Then change the contents of the file:
beatles.js
console.log("Hey Jude");
Save the file and check your status, then checkout the file, and re-check the status
$ git status
$ git checkout -- beatles.js $ git status
There's no undoing this. Make certain you're sure before you discard your changes. If you're not sure, a safer option is to use git stash just in case you decide you want the work back.
cd to our top-level folder for this class
$ cd ~/gdi-git #moves us to our class work folder
Remember how to check where you are by using the pwd command
$ pwd #print working directory
/Users/jyork/Documents/git/gdi-git
5 minutes
2 minutes
If you've already added your changes to the staging area, you can't simply check them out to get rid of them. To unstage a file, you can use git reset. Again, git is pretty helpful in pointing this out on the status screen.
Back in our git-cmd-demos folder!
$ cd ~/gdi-git/git-cmd-demos
Let's stage the changes in our new file and then use reset to unstage it. Change the file again and this time add it to the staging area.
$ git add beatles.js $ git status
Now let's reset that file and re-check our status.
$ git reset HEAD beatles.js
NOTICE! This doesn't destroy the changes. It simply removes the file from the staging area. From here you can use git checkout to remove the changes entirely or continue working before re-staging. Unless...
If you REALLY want to get rid of the staged changes. You can add the
--hard flag to the git reset command. This will unstage and overwrite the files.
Change the file again and stage it. Then use git reset --hard to completely discard the changes.
$ git status $ git reset --hard
NOTICE: This does discard all the changes in your working directory. As before, make sure you're sure you know what you're doing when you use this command.
cd to our top-level folder for this class
$ cd ~/gdi-git #moves us to our class work folder
Remember how to check where you are by using the pwd command
$ pwd #print working directory
/Users/jyork/Documents/git/gdi-git
3 minutes
5 minutes
If you need to undo an entire commit. There's a command for that.
This is a little confusing, git revert actually creates a new commit that reverses the commit mentioned.
Back in our git-cmd-demos folder!
$ cd ~/gdi-git/git-cmd-demos
Let's change, save, add, and commit our beatles.js file. Right now it's empty.
beatles.js
//We won't keep this console.log("Hey Jude");
Add and commit the change.
$ git add beatles.js $ git commit -m "don't make it bad"
Now we'll use git revert to get rid of this commit.
$ git log
Since we're just reverting the most recent commit we can just use this command.
$ git revert HEAD
This will put you into VI, a built-in text editor. Learning to use this editor could eat up another whole class. Luckily, all we need to do in this case is enter a simple command to save the information git provides to us automatically
use this command exactly
:wq
Once your revert is successful, you should be able to see the reverting commit in your history.
$ git log
And if you check the beatles.js file. It should be empty, just like before we made the previous commit.
cd to our top-level folder for this class
$ cd ~/gdi-git #moves us to our class work folder
Remember how to check where you are by using the pwd command
$ pwd #print working directory
/Users/jyork/Documents/git/gdi-git
5 minutes
5 minutes
So now you know the basics of what you need to manage a repo that lives solely on your computer. Unfortunately, sometimes bad things happen to your computer.
In order to have one more layer of protection we're going to add our repo to our github account. This will also make it much easier to share and collaborate with other people.
First though, we need to prepare a place for the repo to live. In your web browser go to your github.com profile, log in, and look for the plus sign (+) next to your name in the upper right corner.
Select 'New Repository'.
Name your repo, add a short description and then click 'Create Repository'.
We will actually make use of two new commands here, one of which we will cover, another we will not. Fortunately github gives us these two commands for free.
After you create the repo find this heading on the repos page. Copy each command and run it in your terminal separately.
(Your url will be different)
Sends any committed changes on your local repo to whatever remote repo you have defined
When you clone a repo (more on that in a moment) it's automatically set to wherever you cloned from. The code given to us by github set it to our new repos destination.
Once your changes are committed locally, you can push them up to the remote server where they can be shared. Make some new changes to your local repo, save, add, and commit them. Then push the changes up.
$ git status $ git push origin master
If it works, you should see something like this.
You can also see the results on your github page.
This command will download any changes made to a defined remote and (try to) merge them with your changes. You must be in sync with the latest changes to a remote before you can push your own stuff.
We need to create a change to our repo on github. Luckily, github makes this fairly easy for us. It will create a readme file for us (just hit the green button), which we will then pull down.
There's another screen that looks like this. No need to change anything just hit the next green button at the bottom to commit the new file to your repo.
Now there is a file on our remote repo that we don't have locally. Let's make a new change and try to push it.
$ touch failboat.js $ git add failboat.js $ git commit -m "this won't work" $ git push origin master
Well that didn't work...
You probably got something that looks like this.
We need to pull the changes (the new file) down before we can push our new changes.
$ git pull
result:
Now that we're in sync the push will work
$ git push origin master
Copies a remote repository to your machine.
Note, this will create a new directory with a name matching the repo. After it creates the new directory it will copy the files into it.
In your terminal, cd to a directory in which you'd like to work.
$ cd ~/git-cmd-demos $ git clone http://github.com/kroysemaj/git-demo.git
Now if you check the contents of the class folder, you should see a copy of the git-demo project in there.
$ ls -al
Even cooler, because git-demo is a project with git as it's source control. It's already it's own repo, ready to be commited to, added to, pushed/pulled, etc. Have a look.
$ cd git-demo $ git log
cd to our top-level folder for this class
$ cd ~/gdi-git #moves us to our class work folder
Remember how to check where you are by using the pwd command
$ pwd #print working directory
/Users/jyork/Documents/git/gdi-git
10 minutes
As mentioned before, one of the biggest benefits to using git and github is that it totally streamlines working with a team.
Let's see how!
You already know most of what you need to know to work on a team using git and github. Let's prove it!
cd to our top-level folder for this class
$ cd ~/gdi-git #moves us to our class work folder
Remember how to check where you are by using the pwd command
$ pwd #print working directory
/Users/jyork/Documents/git/gdi-git
Sometimes (perhaps in the last exercise) things don't go so smooth.
Git will always try (and usually succeed) merge a repos' contents seamlessly. But when it is not sure how to do that, it will stop what it's doing and ask for your help.
What this mean is that git has a file that has contents that it doesn't know how to combine. So rather than guessing and possibly overwriting someone's work, it asks the developer to tell it what should be done.
THIS IS A GOOD THING
You'll usually see a message that looks like this:
Once you get that message, open the file in question in your editor. Look around until you find something that looks like this:
<<<<<<< HEAD This is my change ======= This is your change >>>>>>> 4486cc6114bf5159eb5b1ab1531cfea6fc4baff4
The two chunks of code between the <<<<< and >>>>>> is the conflicting code. We have to fix it and then add, and recommit it.
Since we want to keep both changes in the previous case, we should change the file to something like this, getting rid of the conflict brackets and making sure the rest of the content is there.
This is my change This is your change
Once that's done, it's back to business as usual: add, commit and push the files normally.
What command creates a new repo in your current directory?
git init
What command makes git track files that have not yet been added to a repo?
git add < file path >
BONUS! What command adds a tracked file's changes to git's staging area?
git add < file path >
What command 'saves' all the changes that have been added to the staging area to the repo as a new 'anchor point'?
git commit
BONUS! What flag should you never forget to add to this command to avoid ruining your whole day?
-m
What command discards changes that have not yet been staged?
git checkout < filepath >
BONUS! What command unstages changes that have already been added?
git reset HEAD
DOUBLE BONUS! What command kills all changes with fire and should be used very carefully?
git reset --hard
What command uploads your changes to a remote repo?
git push
BONUS! What command downloads changes from a remote repo?
git pull
Now we will use everything we've learned today in one final project for the day.
Instructions will be intentionally vague because I want you all to help each other as much as you need to get help from us.
This might be a good time to pair program or at least find a war buddy to work with.
Awesome work! Pat yourself on the back!
Is your mind blown?
Are you okay?
For more git fun try these!
git immersion - http://www.gitimmersion.comContact Info
James York