Git Tutorial

Mac/Linux Setup

Installing Git

Here is a general installation on Mac/Linux. If you are using Windows, then enjoy yourself.
Git is actually installed on MacOS, but we’ll be reinstalling it so that we’ll have the newest version:

  • go to Git
  • download the software for Mac
  • install Git choosing all of the default options

First Time Git Configuration

Before you can start using Git, you need to configure it. Run each of the following lines on the command line to make sure everything is set up.

# sets up Git with your name
git config --global user.name "<Your-Full-Name>"

# sets up Git with your email
git config --global user.email "<your-email-address>"

# makes sure that Git output is colored
git config --global color.ui auto

# displays the original state in a conflict
git config --global merge.conflictstyle diff3

git config --list

Git & Code Editor

The last step of configuration is to get Git working with your code editor. Below are three of the most popular code editors.

Atom Editor Setup

git config --global core.editor "atom --wait"

Sublime Text Setup

git config --global core.editor "'/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl' -n -w"

VSCode Setup

git config --global core.editor "code --wait"

Create a Git Repo

Create a Repo from Scratch

mkdir -p git-practice/new-git-project && cd $_

Use git init to initialize a empty new empty Git repository.

.Git Directory Contents

Here’s a brief synopsis on each of the items in the .git directory:

  • config file - where all project specific configuration settings are stored.
  • description file - this file is only used by the GitWeb program, so we can ignore it
  • hooks directory - this is where we could place client-side or server-side scripts that we can use to hook into Git’s different lifecycle events
  • info directory - contains the global excludes file
  • objects directory - this directory will store all of the commits we make
  • refs directory - this directory holds pointers to commits (basically the “branches” and “tags”)

Clone An Existing Repo

Clone from URL

git clone https://github.com/udacity/course-git-blog-project

Clone with rename

git clone https://github.com/udacity/course-git-blog-project blog-project

Determine A Repo’s Status

git status

On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
  1. On branch master – this tells us that Git is on the master branch.
  2. Your branch is up-to-date with ‘origin/master’. – Because git clone was used to copy this repository from another computer, this is telling us if our project is in sync with the one we copied from. We won’t be dealing with the project on the other computer, so this line can be ignored.
  3. nothing to commit, working directory clean – this is saying that there are no pending changes.

Git Log Command

Use Git Log

git log

By default, this command displays:

  • the SHA
  • the author
  • the date
  • the message

It will display the log in less mode:

to scroll down, press

  • j or ↓ to move down one line at a time
  • d to move by half the page screen
  • f to move by a whole page screen

to scroll up, press

  • k or ↑ to move up one line at a time
  • u to move by half the page screen
  • b to move by a whole page screen

press q to quit out of the log (returns to the regular command prompt)

  1. Use git log to find the commit that has a SHA that starts with f9720a. Who made the commit?
  2. Use git log to find the commit with the SHA that starts with 8aa6668. What is the message for that commit?
  3. Use git log to find the commit with the SHA that starts with f9720a9. When was that commit made?
  4. Use git log to find the commit that has the message Set article timestamp color. Which commit belongs to that SHA? Provide the first 7 characters of the SHA.

Change Git Log Displays

  1. the SHA - git log will display the complete SHA for every single commit. Each SHA is unique, so we don’t really need to see the entire SHA. We could get by perfectly fine with knowing just the first 6-8 characters. Wouldn’t it be great if we could save some space and show just the first 5 or so characters of the SHA?
  2. the author - the git log output displays the commit author for every single commit! It could be different for other repositories that have multiple people collaborating together, but for this one, there’s only one person making all of the commits, so the commit author will be identical for all of them. Do we need to see the author for each one? What if we wanted to hide that information?
  3. the date - By default, git log will display the date for each commit. But do we really care about the commit’s date? Knowing the date might be important occasionally, but typically knowing the date isn’t vitally important and can be ignored in a lot of cases. Is there a way we could hide that to save space?
  4. the commit message - this is one of the most important parts of a commit message…we usually always want to see this

What could we do here to not waste a lot of space and make the output smaller? We can use a flag.

The git log command has a flag that can be used to alter how it displays the repository’s information. That flag is –oneline:

git log --oneline

Viewing Modified Files

The git log command has a flag that can be used to display the files that have been changed in the commit, as well as the number of lines that have been added or deleted. The flag is –stat (“stat” is short for “statistics”):

git log --stat
  1. how many files were modified in the commit with the SHA 6f04ddd?
  2. How many files were modified in the commit with the SHA 8d3ea36?
  3. How many lines of code were deleted in index.html in the commit with the SHA 8d3ea36?

Viewing File Changes

The git log command has a flag that can be used to display the actual changes made to a file. The flag is –patch which can be shortened to just -p:

This command adds the following to the default output:

  • displays the files that have been modified
  • displays the location of the lines that have been added/removed
  • displays the actual changes that have been made
git log -p
  1. look at the commit with the SHA 50d835d. What line number in app.css should you start looking at to see what has been changed?
  2. Using git log and any of its flags, what code was added in by commit 4a60beb?
  3. git log –stat and git log -p are both really helpful commands. Wouldn’t it be great if we could have both of their output at the same time?
  4. What does the -w flag do to the patch information?

Viewing A Specific Commit

You must be tired with the scrolling of the previous practices, how about supply the SHA of a commit as the final argument for all of these commands?

git log -p fdf5493

It still show other commits when scrolling.

The other command that shows a specific commit is git show:

git show fdf5493

The git show command will show only one commit.
By default, git show displays:

  • the commit
  • the author
  • the date
  • the commit message
  • the patch information
  1. How many rulesets are added to the CSS by commit 8d3ea36?
  2. There’s a commit with the message “Convert social links from text to images”. How many files were changed by this commit?
  3. Look at commit fdf5493. What’s the first HTML heading element that’s added by this commit?

Add Commits

Git Add

Make a new-git-project directory, and cd into it, then git init it.

First, create a file named index.html, and fill it with some starter code:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Blog Project</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <link rel="stylesheet" href="css/app.css">
</head>
<body>

    <script src="js/app.js"></script>
</body>
</html>

Things to note, the code references a CSS file and a JavaScript file.

Now create the CSS and JavaScript files. You can leave both of these files empty. We’ll add content to them in a bit.

We just made a number of changes to the repository by adding files and content. It’s time to do a quick check-in with Git:

git status

The Git noticed that there are some changes in the repository, so let’s stage those files.

$ git add index.html css/app.css js/app.js
# Same as
$ git add .

When you use:

git status

You can find that:

use "git rm --cached <file>..." to unstage

Git Commit

# check your default commit editor
git config --global core.editor
git commit
# Or just with -m flag
git commit -m "Initial commit"

Now add this just inside the body tag in index.html:

<header>
    <h1>Expedition</h1>
</header>
git status
git add .
git commit

How to write the commit message

The goal is that each commit has a single focus. Each commit should record a single-unit change. Now this can be a bit subjective (which is totally fine), but each commit should make a change to just one aspect of the project.

Now this isn’t limiting the number of lines of code that are added/removed or the number of files that are added/removed/modified. Let’s say you want to change your sidebar to add a new image. You’ll probably:

  • add a new image to the project files
  • alter the HTML
  • add/modify CSS to incorporate the new image

A commit that records all of these changes would be totally fine!

Conversely, a commit shouldn’t include unrelated changes - changes to the sidebar and rewording content in the footer. These two aren’t related to each other and shouldn’t be included in the same commit. Work on one change first, commit that, and then change the second one. That way, if it turns out that one change had a bug and you have to undo it, you don’t have to undo the other change too.

Do

  • do keep the message short (less than 60-ish characters)
  • do explain what the commit does (not how or why!)

Do not

  • do not explain why the changes are made (more on this below)
  • do not explain how the changes are made (that’s what git log -p is for!)
  • do not use the word “and”. If you have to use “and”, your commit message is probably doing too many changes - break the changes into separate commits. e.g. “make the background color pink and increase the size of the sidebar” The best way that I’ve found to come up with a commit message is to finish this phrase, “This commit will…”. However, you finish that phrase, use that as your commit message.

Git Diff

The git diff command can be used to see changes that have been made but haven’t been committed, yet.

Having Git Ignore Files

The .gitignore file is used to tell Git about the files that Git should not track. This file should be placed in the same directory that the .git directory is in.

gitignore.io is a good tool to generate .gitignore file.

Tagging, Branching, amd Merging

Tagging

The command we’ll be using to interact with the repository’s tags is the git tag command:

git tag -a v1.0
This will open your code editor and wait for you to supply a message for the tag. How about the message "Ready for content"?

CAREFUL: In the command above (git tag -a v1.0) the -a flag is used. This flag tells Git to create an annotated flag. If you don't provide the flag (i.e. git tag v1.0) then it'll create what's called a lightweight tag.

Annotated tags are recommended because they include a lot of extra information such as:

the person who made the tag
the date the tag was made
a message for the tag
Because of this, you should always use annotated tags.

After saving and quitting the editor, nothing is displayed on the command line. So how do we know that a tag was actually added to the project? If you type out just git tag, it will display all tags that are in the repository.

Branching

The git branch command is used to interact with Git’s branches:

git branch

It can be used to:

  • list all branch names in the repository
  • create new branches
  • delete branches

Create A Branch

To create a branch, all you have to do is use git branch and provide it the name of the branch you want it to create. So if you want a branch called “sidebar”, you’d run this command:

git branch sidebar

The git checkout Command

Remember that when a commit is made that it will be added to the current branch. So even though we created the new sidebar, no new commits will be added to it since we haven’t switched to it, yet. If we made a commit right now, that commit would be added to the master branch, not the sidebar branch. We’ve already seen this in the demo, but to switch between branches, we need to use Git’s checkout command.

git checkout sidebar

It’s important to understand how this command works. Running this command will:

  • remove all files and directories from the Working Directory that Git is tracking (files that Git tracks are stored in the repository, so nothing is lost)
  • go into the repository and pull out all of the files and directories of the commit that the branch points to

Branches In The Log

The branch information in the command prompt is helpful, but the clearest way to see it is by looking at the output of git log. But just like we had to use the –decorate flag to display Git tags, we need it to display branches.

git log --oneline --decorate

Delete A Branch

A branch is used to do development or make a fix to the project that won’t affect the project (since the changes are made on a branch). Once you make the change on the branch, you can combine that branch into the master branch (this “combining of branches” is called “merging” and we’ll look at it shortly).

Now after a branch’s changes have been merged, you probably won’t need the branch anymore. If you want to delete the branch, you’d use the -d flag. The command below includes the -d flag which tells Git to delete the provided branch (in this case, the “sidebar” branch).

git branch -d sidebar

One thing to note is that you can’t delete a branch that you’re currently on. So to delete the sidebar branch, you’d have to switch to either the master branch or create and switch to a new branch.

Deleting something can be quite nerve-wracking. Don’t worry, though. Git won’t let you delete a branch if it has commits on it that aren’t on any other branch (meaning the commits are unique to the branch that’s about to be deleted). If you created the sidebar branch, added commits to it, and then tried to delete it with the git branch -d sidebar, Git wouldn’t let you delete the branch because you can’t delete a branch that you’re currently on. If you switched to the master branch and tried to delete the sidebar branch, Git also wouldn’t let you do that because those new commits on the sidebar branch would be lost! To force deletion, you need to use a capital D flag - git branch -D sidebar.

Git Branch Recap

To recap, the git branch command is used to manage branches in Git:

# to list all branches
git branch

# to create a new "footer-fix" branch
git branch footer-fix

# to delete the "footer-fix" branch
git branch -d footer-fix

Branching Effectively

First, make sure we’re on the same page and have the same starter code. We’re going to be working in the new-git-project project. The project has the following files:

  • index.html
  • css/app.css (empty)
  • js/app.js (empty)

The CSS and JavaScript files are empty. Make sure the index file has the following content:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Blog Project</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <link rel="stylesheet" href="css/app.css">
</head>
<body>

    <header>
        <h1>Expedition</h1>
    </header>

    <div class="container">
        <main>

        </main>
    </div>

    <footer>
        Made with ♥ @ Git Practice
    </footer>
    <script src="js/app.js"></script>
</body>
</html>

The Game Plan

Right now we have all of our code on the master branch (which is the default branch). We’re about to work with branches, by:

  • adding content to them
  • creating new branches
  • switching back and forth between them

Let’s use branches to make the following changes:

  1. on the master branch - add a default color to the page
  2. create a sidebar branch - create a sidebar for the page
  3. on the master branch - change the heading of the page
  4. on the sidebar branch - add more content to the sidebar
  5. create a footer branch - add social links to the footer

Change 1 - Add Page Color

Make sure you’re on the master branch and add the following content to css/app.css:

body {
    background-color: #00cae4;
}

Save the file. Then add the file to the staging index and commit it to the repository.

Change 2 - Add Sidebar

Let’s add a sidebar to the page. But let’s say that we’re not really sure if we like the new background color. So we’ll place the sidebar branch on the commit before the one that sets the page’s color. Your SHAs will be different, but, for me, the commit that’s before the one that adds the color has a SHA of 5bfe5e7. So adding the branch to that commit would look like:

git branch sidebar 5bfe5e7

Now use the git checkout command to switch to the new sidebar branch.
Running a git log –oneline –decorate shows sidebar.

Did you notice that the master branch does not display in the output? Where did it go!?! Is it lost? Don’t worry, it’s still there, we’ll see how to get it to display in just a second.

But first, in your code editor, switch to the app.css file. Notice that it does not have the CSS we previously entered! Because of this, if you load the project up in the browser, the page won’t have a colored background. This makes sense since the CSS file is empty, but do you know why?

Create a sidebar by adding the following