IF 'git push -u origin master' failed, run this command first:
'git pull git@github.com:user/repository.git'
文章来源:http://tkg.im.ncue.edu.tw/?p=755
*** last update: 2010.11.30 ***
*** refer to: http://zx-1986.blogspot.com/2010/08/git-manual.html ***
Git()是一套分散式的版本管理系統。
類似 SVN(Subversion)或 CVS(Concurrent Version System)對程式碼或文件進行管理。
Git 的概念很單純,想像一下:
你的書櫃裡有許多書,偶而有新書進來,有舊書捐出去。
有時候你還會在某些書上作筆記、寫心得、畫畫。
你在書櫃的側邊貼上一張「大大的白紙」,對書櫃裡的所有變動作紀錄。
紀錄新書擺入的時間,擺放的位置,甚至後面加個註記:『購於網路拍賣』;
紀錄舊書清除的時間,原本的位置,加個註記:『oh,好捨不得』;
紀錄某書寫入筆記的時間,什麼樣的筆記,心得或隨手塗鴉;
紀錄……
當然很少人會這麼費工書寫自己書櫃的變遷歷史。
但這張書櫃側邊貼著的「大大白紙」就類似於 Git,而且 Git 會做得更鉅細靡遺。
當你對一個資料夾啟用 Git 進行追蹤管理與控制時(其實就是 Git 初始化),
Git 程式會在該資料夾底下新增一個名為「.git」的隱藏資料夾。
「.git」類似於前面提到那張「大大的白紙」,裡面紀錄了檔案的變化史。
「.git」會對該資料夾內所有的檔案與其底層的所有資料夾進行紀錄追蹤。
不過,Git 並不會主動、自動紀錄,必須靠使用者操作。使用者類似於史官的角色。
當然,Git 的背後的運作方式更為聰明而且複雜。
Git 的功能不僅僅如此。
團隊合作時,同樣一個文件,在你手上跟在他人手上,可能有不一樣的變化史。
當你的檔案要與他人的合併時,內容有出入的地方,Git 會協助進行處理。
(例如開發同一個程式,你寫的 code 可能被他人改動到,或反之。)
Git 還有其他許多功能與應用,請慢慢挖掘。
*
建議先執行以下指令,將系統預設編輯器選擇為 Vim:
sudo update-alternatives --config editor |
*
Ubuntu 底下安裝 Git 非常簡單,只要在終端機執行:
sudo apt-get install git-core git-doc |
[ 註:亦可以使用 tarball 進行安裝。]
每個使用者帳號都會有它自己的 Git 設定檔,通常是:
~/.gitconfig 例如我的設定檔內容是:
設定完成後可以開一個新的資料夾進行練習。
設計上 Git 不會把空的資料夾加入控管。
建議可以在空的資料夾底下建立一個隱藏檔,例如:.gitignore
執行以下指令產生 .gitignore:
.gitignore 可以寫入「不希望被 Git 控管的檔案」,例如:
執行以下指令初始化 Git(資料夾內會多出一個名為 .git 的隱藏資料夾):
之後只要每次修改或新增檔案後,執行以下兩個指令,Git 就會做一次紀錄:
git add . git commit -a -m '關於此次修改的描述訊息' |
好了,您已經開始在使用 Git 啦!
*
執行:
git 會顯示常用的 Git 指令與參數,例如:
在整個 Git 指令後面加上 -h 參數,能夠查詢該指令可以附加哪些參數,例如:
要查詢完整的指令手冊,可以執行:
*
【關於 Git Repository】
一個被 Git 所追蹤管理的專案,稱為一個 Git Repository(倉儲)。
Git Repository 裡預設的 Trunk(主幹)稱為「master」,
Git Repository 裡其他的 Branch(分支)則由使用者命名。
Git 是一個分散式的版本控制系統,不同於 SVN 傳統的 Server/Client 架構。
Git 不需要像 SVN 必須有一個 Repository Server 作為主要的儲存倉儲。
Git 只要安裝好,預設就可以使用 ssh 互相進行 Repository 傳輸了。
當使用 git clone 指令從遠端複製一個 Git Repository 到本地端電腦上時,
遠端的 Git Repository 通常稱為「origin」;
本地端的 Git Repository 則沒有特殊的名稱(或許可稱為「Local Trunk」?)。
*
一般應用情形是這樣:
假設遠端的電腦叫做 Remote;本地端的電腦叫做 Local。
Remote 上面有一個 Git Repository 資料夾叫做 remote_repository。
要將 remote_repository 整個複製到 Local 上並命名為 local_repository,在 Local 上執行:
Local$ git clone 「Remote 使用者帳號@Remote 位址」:「remote_repository 在 Remote 上的路徑」 local_repository |
複製完成(git clone)後,Local 與 Remote 已經可以分開獨立工作了。
Git 不必拘泥於一定要把修改過的檔案更新存回當初取得檔案的地方。
Remote 可以在 remote_repository 裡發展它的檔案;
Local 可以在 local_repository 裡發展它的檔案。
等到哪天 Remote 突然想取得並合併 Local 發展的檔案,可以在 Remote 上執行:
Remote$ git pull 「Local 使用者帳號@Local 位址」:「local_repository 在 Local 上的路徑」 |
當然,如果 Local 想取得與合併其他人發展的檔案,可以在 Local 上執行:
Local$ git pull 「使用者帳號@位址」:「路徑」 |
#特別說明
git pull – Fetch from and merge with another repository or a local branch
git fetch – Download objects and refs from another repository
官方文件對這兩個指令是這般解釋的,看起來似乎是「git pull」會多進行一項合併的動作。
簡單說,「git pull」其實等於先執行了「git fetch」,然後再自動執行「git merge」。
有人建議少用「git pull」,多用「git fetch」然後「git merge」,請見 Reference 05。
透過底下這張圖可以稍微了解一下 Local 與 Remote 間的關係:
上圖中間黃色部份的「Staging Area」工作階段是一個緩衝地帶,
它讓只有被 add 過的東西,才可以被 commit。
可以直接觀察下圖了解其間的關係:
*
【SVN 式的往日時光】
之前,我在不同的電腦上修改程式,有可能是研究室的電腦、宿舍的電腦或筆記型電腦。
所以我在研究室的一台主機上架了 SVN 伺服器,程式主要版本儲存在 SVN 伺服器上。
每當在不同的電腦進行程式編輯時,會先從 SVN 伺服器上抓最新版本的程式下來。
編輯告一段落後,再把修改過的程式上傳回 SVN 伺服器。
簡單而言,程式集中在一台 SVN 伺服器上,要編輯時從上面更新下來,編輯完再更新回去。
像我這種從 SVN 轉換到 Git 的使用者,還很習慣於從前 SVN 那種模式:
1] 使用 svn checkout 從 SVN 伺服器將整個 Repository 複製到本機端。
2] 本機端對 Repository 的內容進行編輯、修改、新增、刪除等等。
3] 使用 svn update 檢查 SVN 伺服器有沒有其他更新與自己修改的內容有衝突。
4] 解決內容衝突的情況。
5] 使用 svn commit 將自己本機端的所有修改上傳到 SVN 伺服器。
怎麼用 Git 做到類似 SVN 那樣的情形?
有個簡單的方法。
首先,選定一台要當 Repository Server 的機器,假設叫 Server。
在 Server 開一個空的資料夾,假設叫 origin,並切換到該資料夾下。
在空資料夾底下執行:
該資料夾底下會產生以下檔案與資料夾:
本地端的電腦,假設叫 Local。
Local 上一個叫 local_project 的資料夾要上傳到 Server 進行統一管理。
切換到該資料夾底下,執行:
Local$ git commit -a -m 'initialization' Local$ git remote add origin 「Server 使用者帳號@Server 位址」:「Server 上 origin 資料夾的路徑」 |
Local$ git push origin master |
從 Server 上的 origin 複製 local_project 的內容: |
Other$ git clone 「Server 使用者帳號@Server 位址」:「Server 上 origin 資料夾的路徑」 「自訂的資料夾名稱」 |
其他電腦要將其修改的內容傳回 Server,可以使用:
Other$ git push origin master |
*
【Git Repository Hosting】
Git Repository 還可以使用 http 等其他方式傳輸、瀏覽、管理。
- gitosis
*
Git 常用指令:
git init # 將當前資料夾進行 Git 初始化 |
git add . # 將當前資料夾內所有檔案加入 Git 追蹤(tracking 或 staging) |
git add 檔案名稱 # 把當前資料夾內某個檔案加入 Git 追蹤(tracking 或 staging) |
git commit -a # 將目前的變動送繳 Git 進行紀錄,會進入編寫修改訊息的畫面 |
git commit -a -m "*" # commit 時直接寫入修改訊息,不進入編寫修改訊息的畫面 |
git tag v1.0 # 將當前 commit 過後的檔案版本命名為 v1.0 |
git status # 查詢從上一次 commit 到現在,資料夾裡有哪些變化,各個檔案處於什麼狀況 |
git diff # 比較所有檔案的內容與上一次 commit 時有何差異 |
git diff v1.0 v2.0 # 比較 v1.0 與 v2.0 兩個版本間所有檔案的內容 |
git diff v1.0:檔案名稱 v2.0:檔案名稱 # 比較 v1.0 與 v2.0 兩個版本間某個檔案的內容 |
git log # 查詢所有版本的修改狀況,顯示各版本的 hash 編號 |
git log --stat --summary # 查詢每個版本間變動的檔案跟行數 |
git show v1.0 # 查詢 v1.0 版裡的修改內容 |
git show v1.0:檔案名稱 # 查詢某個檔案在 v1.0 時的內容 |
git show HEAD # 看此版本修改的資料 |
git show HEAD^ # 看此版本前一版的修改的資料 |
git show HEAD^^ # 看此版本前前一版的修改的資料 |
git grep "*" v1.0 # 查詢 0.01 版裡頭有沒有某些內容 |
git grep "*" # 查詢現在的版本裡有沒有某些內容 |
git branch 分支名稱 v1.0 # 依照 v1.0 版本裡的內容來建立一個分支 |
git branch -d 分支名稱 # 刪除某個分支 |
git merge 某個分支名稱 # 將當前所在的分支與某個分支合併,如果出現衝突,會紀錄在有衝突的檔案中 |
git checkout master # 切換到主幹上 |
git checkout 分支名稱 # 切換到某個分支上 |
git checkout HEAD # 將所有檔案恢復到上次 commit 的狀態 |
git checkout -- 檔案名稱 # 將某個檔案恢復到上次 commit 的狀態 |
git reset --hard 某個版本的 hash 編號 # 整個 Repository 恢復到某個版本的狀態 |
git count-objects # 分析 Git 資料庫狀況,計算鬆散的物件 |
git fsck --full # 應該是類似 Git 磁碟重組之類的東西 |
Reference:
01.
02.
03. http://walkingice.twbbs.org/blog/archives/504
04. http://ihower.tw/blog/archives/3843
05. http://longair.net/blog/2009/04/16/git-fetch-and-merge
阅读(1887) | 评论(0) | 转发(0) |