Introduction to Git


Vicky Steeves | March 20, 2017


What is Git?

Git is a revision control system, a program to manage your source code history. It is strictly a command-line tool. Most use it to collaborate and version code!


From Wikipedia: Version control is "the management of changes to documents, computer programs, large web sites, and other collections of information."

Basically, it's a way for us to compare, restore, and merge changes to our stuff.

Basic Git Overview

The purpose of Git is to manage a project, or a set of files, as it changes over time. Git stores this information in a data structure called a repository.

A Git repository contains, among other things, the following:

  • Snapshots of your files (text, images, whatever)
  • References to these snapshots, called heads

The Git repository is a hidden sub-folder in your project folder, called .git. You probably won't have to touch this ever.

Basic Git Overview: Branches

Git works on branches, which represent independent lines of development, as each snapshot is linked to a 'parent' one it built upon. By default, everyone's repositories are on a "master" branch.

How Git Does Version Control

There are 3 states that your objects can be in:

How Git Does Version Control

When you add objects, you are telling Git that you made changes you want to track.

How Git Does Version Control

When you commit your changes, you tell Git that it is the latest version of your objects.

Setting Up Git

Let's get on the command line and start!

  • On Windows, in the start menu search, type Git Bash
  • On Mac OSX, search terminal from spotlight search

Then type the following as separate commands:


$ git config --global user.name "Vicky Steeves"
$ git config --global user.email "vicky.steeves@nyu.edu"
$ git config --global color.ui "auto"
$ git config --global core.editor "gedit"
$ git config --list # lists your configurations
					

Where it says core.editor, put in your favourite plain text editor. This could be simply Notepad (Windows) or TextWrangler (Mac), but NOT Word.

Create a Folder & Repository

To create a blank repository, we have to create a new project folder and then initialize Git inside of it.

Type the following as separate commands in your command line:


$ cd Desktop 
$ mkdir hello-world 
$ cd hello-world 
$ git init 
					

You've just created an empty Git repository!

Let's Track a File

  1. Open your text editor from before.
  2. Type out: hi there everyone, I am learning Git because I rock.
  3. Save this file as hi.txt in your hello-world folder.
  4. Go back to the command line.

Type the following as separate commands:


$ git add hi.txt
$ git status
					

Adding our Text File

You should see something that looks like this:

Committing our Text File

Before we commit, let's just what we've just done:


$ git diff --cached
					

Let's commit so Git officially records this as our first draft!


$ git commit -m "first draft"
$ git status
					

You should see something that looks like this:

Now try it on your own!


  1. Modify the text file in your hello-world folder.
  2. Add it and commit it.
  3. Raise your blue stickie note to show you've finished!

Viewing Revision History

To review what you've been up to, type this in the terminal:


$ git log
					

This will list your commits with their IDs, date/time of creation, and commit messages. If you want to only look at the changes to a specific file, enter this command in the terminal:


$ git log hi.txt
					

This will list changes as before, but only those affecting this file.

Viewing Different Commits

Remember that weird number from git log next to commits? This unique hash allows you to refer to that version. For example, enter this in your terminal:


$ git diff 7a9209f  # first 7 characters of hash as shown before
					

This compares your current files with that previous version.

Using History

The same hash from before can be used to check out files from that previous version:


$ git checkout HEAD filename
					

checkout is used to tell Git to revert files back to the version listed.

Exercise

Now let's try viewing and rewriting history!

  1. Overwrite hi.txt | [4.3] - [4.5]
  2. Revert to the first saved version of hi.txt | [5.0]
  3. Switch back to the most recent version of hi.txt | [6.0]
  4. Put up your blue stickynote!

Visualizing your history!

On the command line, run this command within your Git repository:


$ gitk
					

You should see a visualize layout of your development history, branches and all!

Before the more advanced stuff...

Review: Branches

Git works on branches, which represent independent lines of development, as each snapshot is linked to a 'parent' one it built upon. By default, everyone's repositories are on a "master" branch.

Branches

To create a branch, you just need to type git branch branch-name like so:


$ git branch experimental
					

To view all your branches, you'd enter:


$ git branch
					

In this list, there will be an asterisk (*) next to the branch you are currently on. In case you want to delete a branch, it's simply:


$ git branch -d experimental
					

Moar Branches

Different branches are useful for testing a new feature but not implementing it until you're sure it works! To switch to a different branch, it's:


$ git checkout experimental
					

You can edit your repository, and then go through the regular process of adding, staging, and committing your changes:


$ git add .
$ git commit -m "updated content"
					

Even Moar Branches

You've tested everything, and it works! Now, you want to merge the changes made in experimental into master. Try:


$ git merge experimental
					

This will work if the changes are compatible. If there are conflicts, markers will be left in the problematic files showing the conflict; you will need to resolve this before you can merge branches. Git instinctly doesn't let collaborators overwrite each other.


$ git status # to see what lines of which files need fixing
					

Even Moar Branches:
Conflicts Are the Worst

Merge conflicts are tricky to navigate. You can always undo a merge and go back to the state before the conflict occurred, if you and your collaborators agree one branch or version is better than the other. Open the file-in-conflict in your text editor. It will look like:


If you have questions, please
<<<<<<< HEAD # the beginning of the issue
open an issue on GitLab
======= # divides changes from each other
use our contact form.
>>>>>>> branch-a # end of issue, with the branch name
					

Resolving Conflicts

Decide what you want to keep, delete the conflict markers <<<<<<<, =======, >>>>>>> and save the file. Using the example, it looks like this:


If you have questions, please open an issue or ask in our IRC channel if it's more urgent.
					

Then go through the normal process of add and commit. If you made a mistake when resolving a conflict, your can roll it back to the commit before the merge happened with:


$ git reset --hard COMMIT-HASH
					

And start over again.

Rebasing vs Merging

git rebase solves the same problem as git merge:

Merging creates a new `merge commit` in the experimental branch that ties together the histories of both branches:

Rebasing re-writes the project history by creating brand new commits for each commit in the original branch.:

Collaborating without talking about GitLab yet!

Cloning & Remotes

Git is designed to give everyone an isolated development area. This means that changes are not automatically passed back and forth between repos. When you clone a repository, it creates a remote connection called `origin` that points back to the original repo:


$ git clone git@gitlab.com:VickySteeves/hello-word.git 
# or git clone ../myrepo if it's all local, just give it a path
					

Remotes For Days

You need to manually pull upstream commits into their local repository or manually push their local commits back up to the central repository. The git remote command is an easier way to pass URLs to these "sharing" commands.


$ git remote -v
# origin /home/vicky/hpc-git/cloned_repo/../myrepo (fetch)
$ origin git@gitlab.com:VickySteeves/hello-word.git (fetch) 
# origin /home/vicky/hpc-git/cloned_repo/../myrepo (push)
$ origin git@gitlab.com:VickySteeves/hello-word.git (push) 
					

Even More Remotes

You can have use more than one remote, which is nice if you want to track what each team member is doing. This lets you collaborate outside the central repo. You can add that by using:


$ git remote add NAME LOCATION/URL
					

If you ever need to rename or delete a remote:


$ git remote rename OLD-NAME NEW-NAME # rename
$ git remote rm NAME # delete
					

Fetching

Fetching imports commits from a remote repo into your local repo. The commits from the remote repo are stored as remote branches instead of local branches. This gives you a chance to review changes before integrating them into your repo:


$ git fetch REMOTE-NAME # or git fetch REMOTE-NAME BRANCH
					

Fetched content is represented as a remote branch, so it has absolutely no effect on your local dev work.

Pulling & Pushing

git pull rolls merging and fetching into one command, to synch your local repo with upstream changes easily:


$ git pull REMOTE-NAME
					

git push transfers commits from your local repo to the remote repo. It's not the opposite of pull, but the opposite of fetch, because we're exporting commits to remote branches.


$ git push REMOTE BRANCH
					

This has the potential to overwrite changes, so you need to be careful how you use it!!

Pushing

Most people do use git push to publish local changes to a central repo. After you've made a bunch of local commits and are ready to share them with collaborators, you can clean them up with an interactive rebase (to push one commit instead of 100), then push them to the central repo:


$ git checkout master
$ git fetch origin master
$ git rebase -i origin/master # Squash commits, fix up commit messages etc. 
$ git push origin master
					

This only works if you have write access to the server where the central repo is, and if nobody has pushed in the meantime. Beware of merge conflicts!

Ok...collaboration in GitLab using all we've learned.

Creating a Repository

When you are logged into gitlab.com, you should be able to see a + sign in the top right-hand corner.

Creating a Repository

Name your new repository hello-world, don't fill out anything else and hit "Create Repository":

Make a Local Copy

Git calls copying a remote repository to your local computer cloning. When you make a new repository, it comes with these instructions:

We want to use that HTTPS: link to clone our repository; to make a local copy we can work on and edit. *don't do this yet*


$ git clone LINK
                    

Make a Local Copy

In our case, since we already have a Git repository initialized, we just want to link it with the one hosted on gitlab -- this is called a remote in Git, with the default one called 'origin'.
So run the following:


$ git remote add origin LINK
                    

Now, we have to PUSH all our locally created content to the origin remote.

Syncing Local Changes with the Central Repository

Now that we've added the link to our central repository to our local one, we have to push all our newly added content.

This adds 1 more step to what you already know how to do:


$ cd repository-name # navigate to your repository
$ git add -A # shortcut to stage all your files
$ git commit -m "adding hi.txt and bye.txt"
$ git push origin master # send these changes to the central repo
                    

Go refresh your browser to see your changes!

Collaborating on a Central Repository

Since the joy of gitlab comes from sharing, let's discover how to collaborate on here.

  1. You and the person to your right are now partners. People on the ends, wrap around the right.
  2. Decide who is "A" and who is "B".
  3. You will be syncing changes ONLY to person A's repository. Don't do anything yet
  4. Put up the blue sticky note when you are all set!

First Tasks:

Person A: add person B as your collaborator on gitlab using their gitlab name or email address:

First Tasks:

Person B: clone person A's repository:


$ cd Desktop # or wherever you want to put the repository
$ git clone LINK
$ cd repository-name # go into your new repository
                    

Syncing Your Partner's Changes

Person A:

  1. Make changes to hi.text
  2. Save your changes.
  3. Go through the steps to sync to the central repo in Slide 5

Person B:

  1. To get the changes your partner just made, you must pull the central repo!
  2. You do this through (from within the repository's folder!): git pull origin master
  3. Check out your new message!

Next, reverse the roles and try again!

Other Ways to Collaborate

Forking & Merge Requests

A fork is a copy of a repository. Forking a repository allows you to freely experiment with changes without affecting the original project.

A merge request is when you want to integrate the changes you made into the original repository you forked. You describe the changes you made and make sure your changes don't conflict with the original repo's code.

Intial Fork

Creating your copy...

Now you have a copy of their repo!

Follow the Same Instructions


You can edit, push, pull, add, commit, everything the same.

When you want your changes to be integrated into the official repo, you make a merge request!

Make a Merge Request

Compare your PR to their Repo

Describe Your Changes

Submit the Merge Request!

Thank you! Questions?


Email me: vicky.steeves@nyu.edu

Get this presentation: on GitLab