Basic Git Usages

Working directory -add-> Stage (index) -commit-> History

History -reset-> Stage (index) -checkout-> Working directory

(i) initalizing a local git Repo

#make current dir a Git repo
$git init
#make a new dir a Git repo
$git init newrepo #git will create the dir auto
#uninit
$rm -rf .git/
#clone a local repo
$git clone /path/to/repo
#clone a remote repo
$git clone username@host:/path/to/repo

(ii) staging files

#add specific new files
$git add <file1> <file2>
#stage all files (current dir and all sub-dirs)
$git add .
#ignore certain files by modifying .gitignore
    ------------
    #.gitignore
    #Java class files
    *.class
    #object and archive files
    *.[oa]
    #temp sub-dir (end with '/')
    temp/
    ------------
$git add .gitignore

(ii) commiting files

#MUST first stage the changed files
$git add <file1> <file2>
#then, commit ALL files in staging area
$git commit -m "my commit"
#`git commit` does nothing unless u `git add`
#merge `add` and `commit` in one step
$git commit -a -m "my commit"
#or, just commit some files
$git commit -m "commit some" file1 file2

(iii) compare

#I locally changed the file, diff to last commit
$git diff <file>
#uh, I forget the diff bt historic commits
#HEAD is current, HEAD^^ is one before, HEAD~100 is 100 before
$git diff HEAD~1 HEAD <file> 
#or, use the SHA
$git diff aob2 4eac <file>

(iv) undo

#After commit, I made local changes, but the files 
#  are in a mess, I wanna discard all changes in working directory
$git checkout -- <file> #missing '--' will create a new branch
# --> if <file> has not been `add`, then it 
#  will be overwritten by last commit
#--> if<file> has been `add`, then I made more changes,
#  file will be replace by the stage file
----------
#I `git add` the file, but no `commit`; unstage it
$git reset HEAD <file> #counterpart of `git add <file>`

#changed local file, and also 'git add', sync to commit in 2 steps:
$git reset HEAD <file> #unstage
$git checkout -- <file> #replace

(v) rollback

#I wanna rollback <file> to specific commit
$git checkout <SHA> <file>
#now, I wanna back to specific commit
$git reset --hard HEAD^ #no HEAD in `log`
#but, I regret, I want HEAD back
$git reset --hard <SHA> #<SHA> is for orig HEAD
#forget <SHA> of orig HEAD, check cmd history
$git reflog
---------
#put <file> of HEAD^^^ to stage (same `log` result)
$git reset HEAD^^^ <file>
#diff it from current local file
$git diff --cached
#use it to overwrite local file
$git checkout -- <file>
---------
#oops, I made error, back to newest commit
#`hard` overwrites both working dir files and index
$git reset --hard HEAD^
$git reset --hard fa10
   (F)        (F)            (F)
A-B-C   ===> A-B    ===>    A-B-C
    ↑          ↑                ↑
#no hard, working dir files untouched, but index will be
$git reset HEAD^ #back to one before last commit
$git reset fa10 #back to orig HEAD
   (F)          (F)            (F)
A-B-C   ===> A-B-C  ===>    A-B-C
    ↑          ↑                ↑
#`soft` can even leave both files and index untouch
$git reset --soft HEAD^

(vi) remove

#removes the file from repo but also del it from local fs
$git rm  <file>
$git commit -m "remove file"
#remove file from repo and NOT del it from local fs
$git rm --cached <file>
#recovery
$git checkout -- <file> #see, works for both change and remove

(vii) amend

#if u made a commit but want to change the msg or 
#  adding more changes, amend the recent commit
$git commit -m "first commit"
#wanna to update the message
$git commit --amend -m "amend commit"
#realize that u have not staged some files
$git add <morefile>
$git commit --amend

(viii) log

#view current status
$git status
#view commit history
$git log [--pretty=oneline]
#view command history
$git reflog

(ix) branch

#it takes a long time to finish current revision, so I create a new branch to work on
#create branch <dev> and switch
#i.e., git branch dev
#      git checkout dev
$git checkout -b dev

#check current branch
# all branches will be listed, and the current one has a '*'
$git branch

#work on this branch
$git add <file>
$git commit -m "branch add"

#done on this branch, back to 'master'
$git checkout master

#merge 'dev' changes to 'master'
# default 'fast-forward' mode
$git merge dev

#delete 'dev' branch
$git branch -d dev

#if both branches have updates, coflict should be resolved
$git merge feature1 #CONFLICT (content): merge conflict in readme.txt
#check conflict info
$git status
#deal with the conflict, and then
$git add readme.txt
$git commit -m "conflict fixed"
#view the merge case
$git log --graph --pretty=oneline --abbrev-commit
#now, delete the branch
$git branch -d feature1

#when psbl, git merges in 'fast forward' fashion, where branches info would be lost when they are deleted
#forcefully disable 'fast forward', git will create a new commit
$git checkout -b dev
$git add readme.txt
$git commit -m "add merge"
$git checkout master
$git merge --no-ff -m "merge with no-ff" dev
$git log --graph --pretty=oneline --abbrev-commit

(x) remote repo

General workflow:

#ensure your local 'master' is up-to-date
#create a local branch
$git checkout master
#fetch the central repo's copy
$git fetch origin master
#rebasing your changes atop of them
$git rebase -i origin/master
#push commits on your local 'master' to the central repo
$git push origin master
#create a new repo on Github, pin_assem

#1) create a new local repo
$git init
$git add README.md
$git commit -m "first commit"
#relate to remote repo
$git remote add origin git@github.com:cinwell/pin_assem.git
#push local content (branch 'master') to the remote repo
#grammer: git push <remotename> <branchname>
#equivalent to:
# git push origin master
# git branch --set-upstream master origin/master
$git push -u origin master

#2) push an existing repo
$git remote add origin git@github.com:cinwell/pin_assem.git
$git push -u origin master

#afterwards, push newest commit in this way
$git push origin master

#push other branch
$git push origin dev
#list the remote connections you have to other repos
$git remote
#more detailed info
$git remote -v
#create a new conn to a remote repo
$git remote add <name> <url>
#remove the conn to the remote repo
$git remote rm <name>
#rename a remote repo
$git remote rename <old-name> <new-name>
#fetch all the branches from the repo
$git fetch <remote>
#only fetch the specified branch
$git fetch <remote> <branch>

$git fetch origin
#see what commits have been added to the upstream master
$git log --oneline master..origin/master
#approve the changes and merge them into you local master branch
$git checkout master
$git log origin/master
$git merge origin/master
#fetch the specified remote's copy of the current branch and immediately merge it into the local copy
$git pull <remote>
#instead of `git merge`, use `git rebase` to ensure a linear history by preventing unnecessary merge commits
#moves your local changes atop of what everyone else has already contributed
$git pull --rebase <remote>
#clone remote repo
#first create a new repo on Github
#then, clone to local
$git clone git@github.com:cinwell/pin_assem.git