About

Git is a version control system.

History

First came single-file systems, which keep track of versions of individual files, but do not relate those files together. So this system wouldn't know that v1.0.2 of file A should be used with v2.3.0 of file B.

Some of these systems: SCCS RCS

Next came multi-file systems, which do relate different versions of files together so you can checkout one cohesive set of files.

Some of these systems: CVS, VSS, SVN, TFS, Perforce

Now we have distributed multi-file systems, which use changesets (groups of related edits) and can run simultaneously on many machines. Both clients and servers have the entire repository (full history) present at all times.

Some of these systems: Git, Hg, Bazaar, BitKeeper

Git was created by Linus Torvalds (the creator of Linux) after Linux and BitKeeper split up.
Git is written in Perl and C, and runs on many operating systems.

Topologies

Centralized: developers push all changes to one central repository. Often used in Enterprise environments.

Hierarchical: developers push their changes to a subsystem-based repository. The sub-repositories are periodically merged into the main repository. This is done for the Linux kernal because it is so large.

Distributed: developers push their changes to their own repository. Project maintainers will pull selected changes into the main repository, if they are deemed valuable. This is common in open-source projects on Github.
DVCS

DVCS stands for Distributed Version Control System.

Benefits

Backups are also simple, because they are just a clone of the main repository.

Reliable branching and merging. So you can make a branch for developing one feature or fixing one bug, and trust that it will be properly merged back into the repository. Branching allows you to keep all changes version controlled, and only merge them into the main repository when they are complete.

Every developer has a full local history on their machine.

You can analyze regressions, searching in a binary fashion to find out when a bug was introduced.
Terminology

Untracked File: a file that Git is not aware of - it is not the in repository or staging area yet.

Staged File: a file that Git is aware of, and is ready to be committed.

Staging Area: a place to put files that will part of the next commit. New and edited files are not automatically staged.

Git SHA (pronounced "git shaw"): the SHA1 hashcode that identifies a commit. Commits can usually be identified with the first 5-8 characters for their hashcode.
Process

If you have created/edited files for more than one reason, make one commit per reason. That way, the commit message will show the specific reason for each change. It is normal and expected to make many small commits.

Make a new branch for each new feature and each bug fix. This will save you a lot of trouble when you need to switch tasks.
Shell

For all commands, make sure you are in the directory of the repository.

Admin

Setup email and password, etc

git config

Repository Level

Create a new repository out of the current directory

git init

Copy a repository to local drive

git clone <url>
URL example: https://github.com/jquery/jquery.git
The repository will be cloned into a new directory named after the repository.
The upstreams will be set automatically.

View log of commits on repository

git log
Visualize the branching and merging.

git log --graph
Commits are listed newest to oldest.

git log --oneline
Displays a succinct version of the log, with just one line per commit showing the message.

git log --oneline | wc -l
Count how many commits have been made, using Word Count.

git log --oneline --graph
Shows the branching and merging.

git log --oneline --graph --all --decorate
Shows the branch graph for all branches (not just the current one), with labels decorating each line.

List the commits grouped by author, in author-alphabetical order.

git shortlog
Aka "git log --format=short"

git shortlog -sne
"-s" means "summary", so the commit messages will not be shown.
"-n" means "numerically", so the authors will be sorted by most-to-least commits.
"-e" means "email", so each author's email address will be shown.

View the changes between two commits

git diff dd6819..a15ec6
This example shows specifying a commit by just the beginning of its hashcode. This will show the differences between commit "dd6819..." and "a15ec6...".

git diff HEAD~1..HEAD
This looks that the commits "1 back from most recent" to "most recent".

git diff HEAD~1..
An unspecified commit will default to HEAD.

git diff --cached
Compares the repository to the staging area.

View all changes included in one commit

git show HEAD

View the fetch and push URLs.

git remote -v
"-v" means "verbose".
A local repository will not have any remotes.

git remote add <NAME OF REMOTE> <URL>
Add an origin URL to a local repository. The common name for this remote is "origin".
Or add the remote of a forked version of your project, for review. In this case, it is common to have many remotes.

git remote rm origin
Remove a named remote (in this case "origin").

View tags associated with stable points in development

git tag
A tag is a label associated with one commit.
Most often used to tag completed, stable versions of the project.
Tags are not pushed be default. Use "git push --tags".

git tag <TAG>
Adds a tag to the HEAD.

git tag -a <TAG>
Opens an editor to write in the message to annotate the tag with. Tag is added to the HEAD.

git tag -s <TAG>
Add a signed tag to the HEAD. (always includes an annotation)
This tag will be signed by you, the user.

Workflow

Download remote changes (merge will be second step, if you want these changes in your branch)

git fetch

git fetch <NAME OF REMOTE>
If you have multiple remotes, you can specify which to fetch from.

Update from remote repository - fetch and merge together

git pull

git pull <REMOTE NAME> <REMOTE BRANCH>
Example: "git pull origin master"
Specify where to pull from, if the current branch has no upstream set.

View list of edited local files

git status
Red is an unstaged edit or new file.
Green is a staged edit or new file.

Add all changes to staging area for next commit

git add -A
Add one file to the staging area

git add FILENAME
Add all edited (updated or deleted) files to the staging area (does not include new files)

git add -u

Commit all staged files locally

git commit -m "commit message"
Open default editor to write a longer commit message

git commit

Push all local commits to repository

git push

git push origin <branch>
Pushes a local branch to the shared repository.

git push origin <branch>:<remote branch>
Pushes a local branch to the shared repository, with a different name remotely.

git push origin :<remote branch>
Deletes a remote branch.
Be careful doing this - someone else may be using that branch.

Push just one commit to repository (must be the first non-pushed commit)

git push origin <commit-hash>:master

Revert Changes

Replace uncommited changes with HEAD version of file

git checkout FILENAME

Replace all uncommited changes with HEAD version

git reset --hard

Rollback to a previous commit, while preserving changes made since that commit

git reset --soft HEAD~1
This example rolls back to commit "1 back from HEAD".
The changes that were staged for the next commit will be back in the staging area.
This effects the log - it will be like that commit never happened (I think provided you have not pushed it to the repository).

Rollback to a previous commit, while discarding changes made since that commit

git reset --hard HEAD~1

Branching

View list of local branches

git branch
"master" is the default branch.

git branch -r
"-r" means "remote". Lists all branches shared remotely.

git branch --set-upstream <LOCAL BRANCH> <REMOTE BRANCH>
Example: "git branch --set-upstream master origin/master"
Set the remote branch that your local branch mirrors. This must be set to use "pull".

Create a branch, but don't check it out yet

git branch <branch>
Branch from the HEAD.

git branch <branch> <commit hash>
Branch from a specific commit.

git branch -m <current branch name> <new name>
"-m" means "move". Renames a branch.

git branch -d <branch>
Delete a branch.
If the branch has not been merged into master yet, you'll get an error. Run "git branch -D <branch>" to force the delete.

Create a branch and check it out

git checkout -b <branch>

Switch branches

git checkout <branch>

Merge selected branch into current branch

git merge <branch-to-merge-in>
Example: "git merge origin/master" will merge master into current branch (pull master locally first)
If a merge is performed, it'll automatically make a new commit just for the merge edits.
If a fast-forward is all that you need (meaning you just caught up to current commits, no merging needed), there will be no extra commit made.
If there are merge conflicts, you'll get a message that you must fix the conflicts and then commit the result. You'll also need to delete any left-over *.orig files.

To fix merging conflicts, you'll need to edit each file individually, and look for the "<<<<<<<" or ">>>>>>>" lines. They delineate the conflict. Edit the file the way you want it and remove those delineation lines.
Or use mergetool:

git mergetool
This will open an easier-to-use tool to resolve the conflicts.
Some merge tools are kdiff3 and Beyond Compare.

View a log of all references HEAD has pointed at

git reflog
This can be used to find the hashcode for a committed branch that has been deleted, that you want back. Such dangling commits are only kept for 30 days.

Other

Temporarily move uncommitted edits out of the way

git stash
These changes will be stored in the stash, and local files will be rolled back to last commit.
I think you'd only need this if you are not branching for each work item.

git stash list
View a list of each stash you have.

git stash apply
Bring back the most recent stash. This stash will still appear in the list.

git stash pop
Brings back the most recent stash. This stash has been popped off the list.

git stash drop
Deletes the top stash on the list.

git stash branch <branch>
Move the top stash on the list to its own branch. The stash has been popped off the list.

Delete files

git clean -n
Displays a list of files that would be selected. Default to all untracked files.

git clean -f
Actually deletes those files.

Rebase the current HEAD onto another branch

git rebase master
Rebase prunes and moves a commit. It can make it appear that a commit was made on a different branch that it was. This can be used to avoid complex branching and merging trees in the log.
This example rebases the current branch onto "master".

Rebase example:

      A---B---C topic
     /
D---E---F---G master
From in the "topic" branch:

git rebase master
will result in

              A---B---C topic
             /
D---E---F---G master
You can similarly rebase a branch from master onto another branch.

To rebase through GitHub.com:
- Go to the branch or pull request page
- Click "Edit" to the right of the branch name
- Use the "base" drop down to select a new base
- Accept changes

Watch out for conflicting changes during a rebase. In case of merge conflicts, go through the same steps as normal to resolve the issues.
Instead of committing at the end, use:

git rebase --continue

Merge a single commit into current - JUST the changes in that one commit

git cherry-pick <hashcode>
This is not a rebase - it does not move or change that <hashcode> commit.
Git is smart enough that it will not, later, try to apply this commit a second time, even during a merge.

View a list of all the 'refs'
This will include all the 'head' refs at the top of the list

git show-ref

Ignore

The ".gitignore" file specifies patterns of filenames that Git will totally ignore. It will not list these files are new or edited, and will not add them to the staging area.

It is a text file, with one line per pattern.

Place this file in your repository root directory.

Relative Path

Select all files in a directory called "logs" anywhere in the repository.

logs/

Absolute Path

Select files based on absolute path rooted in repository's directory.

/logs/

Patterns

Asterisk (*) matches any string of any length.

/logs/*.txt
This selects all files ending in ".txt" in the "logs" directory.
Rename Repository

On the web:
1) Go to repository main page on Github website
2) Click Settings
3) Update Repository Name
4) Click Rename

On local computer:
1) Open GitShell
2) Navigate to the repository folder
3) "git remote set-url origin <new url>"
- example new url: "https://github.com/WithoutHaste/MyRepo.git"
4) Rename the repository folder to the new name
5) Open Git Desktop
6) Remove out of date folder from repository list
7) File > Add Local Repository > select the renamed folder
Installing Git

Windows
Mac OSX

Install with Home Brew

brew install git

Or download DMG package
[Here]

Linux

Debian and Ubuntu

apt-get install git-core

Fedora

yum install git-core
Configuration

Git has three configuration stores.

System Level

Applies to the entire computer.


git config --system
Located at /etc/gitconfig or C:\Program Files (x86)\Git\etc\gitconfig.

User Level

Applies when this user is logged in.


git config --global
Located at ~/.gitconfig or C:\Users\<NAME>\.gitconfig.

Repository Level

Applies to one repository.


git config
Located at .git/config in each repository.

Command Line

You can edit the config files directly in a text editor, or use the command line.

(Using the global level for the examples)

To list the config options

git config --global --list

To remove a setting

git config --global --unset <SETTING>

Set the username

git config --global user.name "John Doe"

Set the email

git config --global user.email "jdoe@gmail.com"

Set your default editor for editing commit messages, viewing diffs, etc

git config --global core.editor vim
Other options are emacs, notepad, and notepad++.

Enable fuzzy-matches of git commands

git config --global help.autocorrect 1
For example, "git statsu" would be interpreted as "git status".
The digit "1" says wait 1 millisecond before performing the action. Using "0" turns off autocorrect.

Allow git to use color-coding to help display diffs, etc

git config --global color.ui auto
This will not affect the output when Git is running a script (it would mess up your logs).

Set the Carriage-Return-Line-Feed option

git config --global core.autocrlf true
Possible settings:
- true: convert CRLF into just LF when checking in, and convert LF to CRLF when checking out on a Windows machine
- false: make no changes
- input: convert CRLF into just LF when checking in, keep it that way when checkint out
CRLF is common in Windows, but can cause problems on Mac or Linux.
"true" is recommended for Windows machines and "input" for Max or Linux machines.
This only affects text files, not binary files.

Alias a command

git config --global alias.<NAME> "log --oneline --graph --all --decorate"
Alias "command" to NAME.
The initial "git" in the command is not required.
See Commits By File

See that commits that affected one file. Does not track file renaming well (see "git log path").

Displays summary of each commit that affected the file.

git log --follow -- FileName
Click "space" to see more results.
Click "q" to exit the viewer.

Displays actual before/after edits for each commit that affected the file.

git log -p FileName

Suggested for when someone makes changes, but forgets where they made them.

git log --all --first-parent --remotes --reflog --author-date-order -- FileName

I've found "git log -p FileName" to be the most useful for finding when a particular edit was made.
GitHub

PR: Files Changes

To collapse all file details at once: Alt + mouse-click-to-collapse-one-file-details

Search

You can search all repos in one organization at a time.
- go to the organization's page, such as "github.com/Org"
- type into the "search or jump to" prompt
- the default search "org:Org" will auto fill

Search for text in files

org:Org mytext
You cannot search for these characters . , : ; / \ ` ' " = * ! ? # $ & + ^ | ~ < > ( ) { } [ ] @

Search by file extension

org:Org extension:csproj
org:Org extension:csproj mytext

I haven't found a sort option by repo, so the results can be really mixed up.

Problems

Cannot Delete Branch

Scenario:
In Git browser, I cannot click the delete "trashcan" on a branch because "a pull request depends on it".
No pull request depends on it.

Fix:
I can delete the branch through Git Desktop.

Follow Up:
It turns out there was a PR into that branch which I was unaware of. Deleting the branch automatically closed the PR.
It still stands that I was able to force the delete through Git Desktop.