Notes on git + github

I've been using SVN for quite a long time. Recently, started using git and github and really like it! I still need to take notes on some commands so this is what this post is about.
There is an excellent book but is too long to get it every time I need something. So here, I summarize what I believe are the most important/frequent things.


Download the installer from here or use MacPorts or Homebrew and issue:
# for MacPorts
$ sudo port install git-core +svn +doc +bash_completion +gitweb
# for Homebrew
$ brew install git-core


Required configuration:
$ git config --global user.name "firstname lastname" 
$ git config --global user.email nacho4d@nacho4d.com
Specially when working with github, these strings must be the same strings as the ones appearing in github Settings
Optional configurations that I find handy
$ git config --global core.editor emacs
$ git config --global merge.tool vimdiff
$ git config --global color.ui true 
$ git config format.pretty oneline

To see settings inside /etc/gitconfig and ~/.gitconfig do:
$ git config --list

Creating a repo from scratch

$ cd My/LocalRepo/Directory/
$ git init
$ git add *.m 
$ git add README.txt 
$ git commit -m 'This is the message for the first commit'

Creating a remote repo in github

Follow the instructions in github.
(**Warning**: Github needs a README file to show the project correctly on the web. Make sure you have one)

Cloning a repo from github

Get the address of the repo from github and enter like so:
$ git clone git://github.com/schacon/grit.git

File lifecycle

Explaining the lifecycle is not easy (specially if you come from SVN). But I think below explanation is not incorrect :)
  • Untracked: when a file is not version controlled by git
  • Unmodified: when the file is controlled by git and is not modified since the last staging
  • Modified: when the files is controlled by git and it was modified since the last staging
  • Stagged: when the file is in the index, git commit only commits stagged files

Staging a file:

The add command also is for staging not only for tracking files
$ git add filename.txt
$ git status

Ignoring file:

$ cat .gitignore 
*.[oa]     #ignores .o and .a files
*~         #ignores files that end in ~
build/     #ignores build directory
doc/*.txt  #ignores txt files inside of doc directory, is not recursive
(Glob patterns are accepted)

Seeing stagged and unstagged changes
$ git status
$ git diff
$ git diff --cached
$ git diff --stagged


$ git commit
and enter the message in the editor. Or:
$ git commit -m "message for this commit" 
Or: just commit everything (including not staged files)
$ git commit -a -m "message for my commit with -a option"

If a file was forgotten you can always amend current staged files to the last commit
$ git add forgotten_file.txt 
$ git commit --amend
# and to change the commuter date too:
$ GIT_COMMITTER_DATE="`date`" git commit --amend --date "`date`"

Removing files

$ rm fileToRemove.txt
$ git rm fileToRemove.txt
and remove a file only from the stagged are
$ git rm --cached readme.txt

Working with Branches

# list of local branches
$ git branch

# list of all (local and remote) branches
$ git branch -a

# list of remote branches only
$ git branch -r
Create a local branch named uiFixes (from current branch). Then rename it to ui-fixes, check it out, commit something to it, publish it and finally delete it from the remote
$ git branch uiFixes
$ git branch -m uiFixes ui-fixes
$ git branch ui-fixes
$ git checkout ui-fixes
$ git branch
... some changes happened here ...
$ git commit -am "fixes where done"
$ git push origin ui-fixes
... now others can see/use/merge,etc this branch
$ git push origin :ui-fixes


Create a tag v1.0 and push it to the remote. Then push all tags.
Delete tag v1.0 from local repository and finally delete it from the remote.
If a branch is not merged it cannot be deleted so in that case you can force it with -D option
$ git tag v1.0
$ git push origin v1.0          
$ git push --tags               
$ git tag -d v1.0
$ git push origin :refs/tags/v1.0

Renaming a branch:
Create a new tag with that references to the old tag then delete the old one.
# create the new tag
$ git tag new_tag old_tag
# delete the old tag locally
$ git tag -d old_tag
# delete the old tag from the remote
$ git push origin :refs/tags/old_tag

Checking out a tag:
# Create a branch and checkout
git checkout -b 1.6 refs/tags/v1.6
# Just checkout out the tag
# (Useful when looking at it and no changes are planned to be done)
$ git checkout refs/tags/v1.6


Shows a list of commits:
# Show last 10 commits
$ git log -n 10

# Show commits with a graph
$ git log --graph

# Compact 
# git log --graph --pretty=oneline --abbrev-commit


compare a file with current HEAD
$ git diff file.h


# stash current changes without a label
$ git stash
# stash current changes with a label
$ git stash save "Put a message here"
# stash only unstaged (or non-added) changes
# Note that newly created (and non-added) files will remain in
# your working directory. Also, your working directory must be
# clean (i.e. all changes need to be added) when you `git stash
# pop` later on.
$ git stash -k

$ ...

# list of all stashed things
$ git stash list
# will show something similar to:
stash@{0}: On feature/52: Put a message here
$ ...

# Apply the stash to the current branch
$ git stash apply 
# Apply and remove it from the stash list
$ git stash pop

$ git stash clear


# show info about remote branches
$ git remote show origin
# export last commit in the current branch
$ git archive -o latest.zip HEAD


# interactively rebase (change/modify) the last 4 commits:
$ git rebase -i HEAD~4

# Mainly I use it for:
# "squash" various commits in a single one
# "reword" the message of the commit

# forced push of a branch (not merging)
$ git push origin feature/new-feature -f


# Make a patch of a certain commit:
$ git format-patch <SHA>^..<SHA>
# It will create a file, let's say: file.path.

# Check the changes that are in the path:
$ git apply --stat file.path

# Apply the patch
$ git apply file.path
# or
$ git am file.path

Update your fork from Original repo

# Add (additional) remote
$ git remote add --track master mleung git://github.com/mleung/feather.git
# 'master' is the tracking branch and 'mleung' is the tracked branch from the given repo

# verify 
$ git remote

# get lattest changes from mleung
$ git fetch mleung

# merge those changes (mleung/master) into your current branch
$ git merge mleung/master

Gitflow, etc

# check out "develop" remote branch and then start git flow
$ git fetch
$ git checkout -t origin/develop
$ git branch

# initialize git flow
$ git flow init

# publish and track "develop" manually
$ git push origin develop
$ git branch --set-upstream develop origin/develop
$ git remote show origin

# feature start and finish
$ git flow feature start markdown-links
$ git commit -am "markdown now shows links in blue color"
$ git flow finish markdown-links

# hotfix start and finish
$ git flow hotfix start my-hotfix
$ git commit -am "I have solved a really serious bug"
$ git flow hotfix finish my-hotfix


creating and merging local branches (?)
merging and pushing to remote repository (?)
git merge (?) not only to master branch but to any branch
git revert (?) to any point in the past
git reset (?)
git remote (?)
git help **commmand**(?)