2008年12月24日 星期三

Learning GIT


以一個初學者的角度
之所謂分散式,就是 做事在本地端做,但也能互相連結做更新


Add the following line to ~/.bashrc to select vi as the default editor:
export EDITOR=vi


Initial setting
git config --global user.name "Your Name Comes Here"
git config --global user.email you@yourdomain.example.com

git config --global color.diff auto;
git config --global color.status auto;
git config --global color.branch auto;

git config --global alias.r rebase;
git config --global alias.rc "rebase --continue";
git config --global alias.ra "rebase --abort";
git config --global alias.rk "rebase --skip";
git config --global alias.st status;
git config --global alias.bi bisect;
git config --global alias.br branch;
git config --global alias.ci commit;
git config --global alias.cia "commit --amend";
git config --global alias.co checkout;
git config --global alias.f fetch;
git config --global alias.cp cherry-pick;
git config --global alias.ap "add -p";

git config --global branch.autosetuprebase always;
git config --global core.autocrlf false

or Edit the file $HOME/.gitconfig
[user]
name = Your Name Comes Here
email = you@yourdomain.example.com

[color]
diff = auto
status = auto
branch = auto

[alias]
rb = rebase
st = status
bi = bisect
br = branch
ci = commit
co = checkout
ap = add -p

srb = svn rebase
sci = svn dcommit
pu = pull
pullr = pull --rebase
pur = pull --rebase
ps = push
[branch]autosetuprebase = always
Only You Can Prevent git Merge Commits
http://www.viget.com/extend/only-you-can-prevent-git-merge-commits/


git ignore
$GIT_DIR/info/exclude: 整個project的ignore設定
.gitignore: 每個目錄(及以下子目錄)的ignore設定


Remote Operation
git clone <remote_src>
git init

git remote add <remote_name> xxx@xxx:/xxx :新增一個remote設定
git push <remote_name> 將local改變"推"到遠端
git push <remote_name> --all :"推"在.git/refs/heads/下所有的東西
git push <remote_name> --mirror : 推"在.git/refs/下所有的東西 which means .git/ref/heads, .git/ref/remotes and .git/refs/tags/

git pull :"拉"(fetch+merge)

git pull -t :只有"拉"tag
git fetch --tags

Local Operation
git add/rm :告訴git哪些檔案要commit,這些檔案會先進入index。這個過程也叫作Staging
git commit -m "xxx" :只commit有add進index的東西

git commit -a -m "xxx" :commit所有曾經commit的檔案中有 被改變被刪除 的檔案 (add+commit)

git log
git log --all

git checkout <SHA1_code> :切換到某次的commit,you are on "no branch" after checkout
git checkout <tag_name> :切換到某個tag,you are on "no branch" after checkout
git checkout <branch_name> :切換到某個branch
git checkout -b <branch_name> :新增某個branch並切換到它上面

git diff
git merge

git reset
git reset --mixed
(--mixed is the default action)
git reset HEAD :把某個檔案移出index(staging)

git reset --hard :把working tree和index全恢復,即回到 原始狀態
git reset --soft :什麼都不動,但"requires them to be in a good order".....到底是要幹嘛用的阿...



Fixing mistakes
http://kernel.org/pub/software/scm/git/docs/user-manual.html#fixing-mistakes
Fixing a mistake with a new commit
git revert HEAD
Fixing a mistake by rewriting history
git commit --amend


(謎之聲: git是 大大 等級玩的東西,大大的想法不是凡人可以看透的,像這種地雷只有你這種凡人才踩的到啊)
(謎之聲: 你快點回去火星吧,地球是很危險滴!!!)

怎麼找出git中有沒有dangling commit?
現在似乎除了看reflog外沒有其他辦法,新版的git會有warning on dangling commit...

<mkl> Is there anyway to check if there is dangling commit in current database?
<mkl> git log --all or gitk --all won't show dangling commit
<Ilari> mkl: You could extract recent such commits from reflogs, but I don't know easy and fast way to cross-reference them with current branches...
<mkl> yes, reflog seems the only way to find the dangling commit, but only if you aware that there is one, and you have to dig into a long log full with hex code.....
<Ilari> mkl: Also, commit followed by checkout moving from something non-symbolic is pretty good indication that something left dangling.
<mkl> yes, but only if you do aware of the situation....
<mkl> and also commit followed by checkout from tag

<charon> mkl: newer git says which branch you committed on, and indicates a dangling commit with [detached HEAD]
<charon> mkl: 72c69ebc035 which is in 1.6.1
<mkl> Thanks charon, Ilari, drizzd, milli, I finally got the problem clearified and fixed....

detached HEAD explained
http://sitaramc.github.com/concepts/detached-head.html

另一個問題..
首先我回到過去的某個commit: git checkout XXXXXXX

結束後我要回到目前最新的commit
可是突然發現....我不知道它的hash codeㄟ....
當然,在我git checkout XXXXXXX時會show原來的hash code...
但是要是不知道的話要怎麼回到最新的commit呢
git log也看不到...
看來是我自己不知道怎麼搞的搞出了奇怪的狀況
最可能的是因為我用git checkout XXX在不同的commit間切換看code後
直接git checkout <SHA1 of newest commit>然後就改code/commit了
這樣的commit是上去了,但不是在branch上,變成所謂的dangling commit

dangling commit
those commits that is not pointed by any branch/HEAD/tag, and neither the ancestor of any commit pointed by any branch/HEAD/tag

而且dangling commit不會被push/fetch/pull to/from remote端。一個不小心,dangling commit就會消失了...

* 可以用git branch顯示目前所在的branch,改code前一定要切到某個branch下才能改;checkout 某個commit或tag 後,git branch會變成(no branch),這時候不要commit
# git branch
* (no branch)
  test


git branch :list所有的branch與目前HEAD所在的branch

git log --all
list 出所有的commit(但是似乎dangling commit不會被list出來)

git reflog
Reflog is a mechanism to record when the tip of branches are updated. This command is to manage the information recorded in it. 它會log所有的 commit和checkout

git branch -D <branch_name>: 刪除branch
git branch -m <branch_name1> <branch_name2>: 改branch name(branch_name1 -> branch_name2)

.git/HEAD: 目前的指向的位置
.git/refs/heads/<branch_name>: branch "branch_name"指向的位置
.git/refs/tags/<tag_name>: tag "tag_name"指向的位置

git cherry-pick <SHA1_code> :apply某個commit
git merge <branch_name> :與某個branch merge,或者說,apply某個branch的改變

gitk
gitk --all :顯示所有的branch(也不會顯示dangling commit)



一小時內搞懂 Git
http://people.debian.org.tw/~chihchun/2009/01/05/understand-git-in-one-hour/

git-talk
http://media.gitcasts.com/git-talk.flv


Slides
http://www.slideshare.net/chacon/getting-git

The Git Community Book
http://book.git-scm.com/
http://book.git-scm.com/book.pdf

git gc :garbage collection

不小心刪掉了某個檔案
在svn可以很簡單的svn up就抓回來了...
git該怎麼辦呢?

我想到的辦法是用git diff產生patch再 patch -R....但是我覺得這樣應該是很蠢的
git該有辦法回復吧?
  • git reset --hard
    把所有改變(data/index)回復,不過不能就單個檔案回復
  • git checkout [FILE]
    回復單一檔案data,像svn revert那樣
    但如果檔案的index已經改變則要先恢復index才能用

    但只是git checkout沒給任何檔案不會回復任何檔案
  • http://www.kernel.org/pub/software/scm/git/docs/git-stash.html
    git stash
    git stash list
    git stash apply
    git stash apply stash@{1}
    git stash clear

又..該檔案又被我git rm掉了
雖然還沒有commit...
但是我該怎麼回到原來的狀態呢.....
(任何index的改變)
git reset
git reset -- [filename]
可以回復index的改變,但僅止於index,實際檔案資料則不行


git-reset(1) Manual Page
http://www.kernel.org/pub/software/scm/git/docs/git-reset.html

Git - SVN Crash Course
http://git.or.cz/course/svn.html

gittutorial(7) Manual Page
http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html

GitWiki - QuickStart
http://git.or.cz/gitwiki/QuickStart

Rex's blah blah blah - Learning git
http://people.debian.org.tw/~chihchun/2008/08/20/learning-git/

Everyday GIT With 20 Commands Or So
http://www.kernel.org/pub/software/scm/git/docs/everyday.html

Git User's Manual (for version 1.5.3 or newer)
http://www.kernel.org/pub/software/scm/git/docs/user-manual.html

git-svn
http://asleepfromday.wordpress.com/2008/03/24/git-svn/

[Linux][軟體] Git-svn 使用簡單介紹
http://antontw.blogspot.com/2008/05/linux-git-svn.html

git-svn(1) Manual Page
http://www.kernel.org/pub/software/scm/git/docs/git-svn.html

3 則留言:

Harry 提到...

如果你的git夠新.... git stash 可以回到上個commit 的進度. (其實就是簡化過branch+checkout) ...


by 路人

mkl 提到...

感謝大大

昨天還覺的git有點難用
不過越用越覺得我的git之路越來越寬了呢

Harry 提到...

*我是小小*

剛好尋Trace32 on ubuntu 進來的
git reset 我比較常用 --soft, --hard 頗可怕XD

話說Trace32 debug 真是好用無比~.~
我的FreeRTOS如果沒有他 不知道該怎辦解bug