Contents

Concepts

The main git objects are commits, trees and blobs. A git repository (repo) is a list of commits. A commit consists of a tree which in turn consists of blobs.

find ./.git/object -type f | sort

Each object is referenced by first 6-7 digits/letters of it's hash. The directory name under .git/object is part of the hash name. For instance

./.git/objects/46/3c1628ca10b51cab62ef3983f9e15119db56bc  // hash is 463c16...

View the type of object using:

git cat-file -t <hash> // outputs blob, tree or commit

blobs

A blob is the SHA1 hash of the file contents.

git hash-object <filename|dirname>
git cat-file blob <blob_hash> // outputs file contents
git ls-files

trees

A tree is a collection of blobs

git ls-tree [-r]  <commit_hash> // lists the blobs and sub-trees (-r recurses into subtrees) in the tree associated with commit_hash

commits

A commit is a snapshot of a working tree at some point in time.

HEAD defines what's currently checked out.

git rev-parse HEAD // outputs the hash of HEAD
git rev-list --all <--header> // list all commits in all branches --header for details about commit
git rev-list --max-count=2 <commit> // list the commit and it's parent
branch

A branch is a named reference to a commit.

git branch -v // lists branches in repository
git branch b1 // creates a new branch called b1
git checkout b1 // switches to branch b1

If you checkout a previous commit (which isn't a branch), make some changes and commit, that commit is considered detached from HEAD and will be lost unless you convert that commit to a branch:

git checkout -b b11

git show-branch

config

git config -l
git config --global user.name "Firstname Lastname"
git config --global user.email "email@gmail.com"
git config --global github.user github_username
git config --global github.token <token>
git config --global --unset credential.helper

github config

ssh-keygen -t rsa -C 'email' pwd 
// Copy contents of id_rsa.pub to github
mv ~/.ssh/id_rsa ~/.ssh/github_rsa
mv ~/.ssh/id_rsa.pub ~/.ssh/github_rsa.pub
ssh-agent s
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/github_rsa
ssh -T git@githhub.com

workflow

git init [project-name] OR
cd directory
git init
git status
git diff
git diff --staged
git diff HEAD
git diff --color-words

Typical workflows always begin with a branch, no matter how small or grand the level of effort might be or the number of commits involved.

git branch    // list branches, identify current branch
git branch [name] // create a new branch from current branch
git checkout [name] // switch to a different branch
git branch -m [current-name] [new-name] // rename any branch
git branch -d [name] // delete a *reachable* branch
git branch -D [name] // delete whether or not reachable
git merge [branch] // the final step to bringing the history of a branch into the current one is performed by merging it. Integrate history of specified branch into current one

git add <filename>     // -u adds all files which have been updated
git add .
git add -u             // update already tracked files
git reset <filename>   // undoes add for single file
git reset              // unstages all files which have been added
git commit -m "message"
git remote add origin git@github.com:github-user/repo.git
git push <origin> <master> // origin is remote repo master branch

Can include some more changes to previous commit.

git add -u
git commit --amend

Can (force) push amended commit to remote.

git push -f fork [branch]

rebase

git checkout b1
git rebase <commit_hash> // rebases the point where b1 branches to <commit_hash>

stash

git stash                // same as "git stash save" stashes away changes without adding to index or committing 
git stash save "message" // 
git stash list           // lists blobs in stash
git apply|pop <stash_ref>// pops 

git diff --name-only da8152d 2032f7 // get changed filenames between 2 commits
git diff da8152d 2032f7 -- filename // get diffs between same file across 2 commits

git diff stash@{0}^1 stash@{0} -- <filename> // diff between stash and stash's parent (commit at which changes were stashed away)
git diff stash@{0}^! -- <filename> // cryptic version of above
git checkout stash@{0} -- <filename> // checkout single file out of stash
git show stash@{0}:<full filename>  >  <newfile> // save file from stash as new file
git show stash@{0}:./<relative filename> > <newfile> // same as above

git rm -r --cached <dir> //removes from git index - doesn't delete from file system
git rm -r -n dir/   // -n to only simulate -r for recursive removal. doesn't delete from file system
git clean dir/     // deletes from file system altogether

log

git log
git log -- <filename> // lists commits with changes to a file
git ref log // git can look back at the history of each commit to see when a change took place, who made the change, or what the change contained. Some simple option flag additions to the log command can make the output more concise.
git log --oneline // simple commit summaries
git log --patch --color-words // if displaying the full contents of the change and word-level comparisons are helpful, there are option switches for that too. Option switches common with `diff`

reset

git reset --soft HEAD^
git reset --hard      // get rid of all changes made since last commit / checkout - use sparingly
git reset --hard <commit> // Resets the index and working tree. Any changes to tracked files in the working tree since <commit> are discarded.
git reset HEAD <file>... // unstages <file>
git checkout -- <file> // re-instates <file> after git rm <file>, i.e. discards changes in working directory, the -- is merely a separator

Following allows splitting of an ammended commit into 2 separate commits.

git reset --soft HEAD@{1}
git commit -C HEAD@{1}

filter-branch may be used to remove a file and all its history from index. Deletes file from working directory and edits/renames commit hashes and tags. Useful to remove files with sensitive information inadvertently added to repo.

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch run_confo_server.sh" --prune-empty --tag-name-filter cat -- --all

syncing with upstream

git clone https://github.com/tortuoise/pelican-themes
git remote -v //lists remote repos
  * origin  https://github.com/tortuoise/pelican-themes (fetch)
  * origin  https://github.com/tortuoise/pelican-themes (push)
git remote add upstream https://github.com/getpelican/pelican-themes.git
  * upstream        https://github.com/getpelican/pelican-themes.git (fetch)
  * upstream        https://github.com/getpelican/pelican-themes.git (push)
git fetch upstream
git checkout master // presumably origin master
git reset --hard //get rid of all local uncommitted changes
git merge upstream/master //merges with upstream/master
git push origin master //pushes origin/master

subtree

git subtree add --prefix=_vendor/github.com/gohugoio/gohugoioTheme/ git@github.com:/gohugoio/gohugoioTheme.git --squash

modules

gothas

Error encountered while cloning:

git clone https://github.com/hashicorp/vault
error: RPC failed; curl 56 GnuTLS recv error (-9): A TLS packet with unexpected length was received.
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
package github.com/hashicorp/vault: exit status 128

For more verbose output try:

GIT_CURL_VERBOSE=1 git clone https://github.com/hashicorp/vault
* GnuTLS recv error (-110): The TLS connection was non-properly terminated.816/103039), 19.32 MiB | 1.38 MiB/s
* stopped the pause stream!
* Closing connection 0
error: RPC failed; curl 56 GnuTLS recv error (-110): The TLS connection was non-properly terminated.
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed

Try the following before re-cloning:

git config --global http.postBuffer 1048576000

The below will clone the master branch. See ref to pull other branches.

mkdir -p $GOPATH/src/github.com/hashicorp
cd $GOPATH/src/github.com/hashicorp
git clone --depth 1
cd vault
git fetch --unshallow
git pull --all

References