转自:(转自:http://www.360doc.com/content/10/0621/16/11192_34417725.shtml#)
用 Git 就是要愛用 Branch 啊,Branch 很好用,開 Branch 不用錢。開 Branch 的情境除了在上一篇中提到因應產品 release 需求的 stable/production branch 之外,其他開 branch 情況有:
- 帶有實驗性質的變更,例如想改寫新的演算法、重構程式碼等
- 新功能 feature 開發
- Bug fixes,你可能需要做些實驗才知道到底怎麼修
這些事情都可以先在本地開 local branch 做,而不需要立即 Push 分享給別人。
git branch <new_branch_name> 建立本地 local branch
git branch -m <old_name> <new_name> 改名字 (如果有同名會失敗,改用 -M 可以強制覆蓋)
git branch 列出目前有那些 branch 以及目前在那個 branch
git checkout <branch_name> 切換 branch (注意到如果你有檔案修改了卻還沒 commit,會不能切換 branch,解法稍後會談)
git checkout -b <new_branch_name> (<from_branch_name>) 本地建立 branch 並立即 checkout 切換過去
git branch -d <branch_name> 刪除 local branch
開 Branch 最大的好處除了可以不影響 stable 和其他分支版本的開發,另一個超棒的地方是”你可以決定 Merge 的方式”。Git 的 Merge 方式可以分成四種:
- Straight merge 預設的合併模式,會有全部的被合併的 branch commits 記錄加上一個 merge-commit,看線圖會有兩條 Parents 線,並保留所有 commit log。
- Squashed commit 壓縮成只有一個 merge-commit,不會有被合併的 log。SVN 的 merge 即是如此。
- cherry-pick 只合併指定的 commit
- rebase 變更 branch 的分支點:找到要合併的兩個 branch 的共同的祖先,然後先只用要被 merge 的 branch 來 commit 一遍,然後再用目前 branch 再 commit 上去。這方式僅適合還沒分享給別人的 local branch,因為等於砍掉重練 commit log。
其中 rebase 比較難理解會在下一篇再詳述:
git merge <branch_name> 合併另一個 branch,若沒有 conflict 衝突會直接 commit。若需要解決衝突則會再多一個 commit。
git merge --squash <branch_name> 將另一個 branch 的 commit 合併為一筆,特別適合需要做實驗的 fixes bug 或 new feature,最後只留結果。合併完不會幫你先 commit。
git cherry-pick 321d76f 只合併特定其中一個 commit。如果要合併多個,可以加上 -n 指令就不會先幫你 commit,這樣可以多 pick幾個要合併的 commit,最後再 git commit 即可。
使用 merge 可能會有部分程式碼會 conflict 衝突:簡單的情況只要編輯檔案處理 <<<< ===== >>>>> 即可,然後重新 add 到 staging area 並 commit (沒有像 SVN 的 resolve 指令)。複雜一點的可以再用 git mergetool 選檔案合併的 GUI 工具 (OS X 下面可以用 opendiff, linux 可以用 kdiff3 ),處理好後 git commit。
一旦 merge 好了,git branch -d <branch_name> 可以刪除 branch。但如果要刪除的 branch 還沒有合併,就會有錯誤訊息。如果真的要強制刪除可以用 -D
Git 的 working tree 是從 SVN 換過來一個不習慣的地方,因為它只是一個工作暫存區,在切換 Branch 時就會整個換掉。也因為如此,如果有檔案有修改還沒有 commit 出去,切換 branch 時就會出現 error 不能切換 (除非是新的 untracking 檔案),例如有修改還沒 add 會出現 error: Entry 'ooxx’ not uptodate. Cannot merge. 有修改且已經add(還沒ci)會出現 error: Entry 'ooxx’ would be overwritten by merge. Cannot merge.
最理想的處理當然是事情剛好做到一個段落,把東西 commit 出去才切換 branch 做事。不過事情總有臨時,如果要換 branch 的暫時的解決方式是使用 git stash 會先把修改暫存下來,要回復則執行 git stash pop。下一篇等你學會 git reset 之後,你會發現就算把還沒完成的東西 commit 也不會怎麼樣,只要還沒 push 出去一切 commit 紀錄都是可以改的。
创建远程项目仓库
-
登录到服务器, 寻找合适位置, 建立 test.git 目录. 然后初始化一个空仓库, 以此作为服务器上的主仓库.
git --bare init --shared
git-init 命令的 --bare 选项可以让 test.git 目录等价于一个仓 库. 也就是说, test.git 本来是一个工作树, 但是 --bare 选项将本应当存放在 test.git/.git 中的仓库内容全部放置在 test.git 目录下, 就好像仓库完全的裸露在工作树中, 所以称之为赤裸的仓库.
-
将自己机器上已经接受 Git 管理的仓库推送到刚刚建立的远程仓库.
git push user@somewhere:~/path/test.git master
-
此时, 所有人就可以通过 git-clone 命令在本地创建工作目录
git clone user@somewhere:~/path/test.git
协同开发流程
服务器上已经建立了 Test 仓库. 现在以一位开发人员的角度熟悉一下一天的工作流程.
-
首先, 需要更新自己机器上的工作树, 并查看其他成员的版本更新信息.
git pull git log
-
在本地建立一个新的项目分支, 如 develop 并将当前分支切换为该分支.
git branch develop git checkout develop
-
好了, 现在就能在自己建立的项目分支上完成开发工作了. 一天的工作完成后, 有必要将这一天的工作与 Test 仓库的 master 分支进行合并, 然后删除 develop 分支.
git checkout git merge develop git branch -d develop
-
这样, 开发人员就已经将这一天的工作反应到自己机器上的 Test master 分支上了. 如果还需要推送到远程仓库, 需要注意, 在推送版本更新之前, 需要使用 git-pull 命令将这一天其他成员对服务器端的更新拉过来合并到自己的 master 分支, 然后才能将自己的版本更新推送出去.
在个人开发时新建一个分支, 能较好地避免因个人操作不当而导致向服务器提交太多的脏数据. 另外, 也有效保持了本地项目的干净, 避免频繁 git-clone 服务器端的仓库来恢复本地的项目分支.