GIT and GITHUB

What They Are And How to Use Them

Holden Profit
( https://github.com/hprofit )

What is GIT?


A completely different type of VCS from the ones you're used to.

  • (Almost) Everything is local
  • Commits are snapshots (not differences)

Why GIT?

Because of how GIT works, creating branches becomes cheap and easy to do. This not only allows developers to create "experiment" branches which are easily reverted, but increases teamwork and collaboration on features.

How does GIT work?

GIT has 3 states for files to be in:

Committed
- Stored in your local DB/Repo
Modified
- Changed but not committed yet
Staged
- Changed and marked for going into your next commit

Git has 3 "Areas"

Repository (.git directory)
- Dir containing GIT metadata, the local DB/Repo for your project
- This is what is copied when you clone from another repository
Staging Area (or "Index")
- A file (found in .git dir) that holds info about what files go into the next commit
Working Directory
- A checkout version of your repo, decompressed from the repo and placed on disk for you to work with

The "Areas" of GIT

The mythical .git dir revealed!

An important note about GIT

GIT uses check-sums for all contents of a repo to track changes.
This makes it impossible for file contents to change without GIT noticing and erasing data or making something undoable are very difficult.
Effectively, it's best to think that GIT simply remembers everything you do and making it forget is (understandably) hard to do!

How to use GIT

Learn Terminal/CMD Commands

GUIs are nice, but using the terminal (or msysgit for Windows) will allow you to use GIT anywhere with minimal set up as well as better understand how GIT does things.
GUIs usually only implement a subset of GIT’s functionality and by learning the terminal you should be able to figure out the GUI while the opposite is not necessarily true.

GIT Commands

* This is by no means comprehensive, please refer to the sources slide for more detailed documentation. *

  • git config --global user.name "[name]"
    • This will set the [name] you want to associate to any commit actions you make
  • git config --global user.email "[email]"
    • This will set the [email] you want to associate to any commit actions you make
  • git init [project name]
    • Creates a new .git repository
    • [project name] will supply the repo with given name instead of the default

  • git clone [repository URL]
    • Copies the entire directory from the given repository URL
  • git status
    • Provides a summary of what files have been modified, added, or deleted
    • Files marked in red have not been added while files marked green have
  • git add [-A/--all/. OR file/directory]
    • Stages the named file/directory (or all) for commit
    • This means those files will be go into your next
    • NOTE: You can use * for regex purposes
  • git commit [-m "Commit message goes here."]
    • Commits all files that are currently staged to your local repo
    • NOTE: This does NOT move them to the actual repo online!

  • git pull [remote] [branch]
    • Pulls the changes from the given [remote]'s [branch] and auto merges them into the HEAD
  • git push [remote] [branch]
    • Pushes your local repo HEAD up to the targeted [remote]'s [branch]
  • git reset [--soft/--hard][paths]
    • UN-Stages the named file/directory (or all) from the staging area
    • --soft will merely undo any git add commands you have performed
    • --hard will undo git add AND discard all changes you've made

  • git branch [--all/-a/-av]
    • Lists out your branches
    • -a/--all will list local branches and those located within your remotes
    • -av will do the same as -a but also gives the last commit message
  • git checkout [-b] [branchname]
    • Switches you to the branch of the given [branchname]
    • -b will create a new branch of [branchname] and switch you to it
  • git branch [branchname] -d
    • Deletes the branch with the given [branchname]

  • git remote [-v/--verbose]
    • Lists out your remote names
    • -v/--verbose will list out remote names AND the associated URL
  • git remote add [name] [url]
    • Adds a new remote with the given [name] pointing to the given [url]
  • git remote remove [name]
    • Deletes the remote with the given [name]
  • git remote rename [oldName] [newName]
    • Renames the remote with the given [oldName] to the given [newName]

  • git merge [branch]
    • Attempts to auto-merge changes from the given [branch] into the current branch
    • Any files that GIT fails to auto-merge will be marked and will need to be manually merged before being added and committed again
    • Any merges done this way are entirely local only, no changes will be made to your remotes
  • git rebase [branch]
    • A different type of merge, this will rewrite the commit history of your branches
    • The history rewrite will smooth out your branch history and make it more readable and clean
    • Any merges done this way are entirely local only, no changes will be made to your remotes
    • DO NOT USE THIS ON PUBLIC BRANCHES!!!
  • git log [-p] [file]
    • Will list the commits starting with the most recent
    • -p [file] will go over the history of a specific file line by line

Useful GIT Tips

Sometimes you find yourself in a situation that might be a little difficult to get out of.
The following are some useful commands to solve some fairly common problems.

GIT Commands

* This is by no means comprehensive, please refer to the sources slide for more detailed documentation. *

  • git rm --cached [file]
    • This command will remove the given [file] from your .git repo
    • The file will show up as deleted from the repo while still existing in your local project
  • git rm --cached -r [directory]
    • This command will remove the given [directory] and all files within from your .git repo
    • The directory and all files within will show up as deleted from the repo while still existing in your local project
  • git remote update [remote] --prune
    • Will update the branch list for the given [remote]
    • If another repo's branches have been modified and you don't see them via "git branch -av" then you can use this command to manually refresh the list

How to use GITHUB

Creating a new Repo on GITHUB is a piece of cake.
Accessing a Repo on GITHUB can be a bit more challenging for the uninitiated.
There are multiple ways of doing so, but I'm going to cover SSH keys.

Creating an SSH Key

  • In terminal, you can use "ls -al ~/.ssh" to list out existing ssh key files.
  • ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
    • It will prompt you for the location you want to save, the key at pressing enter will default to ~/.ssh
    • It will then prompt for a passphrase. Hitting enter will default to none.
      • If you create a passphrase, you will be prompted when using the SSH key for the passphrase.

Using the SSH Key

  • Once you have your SSH key, open the file (id_rsa.pub by default) with TextEditor (or something similar)
  • Copy the contents to your clipboard.
  • On GITHUB (either your own or MHE's), go to Settings -> SSH Keys
  • and click on Add SSH Key
  • Give the key a title and paste the copied RSA SSH key from earlier into the Key field

Cloning a Repo

  • Go to your desired Repo and copy the SSH URL at the bottom right (it usually defaults to HTTPS)
  • In terminal, use git clone [url] to pull down a copy of the repo
  • Congratulations, you've cloned a GIT repo and are now ready to work!

So how do I actually use GIT?


A good question!
GIT projects tend to be set up and operate a little different from their CVS counterparts.
Here is a fairly typical example of how a GIT project would work.

A GIT project model


Image taken from Vincent Driessen's article

Main (Infinite) Branches

  • master Your production branch, this is what the public sees as the end result of all your hard work! This branch is not frequently committed to but rather merged into when you're ready for a release.
  • develop Your working branch, this is what you push your changes to the most. All code here is available to the team and updated frequently with new features, bug fixes, etc.

Finite Lifetime Branches

  • release When the project is ready for a release, the current develop branch is branched off and this is effectively "frozen code"
  • hotfix For those times when someone discovers a show stopping bug in production (which would never happen to you, of course!) hotfix branches can be created to solve the problem
  • feature Generally local branches that you use to section off work on particular items before merging back into develop These are common place and will usually be deleted once they've served their purpose.

Pull Requests

Instead of simply merging into your team's "central" repo, you may want to have someone review your code before it's committed. This can be done in the form of pull requests!

In their simplest form, a pull request is a notification to the maintainer(s) of a repository that you have changes you'd like to be reviewed and merged into said repo.

You can look up a fully detailed tutorial here!

Putting it all together


Now that you've seen an example, let's go through how a
typical day of development might work.

A small note, this may be specific to where I work,
taylor it to meet your needs if your workflow is different.

Step One

First thing you should do in the morning is update your local workspace.

  • git remote update --prune
  • git branch -av - if your develop branch says "[behind X]" then you need to
    update it to match HEAD
  • git checkout develop
  • git pull origin develop

Step Two

Once develop has been updated, you should
(i.e. are strongly encouraged to)
update your working branches, if you have any.

NOTE: Do NOT update master or release branches until those show changes from origin.

  • git checkout {branch}
  • git rebase develop - you might run into merge conflicts,
    but these will be rare if you've been diligent about keeping your local workspace up to date.
    More on this in the next section.
  • Repeat this for any other working branches you currently
    have to keep everything up to date with the HEAD.

Step Three

Work! Once everything is up to date as it should be, continue or start your work.
Assuming you've already started, simply
git checkout {branch} back to where you were and continue.
If, however, you're just starting something new, then:

  • git checkout -b {branch} - As discussed previously, this will simultaneously
    create and switch you over to the newly created branch.
  • Do your work now! Change files however you see fit.
  • When you feel like your work has reached a good point and you're ready to 'save' it, you can commit it to your local repo.

Step Four

Save your work and commit it!

  • git add . or git add --all - These (there is a difference, but it's negligible most of the time) will stage your work for commit. IT HAS NOT been committed yet at this point.
  • git commit -m "{message here}" - Replace the last bit with some short blurb about what changes you made. IT IS NOT up on github yet at this point.
  • git push {your remote} {branch} - If you've reached a point where your work on the feature is complete (however you define the word), then push it to your repo on github.
    • {your remote} - should point to your personal fork of the origin on github.
    • {branch} - the name of the branch you working on.

Step Five

Create a Pull Request! Once your feature is fully developed and ready to be integrated into the team's collective origin repo, go to your forked repo on github and click on either green button to initiate a pull request.

OR

  • Give your pull request a name and write a short blurb about what you did.
  • DO NOT MERGE IT YOURSELF!!
    The point of a pull request is code review! Once you have a pull request up, github (should) notify relevant members of your team to merge it, but don't be shy about notifying them yourself.

Git Merge and Rebase

One of Git's most powerful features is branches. It comes without saying that you'll have to eventually merge those branches and you have two options: Merging and Rebasing.
While they do (esentially) the same thing, they have a vital difference.

Merge will take all the changes on your current branch from where you initially split off and commit them as a single commit object into the branch you're merging into.

Rebase will take your current branch and rewind it to the point of branching then play all of the changes from the rebased branch onto it before re-applying your own on top of those.

Sources

Questions

Holden Profit
( https://github.com/hprofit )