Git logo

How To Be Git!

i m catalog.

安裝 git-core

install git-core on ubuntu

$ sudo apt-get install git-core

設定

使用 git 第一步是設定你的 user name 跟 user email

$ git config --global user.name "nyo"
$ git config --global user.email "nyo@mail.com"

設定檔會在 ~/.gitconfig
或者可以下指令看

$ git config -l

設定顯示顏色

$ git config --global color.diff auto
$ git config --global color.status auto
$ git config --global color.branch auto
$ git config --global color.log auto

# 自訂 log 格式到 lg,當然你也可以定義其他 alias

$ git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative"

設定 commit 時,使用的編輯器
預設是用系統預設的編輯器或者是 vi

$ git config --global core.editor vim

設定你想用於處理 conflict 的 tools

$ git config --global merge.tool gvimdiff

為專案建立 Repository

假設專案的資料夾為 project

$ cd project/
$ git init

git 會建立一個 .git 的資料夾,所有 repository 所需要的資料都在裡面

接著將要讓 git 追蹤的檔案加入

$ git add .
(. 指目前所在的目錄,當然也可以指定檔案)

最後輸入 commit 指令,把資料 commit

$ git commit

輸入指令後會進入編輯器,為目前的資料變動加上說明
存檔後此次 commit 的資料就會加入 repository 中

複製一份 Repository

以 git clone 的指令把其他地方的 repository 複製到你目前的工作目錄下
可以用 git://, http(s)://, ssh:// 從網路複製,或直接從電腦中的其他資料夾複製

$ git clone ssh://username@url/<路徑>
$ git clone <資料路徑>

clone 完成後,來源的網址會存到 config 中的 remote origin 中

建立新的 branch,編輯,然後送回原位子

開一個新的 branch newBranch

$ git branch newBranch
$ git branch newBranch v2.5 # newBranch based at v2.5

如果你是跑

$ git branch

會看目前你擁有的 branch ,有*的是目前所在的 branch

其他 branch 參數

$ git branch -d <branch> #刪除 branch
$ git branch -r #列出所有的 remote branch
$ git branch -a #列出所有的 branch

切換到新的 branch

$ git checkout newBranch

現在在新的 branch 上做任何修改都不會動到原本 master 上的資料了

修改創作完成後,就是要把修改的內容 commit 到 repository

# 加入新增的檔案(如果有的話)
$ git add <檔案>
# commit 全部修改的資料
$ git commit -a

或者是

$ git add -u #stage 修改的資料
$ git commit

切換到 master

$ git checkout master

再來要把資料 merge 並送回 origin,但是在那之前要先確定有沒有其他人 push 資料上去

$ git pull [origin] [remote branch name]

事實上 pull 等於 fetch 新的資料並 merge 進local branch

更新完 master 後,將 master 和 newBranch merge 起來

$ git merge newBranch

merge 時如果有 conflict 時,conflict 的部份會有<<<< ==== >>>>
只要將 conflict 的部份修改再 commit 即可完成 merge 動作

最後將 master push 到 remote repository 工作就告一段落了

# push all branch
$ git push origin
$ git push <remote>
$ git push <remote> <local branch>:<remote branch>

沒辦法 push master?
修改 remote 的 git config

$ git config receive.denyCurrentBranch=ignore

關於 Commit

自動 stage 已修改或刪除的檔案,但是對新增的檔案沒有作用

$ git commit -a

直接使用 "message" 當 commit message

$ git commit -m "message"

commit 指定的 file,已 stage 的資料不會被 commit 依舊是 staged

$ git commit <file>

修改當前 branch 最近一次的 commit

$ git commit --amend

想要只 commit 部份的變動,可用以下指令,進入 Interactive mode

$ git add -i

關於 Reset

working tree: 當前的工作資料 (unstage)
HEAD: 目前所在的 commit (staging area)
index: 儲存的 commit 資料 (repository)

reset 後,原本的 HEAD 會存到 ORIG_HEAD

reset HEAD 跟 index 到指定的 commit 而 working tree 不會變動

$ git reset HEAD

reset HEAD 到指定的 commit

$ git reset --soft HEAD
$ git reset --soft HEAD^ # HEAD 的前一個 commit
$ git reset --soft HEAD~3 # HEAD 的前三個 commit

reset HEAD, index, working tree 到指定的 commit

$ git reset --hard HEAD

關於 Cherry-pick

要將已存在的 commit 拿來使用

$ git cherry-pick <commit>
$ git cherry-pick -n <commit> #只套用該 commit 的變動,不會 commit 出去

關於 Tag

commit 的編碼都很亂,加個 tag 很方便

$ git tag <tagname> #為目前的 commit 加上 tag
$ git tag <tagname> <commit> #為指定的 commit 加上 tag
$ git tag -d <tagname> #刪除 tag

關於 Merge

假設當下所在的 branch 是 master

          A---B---C topic
         /
    D---E---F---G master

$ git merge topic

topic 裡從 master 分支出來後的 commit(A, B, C) 會合到 master 並用一個新的 commit 加以記錄

          A---B---C topic
         /         \
    D---E---F---G---H master

merge 時如果有 conflict 時,conflict 的部份會有<<<< ==== >>>>
只要將 conflict 的部份修改再 commit 即可完成 merge 動作

加上 --no-commit 執行 merge 不會自動 commit ,你可以在 commmit 前修改 merge 結果

$ git merge --no-commit <commit>

關於 Rebase

rebase 的基本用法:
假設當下所在的 branch 是 topic

          A---B---C topic
         /
    D---E---F---G master

用以下指令:

$ get rebase master
$ git rebase master topic

                  A'--B'--C' topic
                 /
    D---E---F---G master

rebase --onto 的用法:
假設目前的 commit tree 是:

    o---o---o---o---o  master
         \
          o---o---o---o---o  next
                           \
                            o---o---o  topic

想要把 topic 跟 master merge 但是又不要有 next 的資料

$ git rebase --onto master next topic

    o---o---o---o---o  master
        |            \
        |             o'--o'--o'  topic
         \
          o---o---o---o---o  next

rebase 還可以移除 commit

    E---F---G---H---I---J  topicA

$ git rebase --onto topicA~5 topicA~3 topicA

F 跟 G 就被刪掉了

    E---H'---I'---J'  topicA

rebase 的時候遇到 conflict 時,
git rebase 會停在第一個有問題的 commit 並在 working tree 裡 mark conflict
修正完 coflict 後再以 git-add 告知 git conflict 解除了
再下指令繼續 rebase

$ git rebase --continue

或者想要取消 rebase 動作

$ git rebase --abort

關於 Stash

當你程式改到一半,還不打算 commit 修改的資料,但是又想要對 repository 有所動作時,就是用 stash 了
將修改的資料先暫存起來,並回復到 HEAD 的狀態

$ git stash

取出一筆記錄,並從 stash list 中移除,不指定 stash 的話預設會是 stash@{0}

$ git stash pop [<stash>]

取出一筆記錄,但不移除

$ git stash apply [<stash>]

顯示該筆 stash 的修改記錄

$ git stash show [-p] [<stash>]

列出暫存區裡的所有資料

$ git stash list

清空 stash list

$ git stash clear

從指定的 stash 所在的 commit 建立並切換到一個新的 branch,並將 stash 的記錄套用到新的 working tree。
成功執行後,該 stash 資料將被 drop

$ git stash branch <branchname> [<stash>]

其他指令

$ git diff # 比較 commit 之間的差異
$ git difftool
$ git show
$ git log
$ git status # 查看 working tree 的狀態
$ git grep
$ git rm # 從 working tree 跟 index 中刪除檔案
$ git mv # 移動或重新命名
$ git svn # svn tool for git