Git Notes

Git is a distributed version control system compatible with most operating system. Faster than most competing solutions and the most used of all.

Git workflow

You make changes to files in your working folder, then add to staging index before finally writting changes to the repository.

Linux installation

Debian and derivatives

$ apt install -y git bash-completion

Configuration

Configurations can be set to be default (apply to everyone) using the machine, a single user, or apply only to a given project. This depends on where the gitconfig file is stored.

 folder:  /etc/gitconfig      # system wide configuration
 folder:  ~/.gitconfig        # User specific config
 folder:  project/.git/config # Project specific config

Use the git config command to write to the .gitconfig file. When followed by --system configuration data is system wide. Paramater --global references user specific configurations. Global specifies default git configurations for the logged in user. No parameter is required for Project specific config.

Sample configuration commands

Sample commands for git cofig

Sample git config settings

 $ git config --global user.name "Fred Smith"  
 $ git config --global user.email "fred@moo.com"  
 $ git config --global user.mobile "+447593744831"

 ## text output on command line is in colour
 $ git config --global color.ui true

 ## set default text editor
 $ git config --global core.editor "vi"

 ## Diff / merge tool to use
 $ git config --global diff.tool meld
 $ git config --global merge.tool meld
 $ git config --global --add difftool.prompt false

When git reports conflicts, launch a mergetool to resolve conflicts

$ git mergetool

List contents of gitconfig

 $ git config --list
   user.name=Fred Smith
   user.email=fred@moo.com
   color.ui=true
   core.editor=vi

 $ git config user.name
   Fred Smith

# view the contents of the configuration file
 $ cat ~/.gitconfig

Working with Projects

Git has a 3 step process of working with files

  1. Initialise Project - Specify which folder to track.
  2. Stage Changes - Upload changes to the GIT Index - a temporary step before submitting changes to repository.
  3. Commit Changes - Submit changes to the repository

Initialise a project

Initialising a project is a way of telling GIT which project to track. Projects are normally contained in separate folders. The way to initialise a GIT project is to CD into the root folder of a project and run the git init command, e.g.

$ cd ~/dev/www/lcm
$ git init
Creating shared repositories

If you want other users to be able to clone your repository, you should create a bare repository. These should end in extension .git

 $ git init --bare project-name.git
Git bare repository

Git allows you to create a repository on a server somewhere just so that multiple developers can pull or push to the repo. A bare repository contains just the .git folder. You could not ssh into the server and try to checkout files or commit.

 $ mkdir test.git # // create a folder for a bare repo
 $ cd test.git
 $ git init --bare  # //initialise a bare repository
 $ cd ..
 $ git clone test.git mylocal-repo # // clone your bare repo
Connect local repository to a remote repository

Assume you have already begun some project work on your local machine and later on opened a Github account. Now you want to upload your work including all current history to your newly created remote repository. Use the next command to specify a remote repository for your local git repository:

link local repo with remote git repo
    
        ## Check if you are your repo is already linked with a remote repo
        $ git remote -v

        ## link local repo to project1.git hosted at example.com
        $ git remote add origin https://example.com/repos/project1.git

        ## If you have forked the repo, you want to add the upstream link
        $ git remote add upstream git@github.com:user/repo

        ## push and pull commands have to be explicit
        $ git pull upstream master
        $ git push upstream master

        $ git push origin master
    

Now remote commands such as push and pull recognise the remote repo.

Stage changes

Consider the staging step as a way of telling Git your intention to place changes into the repository. The Git philosophy is to track set of changes, e.g. if changing System authentication affected 5 files in total, all the 5 files could be staged together so that the commit could be described as, "Changing authentication to use SHA2 encryption in response to vulnerabilities discovered in SHA1 and Blowfish encryption"

The git add command is used to add files and folders of a change set to the staging index. The changes are described in commit messages.

 $ git add .  # add current folder and sub folders to staging index.
 $ git add file1.txt file2.txt  add specific files to staging index
 $ git add folder/  # add all files in folder
 $ git add folder/*  # add all files in folder, same as above

Undo a Stage

Use Git HEADERS when you want to undo changes

 $ git reset HEAD  file2.txt # // remove file2.txt from Stage

Commit Changes

Commit actually writes changes into the repository that becomes permanent. Git generates a SHA1 checksum value of the change set which is then written in the HEADER. Git headers are central to what goes on in repositories they are useful for checking out and resetting changes.

$ git commit -m "Brief text to describe the change set/commit" # // commit changes to repository

Once commited, changes are permanent. It is possible to use the git ammend command to either edit commit message of the last commit or make adjustments to that commit. Once a commit has become a parent, it can not be amended. The only way to amend a parent commit is to create changes that reverse that parent commit. This way data integrity is maintained in Git.

It is possible to have commit messages that span multiple lines.

Using git from the command line with bash you can do the following:

 $ git commit -m "this is 
    a line 
    with new lines 
    maybe"

# // Press Enter for a new line.
Commit messages
# // commit all staged files
$ git commit -m "Description of commit" 

# // Stage all files in project and commit at same time
$ git commit -am "Description of commit" 

Best practices

  1. Messages should be descriptive. The first line should be short and brief. After blank line, say more about what the commit does. e.g Bug fixes - bug no. 33445.
  2. Subsequent lines should be less than 72 characters
  3. Describe what the problem was and what was fixed
  4. Messages should be about the commit and nothing else
commit logs

Use commit logs to view a snapshop of changes that have been made in the repository.

git log commands

 # -
 $ git log  # shows author, date and commit description
 $ git log --oneline  # shows all commits in one line
 $ git log --oneline --decorate --all --graph  # shows all commits on one line and graph
 $ git log -n 3  # show only up to 3 commit logs
 $ git log --since=2012-12-30  # show commits since date specified
 $ git log --until=2012-12-30  # show commits until date specified
 $ git log --author="Fred"  # show commits by Fred
 $ git log --grep="javascript"  # show commits with Javascript in commit messages.

# I'm trying to find a line of code in a specific file, 
# and I can't find which branch or commit it was in. 
# How I can search for this line of code?
$ git log -S 'function getAllManagers()' --all -- myfile.php

Commit Checksum
  • Each change log committed to the repository has a SHA1 checksum value that Git uses to identify the change set.

  • commit Head points to the position in the repositories where the next Commit will be written, same as a serial tape will record from where the write heads are currently positioned.

Ammend a commit

There maybe times when you dont want to generate an entirely new change set after making adjustments to files that relate to a change set that you have just committed. If that that change set is the last that has been committed, you can use the git ammend command to ammend the last commit. The command also works to simply make edits to commit descriptions.

 $ git add file2.txt  # first stage the files that have been amended.
 $ git commit --amend -m "New or same commit description"  # amend commit

If you forgot to add a file to a commit, or made a change so small you dont want to create an extra commit message, use the next command

 $ git commit -a --amend -C HEAD

Git Tags

Tags are labels you can put at any commit point in your repository. Head is assumed if no commit Id is specified during the creation of a tag. A good use for tags is marking version numbers in your repository.

Tag names are listed next to commit IDs when you use git log.

Git tag command examples

## Mark current commit (head) as mytag
$ git tag mytag

## List tags
$ git tag --list

## delete tag
$ git tag -d mytag

## Create an annotated tag. Give the tag a commit message "Version 5.0"
$ git tag -a v5.0 -m "Version 5.0"

## Display information about annotated tag
$ git show v5.0

Git Release

Tags that have release notes attached are called "Git releases"

Deleting a tag or a release does not delete the associated commit.

Checkout / Restore changes from repository

A git file can either be in Staging area or in Repository. When you bring a file back from staging or go back to a previous version in the repository, it is called checking out a file.

You can restore a file, folder or entire change set using the SHA value. It's important to specify if branch is the current one or another.

 $ git checkout filename.xtn # // restore file from staging
 $ git checkout -- filename.xtn # // checkout file from staging in current (--) branch.
 $ git checkout -- folderName # // checkout a folder

Checkout file from a change set

Use the git log command to find the SHA-VALUE and copy the whole or part of the value.

 $ git checkout SHA-VALUE -- filename.xtn # //checkout from change set in current folder.

Files from change set are put into the Staging Index not in the working folder. You can commit the change if you changed your mind and decided to undo the checkout

 $ git reset HEAD filename.xtn  # // remove the file from staging index into working folder
 $ git checkout -- filename.xtn # // remove file from working folder

Undo Changes

Using git revert

This is like using System restore. Reverts everything to what it was before the change set. The command requires the SHA-VALUE or part of the SHA-VALUE.

$ git revert SHA-VALUE

I have had problems reverting a file while it was open in another program. Make sure all files are closed before attempting revert.

Git Reset

Git reset is like rewinding the a tape recorder to previous commit. Its like pressing backspace to a required commit

  • Soft reset Moves HEAD pointer to the specified commit. Doesn't change the staging index or the working directory. Is the safest of all options. Only files in the repository will change. Those in working folder and staging index will stay at their latest versions.

  • Mixed reset In between soft and hard and is the default. Changes the staging index and the repository. Does not change working directory.

  • Hard reset Removes all changes that happened after the specified commit. Hard reset will permanently lose all uncommitted changes in the working directory, and the staging index. Use hard reset with caution because it is highly destructive.

# // rewind changes to the specified commit
$ git reset --heard 103ddc 

Deleting files from Git

Git can track changes of files deleted from the repository. Deleted files are first put in staging and must be committed.

 $ git rm filename.txt # // stage deletion
 $ git commit -m "Deleted filename.txt - use file.txt instead" #// commit changes

It is posible to delete files using your everyday operating system commands but you will still need to run the above commands to actually delete the files and commit the changes. Operating system commands have the advantage of putting things in the recycle bin if you prefer working that way. However, deletions are not added to the staging index like git rm does.

Renaming files in git

You can use OS tools to rename, or use GIT commands.

Using git commands to rename files
# // rename file and add changes to staging index
$ git mv old-file.txt new-file.txt

# // commit changes
$ git commit -m "renamed old-file.txt to new-file.txt" 
git - renaming files using OS tools

If you use OS tools to rename files, GIT perceives the action in terms of a file being deleted and a new 'untracked' file being created. Rename action is detected when you add the new file to the staging index, then remove the old (deleted) file from the repository.

 $ mv -v file.txt  new-file.txt 

 # // git reports file.txt as deleted and new-file.txt as untracked file in working directory
 $ git add new-file.txt // add new-file.txt to staging index
 $ git rm file.txt   // delete old file from repository

# // now that both files are in the staging index, git is able to note that the files were actually renamed.
 $ git status 

# // commit changes 
 $ git commit -m "file.txt renamed to new-file.txt" </code>

.git ignore

Ignored files are not tracked by git and they will not be committed to repository.

You may wantto set git to ignore

  • compiled binary files
  • compressed packages / files
  • logs and databases that change often
  • operating system generated files like temp files and swap files
  • user uploaded assets that are not necessarily part of your project

The list of files to ignore is stored is file called .gitignore stored in the root of the project folder (/project/.gitignore

Files to be ignored are listed one per each line, or you can use regex to specify file patterns. Acceptable regex characters are ? * [abcde] [0-9] !

Generate a .gitignore entries for you project at

https://www.gitignore.io/

.gitignore negation

Specify that git ignores all txt files except readme.txt

 # ignore all .txt files
 *.txt

 # don't ignore readme.txt
 !readme.txt

Use the trailing / to ignore all files in a folder
 # ignore all files in the video folder
 assets/videos/

After writing instructions into the .gitignore file, you will need to add and commit (optional) .gitignore to your repository.

 $ git add .gitignore
 $ git commit -m "git ignore"

globally ignore files

If you want to ignore certain files accross all the projects on your machine, you can do so by creating a global .gitignore file using the git config command.

$ git config --global core.excludesfile ~/.gitignore

The git ignore file can be located anywhere and can be named anything.

 # sample global git ignore
 ~*
 *.swp
 *.tmp

ignore files already being tracked

Git will not stop ignoring files that it has already started tracking before ignore rules were applied. To stop tracking a file, you need to remove the file from the staging index, also called cache.

 $ git rm --cached file.txt 
 $ git commit -m "Removed file.txt from index" 

This action will not delete file from the repository. The file will still be available for download but wont be tracked.

Stop tracking changes

Delete the .git folder in the root folder of your project to stop git from tracking changes in that project.

Working with assets in repository

Git Tree-sh

Tree-is is a pointer (reference to a commit). One way is to use the SHA-1 key, the who key or part of the key. At least four characters is required when referencing the short key.

Another way is use the HEAD pointer

Also use the branch reference.

Can also use Tag reference.

Reference to ancestry using the caret character or the tilde character

Parent commit

The parent of head can be refrenced using the caret as HEAD^, acf875043^, master^

Use tilde notation to reference the number of generations you want to go up.

HEAD~1, HEAD~

HEAD~1 means head going back one. Same as HEAD^, meaning parent of head.

Grantparent commit

To reference the parent commit of a parent commit (grandparent) you could use

HEAD^^, acf875043^^, master^^

Using the ^^ character to reference the number of steps up the tree you want to go can be cumbersome. Tilde makes it easy by specifying the number of steps

HEAD~3, HEAD~4

List files in git repository

$ git ls-tree HEAD // list git tree-ish.

You can parse folders that you would like to look into

 $ git ls-tree master assets/videos/
 $ git ls-tree master^^ assets/videos/

You may notice that are files in one tree added later that did not exist in the other tree.

When files are listed, they as referred to as either a blob or a tree. A tree is a directory and a blob is a file.

Track changes

See what was changed in a commit

 $ git show 4ea4f91

 # // navigate the tree. The next two lines do the same thing
 $ git show --format=oneline HEAD~2
 $ git show --format=oneline HEAD^^

See if any changes were made to files in a repository.

$ git status

Git diff

See what text changed.

# // difference between working directory and repository
# // does not show you new files. Use 'git status' for that
$ git diff

# // difference between staging directory and working directory
$ git diff --staged 

# //See what changed since the last commit.
$ git diff HEAD 

# // Use a GUI tool to show differences. Vimdiff is a good ncurses diff tool.
$ git difftool HEAD 

# // Configure a custom diff tool to use
$ git config --global diff.tool meld 
$ git difftool HEAD

Delete files from repository

# // Do git commit without gid add after removal.
$ git rm filename.xtn 

# // Rename files. Remember to commit changes
$ git mv oldfile.xtn newfile.xtn 

## // Re-download files from master
$ <code>git pull </code>

Git branches

To get the most out of Git, you would have to use branches a lot.

They are easy to setup, easy to maintain and do not cause a lot of headaches.

Branches allow you to allow new ideas. Instead of making numerous commit to your main branch trying new ideas, you can create a new branche where you try your ideas. Should they not work out, you can just delete the branch or merge the branch with the the main brach when your ideas work out.

You could also have a branch where developers can collaborate on a feature outside the main branch. Once completed, the new feature could then be merged to the main.

  • branches are created in the same working directory. Git uses fast context switching where it recognises which files belong to a particular branch.

  • branches can have sub branches that can merge with parent branches.

How to create a branch

List branches on the local machine

# // list all branches
# // The current branch is marked with a * (* master) if you have only one branch.
$ git branch 

# // Directory listing of all the branches
$ ls -la .git/refs/HEADS/ 

# // create a new branch
# // New branches that have not changes point to the same commit as their master.
$ git branch name_of_branch 

Switching branches

The working directory must be clean to be able to switch branches. Changes must either be committed, discarded or stashed before switching.

The current branch, or the branch in our working directory is called a checked out branch. you will notice it by the (*) next to its name.

  • use git checkout command to switch between branches.
 $ git checkout name_of_branch

If this is the first time you are switching branches, the new branch is an exact copy of the master. However, any changes made will remain in this branch. These changes wont be visible when you switch to the master branch unless you merge the branches first.

New branches can also be created with the git checkout -b command. Switch -b means create and switch branches at the same time.

We can create a sub branch of any checked out branch like so

$ git checkout -b fancy_login_mockup

To see where HEAD is pointing in all branches

$ git log --graph --oneline --decorate --all

Discard changes made to a file

 $ git checkout -- <filename>

-- refers to file. Only changes made to the file passed will be discarded in the above example.

Comparing branches

Compare one branch with another

 $ git diff master..my_branch

Will compare the most recent commits in master to the most recent commits in my_branch and list the difference.

You can compare a tree-ish of a branch

 # // compares current HEAD in master to previous HEAD in my_branch.
 $ git diff master..my_branch^ 

See which branches are completely included in the current branch

  $  git branch --merged

Any branches that are listed by this command means that those branches can safely be deleted if you choose to because they contain all the commits that are also in the current branch.

Renaming git branches

 # // rename old_branch to new_branch
 $ <code> git branch --move old_branch new_branch

Deleting git branches

Delete local branch

 $ git branch --delete branch_name

You cannot delete a currently checked out branch. You have to be working on a different branch to delete a branch.

You will get a warning message if you try to delete a branch that has not been merged to its parent branch.

Use a colon before branch name to delete the branch both remotely and locally.

Delete branch locally and from remote

 # // branch_name will be deleted from remote
 $ git push origin :branch_name

Show git branch on command prompt

Git completion script must be installed for this to work.

Run this script while in the git folder.

 $  __git_ps1

 # // result
 (branch_name)pc_user@hostname /git/folder $

When you navigate out of a git tracked folder, the prompt changes to normal system prompt.

Merging git branches

To merge branches, first you must make sure that the receiving branch is the branch that is currently checked out. E.g to merge branch 'products' with the master branch, the master branch must be the checked out branch.

# // first checkout the branch you want to merge into (target branch)
$ git checkout master 

# // Now merge the branch with latest changes
$  git merge products  # // thats it.

# // Confirm that the changes were merged.
$  git log 

Merges can become really complicated. It is good practice to run merges with a clean working directory.

Stashing GIT Changes

There are times when you might be working on a Branch A and then have to stop midway to work on another Branch B.

If changes in Branch A are still messy and not ready to be committed, you could stash them.

Stashing takes the dirty state of your working directory – that is, your modified tracked files and staged changes – and saves it on a stack of unfinished changes that you can reapply at any time.

Stash changes

Use the following commands to stash changes

git stash commands

 $ git stash 

 # // alternatively
 $ git stash save 

 # // give a name to your stash
 $ git stash save "stash_name" 

 # // include untracked files in stash
 # // files remain untracked when they are applied
$ git stash --include-untracked

# // include all files (even ignored ones)
$ git stash --all

# // pick and choose changes to stashes
$ git stash -p

# // show contents of a stash
$ git stash show stash@{0}

# // create new branch from stash
$ git stash branch < optional stash name >

# // get a single file from stash
$ git checkout  -- < filename >

# // apply changes from last stash and delete stash
$ git stash pop

# // delete last stash
$ git stash drop

# // delete specific stash
$ git stash drop stash@{0}

# // delete all stashes
$ git stash clear

It is now safe to switch branches and do work elsewhere.

View a list of Git stashes

To see a list of what you have stashed

 $  git stash list
 # //
 stash@{0}: WIP on master: 049d078 added the index file
 stash@{1}: WIP on master: c264051 Revert "added file_size"
 stash@{2}: WIP on master: 21d80a5 added number to log

In the above example, there are 3 stashes stash@1 to 3.

To get back to the branch that you have just stashed

# // bring back last stashed changes
$ git stash apply  

# // bring back a specific stash
 $ git stash apply stash@{1} 

Handling merge conflicts

If git fails to merge because conflicts were detected, you can abort the merge

$ git merge --abort // abort git merge

After an abort, your git repo is clean for you to merge with other branches that will not cause conflicts.

If you decide you want to resolve the conflicts, list files that are causing conflicts with the git status command.

$ git status // show files that are causing conflicts.

Open each of the files in a text editor that have been adentified as causing conflicts. Search for the string '====' to quickly jump to conflict sections and make appropriate corrections. When you are done, the file should read clean without conflict markers, etc.

When conflicts are resolved, add your file to the staging index

$ git add .

Commit your changes ...

$ git commit

Git commit command will open up a commit message in a text editor for you to edit. Edit the commit message to whatever you want. After saving the message, your commit will be complete and you have successfully dealt with a conflict.

Record and replay git conflict resolution steps

Git reuse recorded resolutions are useful where you happen to see the same conflicts again and again. You must enable the feature before you can use it.

$ git config --local rerere.enabled true // enable recording steps

The first time you perform a merge and resolves a conflict, git will remember how you resolved that conflict. If git sees the same conflict again when you try merging another branch that contains the same conflict, git will offer to resolve the conflict using the previously recorded steps. If you agree, all you will have to do then is to commit your changes.

Git rebase

  • Use rebase to rewrite commit history
  • Use rebase if branches do not cleanly merge due to conflicts.

To rebase a branch called 'A' on Master, you must checkout the branch first and then do a rebase.

Rebase a branch called A on Master

 # // first - checkout branch A
 $ git checkout A

 # // run rebase command
 $ git rebase master

 # // result
 # // 1. Git rewinds A to to the point the branch diverged with master
 # // 2. All changes that took place in master since A was taken are applied first
 # // 3. Any conflicts must be resolved in the normal way
 # // 4. Changes to A are applied last. With a rebase, you will be able to see your changes always ahead of master

Git will first rewind all changes on A and then applies them one at a time with changes from master picking up conflicts as it goes. This means ''changes to 'A' will always stay ahead of master''. Conflicts must be resolved as normal; then run rebase continue to proceed

$ git rebase --continue // run each time you resolve conflict while doing rebase.

When you merge your branch back into master, git rebase gives you a fast forward commit. Whereas git would have shown where the branch was taken, git will not show that history but will just move HEAD in a linear fashion.

To merge back into master without a fast forward merge

$ git checkout master $ git merge --no --ff branchA // git merge no fast forward.

Git will now always show that there was a branch in commit history.

Git rebase interactive

Allows you to rewrite history

$ git rebase -i HEAD~4

Git opens up the last 4 commits in a text editor where you can, delete entire commits and make it look like the commit never happened, mark some commits for rewording, squashing, etc.

When you save and exit this file, git will execute the commands. If you have some commits marked for squashing, git will open a text editor for you to rewrite your commit messages.

Git rebase interactive works well if you have not pushed your changes to origin master. In this situation, git will not make it easy for you to push. You could force a push (not recommended if someone has already pulled and is working on your changes).

$ git push -f // not recommended

If someone does a force push and you want to re-sync your changes with origin master, then you must reset to origin master.

$ igt reset --hard origin/master

git bisect

Imagine you have got a lot of commits done. In one of these commits somewhere, a file was deleted but you don't know when.

Git bisect will help.

Start git bisect mode

 $ git bisect start  # // turn git bisect mode on

 # // pick a commit the last commit when you know things were working ok
 $ git bisect good 11cd  

 # // specify a commit when things are broke.  We know this is currently broke
 $ git bisect bad  # // omitting commit ref means you are in HEAD

 # // (optional) show a visual representation of your commits. Git opens whatever git gui tool you are using.
 $ git bisect visualize 

To actually find the file that was deleted, you need a script file, which will return an exit status of TRUE or FALSE when git bisect runs it. The script must be in a folder that is outside your version control.

 $ vi test.sh

 # // contents of test.sh
 #!/bin/bash

 [ -e students.html ]

Run git bisect with your script.

$ git bisect run ~/test.sh

Git will test commits within the range specified looking for the file. If found, it will show you the commit hash, commit message, and the file name.

To get out of git bisect mode $ git bisect reset

Push changes to remote

git push

# // https://git-scm.com/docs/git-remote
# // origin = alias to remote git url
# // master = the branch you would like to push
# // -u = prompt for login credentials

$ git push -u --tags origin master

Git Aliases

Create an alias git s as shortcut for git status

git alias

# // Alias will be placed in global git config file
# // create the alias
$ git config --global alias.s status

# // Inspect global git config to confirm alias was created
$ cat ~/.gitconfig

# // result
# [alias]
#    s = status

## use the alias
$ git s

Aliases that are more than a single word must be created as an OS command prompt alias. In Linux, aliases could be added to .bashrc or .profile

.bashrc

alias gco='git config --global'

To create doskey aliases in Windows Commandline
  • create a file called 'alias.cmd' as an example in the %Userprofile% folder
  • add a registry key that points to the alias.cmd file
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Command Processor]
"AutoRun"="%USERPROFILE%\\alias.cmd"
alias.cmd

@echo off

:: Temporary system path at cmd startup
set PATH=%PATH%;"C:\Program Files\Sublime Text 2\"

:: Add to path by command
DOSKEY add_python26=set PATH=%PATH%;"C:\Python26\"
DOSKEY add_python33=set PATH=%PATH%;"C:\Python33\"

:: Commands
:: use $* for commands that take an argument
DOSKEY ls=dir /B
DOSKEY sublime=sublime_text $*  

:: Common directories
DOSKEY dropbox=cd "%USERPROFILE%\Dropbox\$*"
DOSKEY research=cd %USERPROFILE%\Dropbox\Research\

Git Best Practice

Sources: https://sethrobertson.github.io/GitBestPractices/