Git基本操作 vs SVN
FROM http://www.cnblogs.com/guanghuiqq/archive/2012/08/27/2658752.html
http://www.open-open.com/lib/view/open1332904495999.html
http://www.cnblogs.com/xh831213/archive/2008/05/14/1196786.html
版本控制原因:
1.1 小明負責的模組就要完成了,就在即將Release之前的一瞬間,電腦突然藍屏,硬碟光榮犧牲!幾個月來的努力付之東流——需求之一:備份!
1.2 這個專案中需要一個很複雜的功能,老王摸索了一個星期終於有眉目了,可是這被改得面目全非的程式碼已經回不到從前了。什麼地方能買到哆啦A夢的時光機啊?需求之二:程式碼還原
1.3 小剛和小強先後從檔案伺服器上下載了同一個檔案:Analysis.java。小剛在Analysis.java檔案中的第30行聲明瞭一個方法,叫count(),先儲存到了檔案伺服器上;小強在Analysis.java檔案中的第50行聲明瞭一個方法,叫sum(),也隨後儲存到了檔案伺服器上,於是,count()方法就只存在於小剛的記憶中了——需求之三:協同修改!
1.4 老許是一位專案經理,我會告訴你他把每一個版本都儲存一份嗎?我會告訴你這些工程裡其實有很多檔案都是重複的嗎?我會告訴你老許為這事刪了很多電影嗎?——需求之四:多版本專案檔案管理!
1.5 老王是另一位專案經理,每次因為專案進度捱罵之後,他都不知道該扣哪個程式設計師的工資!就拿這次來說吧,有個該死的Bug除錯了30多個小時才知道是因為相關屬性沒有在應用初始化時賦值!可是二胖、王東、劉流和正經牛都不承認是自己乾的!——需求之五:追溯問題程式碼的編寫人和編寫時間
1.6 小溫這兩天幸福的如同掉進了蜜罐裡,因為他成功的得到了前臺MM麗麗的芳心,可他鬱悶的是這幾天總是收到QA小組的郵件,要求他修正程式中存在的Bug,可他自己本地電腦上是沒有這些Bug的,“難道我的程式碼被哪個孫子給改了?”。是的,小溫沒來的時候,麗麗是QA小組小鄭的女朋友啊!——需求之六:許可權控制!
(from 不知哪裡)SVN:版本控制工具
1.1 SVN基本操作
①檢出(checkout):將一個伺服器端建立好的專案整個下載到本地,這是到專案組後參與開發的第一步,只需執行一次。
②更新(update):將本地檔案更新為伺服器端的最新版本,通常為每天上班時或修改公共檔案之前執行一次。
③提交(commit):將本地修改提交到伺服器端。通常每天下班前或每實現一個功能、完成一個模組時執行一次。
Git是一個分散式的版本控制工具,本篇文章從介紹Git開始,重點在於介紹Git的基本命令和使用技巧,讓你嘗試使用Git的同時,體驗到原來一個版 本控制工具可以對開發產生如此之多的影響,文章分為兩部分,第一部分介紹Git的一些常用命令,其中穿插介紹Git的基本概念和原理,第二篇重點介紹 Git的使用技巧,最後會在Git Hub上建立一個開源專案開啟你的Git實戰之旅
1、Git是什麼
Git在Wikipedia上的定義:它是一個免費的、分散式的版本控制工具,或是一個強調了速度快的原始碼管理工具。Git最初被Linus Torvalds開發出來用於管理Linux核心的開發。每一個Git的工作目錄都是一個完全獨立的程式碼庫,並擁有完整的歷史記錄和版本追蹤能力,不依賴於網路和中心伺服器。
Git的出現減輕了許多開發者和開源專案對於管理分支程式碼的壓力,由於對分支的良好控制,更鼓勵開發者對自己感興趣的專案做出貢獻。其實許多開源專案 包括Linux kernel, Samba, X.org Server, Ruby on Rails,都已經過渡到使用Git作為自己的版本控制工具。對於我們這些喜歡寫程式碼的開發者嘛,有兩點最大的好處,我們可以在任何地點(在上班的地鐵 上)提交自己的程式碼和檢視程式碼版本;我們可以開許許多多個分支來實踐我們的想法,而合併這些分支的開銷幾乎可以忽略不計。
2、Git 1+1
現在進入本篇文章真正的主題,介紹一下Git的基本命令和操作,會從Git的版本庫的初始化,基本操作和獨有的常用命令三部分著手,讓大家能夠開始使用Git。
Git通常有兩種方式來進行初始化:
git clone: 這是較為簡單的一種初始化方式,當你已經有一個遠端的Git版本庫,只需要在本地克隆一份,例如'git clone git://github.com/someone/some_project.git some_project'命令就是將'git://github.com/someone/some_project.git'這個URL地址的遠端版 本庫完全克隆到本地some_project目錄下面
git init和git remote:這種方式稍微複雜一些,當你本地建立了一個工作目錄,你可以進入這個目錄,使用'git init'命令進行初始化,Git以後就會對該目錄下的檔案進行版本控制,這時候如果你需要將它放到遠端伺服器上,可以在遠端伺服器上建立一個目錄,並把 可訪問的URL記錄下來,此時你就可以利用'git remote add'命令來增加一個遠端伺服器端,例如'git remote add origin git://github.com/someone/another_project.git'這條命令就會增加URL地址為'git: //github.com/someone/another_project.git',名稱為origin的遠端伺服器,以後提交程式碼的時候只需要使用 origin別名即可
3、Git的基本命令
現在我們有了本地和遠端的版本庫,讓我們來試著用用Git的基本命令吧:
git pull:從其他的版本庫(既可以是遠端的也可以是本地的)將程式碼更新到本地,例如:'git pull origin master'就是將origin這個版本庫的程式碼更新到本地的master主枝,該功能類似於SVN的update
git add:是將當前更改或者新增的檔案加入到Git的索引中,加入到Git的索引中就表示記入了版本歷史中,這也是提交之前所需要執行的一步,例如'git add app/model/user.rb'就會增加app/model/user.rb檔案到Git的索引中
git rm:從當前的工作空間中和索引中刪除檔案,例如'git rm app/model/user.rb'
git commit:提交當前工作空間的修改內容,類似於SVN的commit命令,例如'git commit -m "story #3, add user model"',提交的時候必須用-m來輸入一條提交資訊
git push:將本地commit的程式碼更新到遠端版本庫中,例如'git push origin'就會將本地的程式碼更新到名為orgin的遠端版本庫中
git log:檢視歷史日誌
git revert:還原一個版本的修改,必須提供一個具體的Git版本號,例如'git revert bbaf6fb5060b4875b18ff9ff637ce118256d6f20',Git的版本號都是生成的一個雜湊值、
上面的命令幾乎都是每個版本控制工具所公有的,下面就開始嘗試一下Git獨有的一些命令:
4、Git獨有的一些命令
git branch:對分支的增、刪、查等操作,例如'git branch new_branch'會從當前的工作版本建立一個叫做new_branch的新分支,'git branch -D new_branch'就會強制刪除叫做new_branch的分支,'git branch'就會列出本地所有的分支
git checkout:Git的checkout有兩個作用,其一是在不同的branch之間進行切換,例如 'git checkout new_branch'就會切換到new_branch的分支上去;另一個功能是還原始碼的作用,例如'git checkout app/model/user.rb'就會將user.rb檔案從上一個已提交的版本中更新回來,未提交的內容全部會回滾
git rebase:用下面兩幅圖解釋會比較清楚一些,rebase命令執行後,實際上是將分支點從C移到了G,這樣分支也就具有了從C到G的功能
git reset:將當前的工作目錄完全回滾到指定的版本號,假設如下圖,我們有A-G五次提交的版本,其中C 的版本號是 bbaf6fb5060b4875b18ff9ff637ce118256d6f20,我們執行了'git reset bbaf6fb5060b4875b18ff9ff637ce118256d6f20'那麼結果就只剩下了A-C三個提交的版本
git stash:將當前未提交的工作存入Git工作棧中,時機成熟的時候再應用回來,這裡暫時提一下這個命令的用法,後面在技巧篇會重點講解
git config:利用這個命令可以新增、更改Git的各種設定,例如'git config branch.master.remote origin'就將master的遠端版本庫設定為別名叫做origin版本庫,後面在技巧篇會利用這個命令個性化設定你的Git,為你打造獨一無二的 Git
git tag:可以將某個具體的版本打上一個標籤,這樣你就不需要記憶複雜的版本號雜湊值了,例如你可以使用 'git tag revert_version bbaf6fb5060b4875b18ff9ff637ce118256d6f20'來標記這個被你還原的版本,那麼以後你想檢視該版本時,就可以使用 revert_version標籤名,而不是雜湊值了
Git之所以能夠提供方便的本地分支等特性,是與它的檔案儲存機制有關的。Git儲存版本控制資訊時使用它自己定義的一套檔案系統儲存機制,在程式碼根目錄下有一個.git資料夾,會有如下這樣的目錄結構:
有幾個比較重要的檔案和目錄需要解釋一下:HEAD檔案存放根節點的資訊,其實目錄結構就表示一個樹型結構,Git採用這種樹形結構來儲存版本資訊, 那麼HEAD就表示根;refs目錄儲存了你在當前版本控制目錄下的各種不同引用(引用指的是你本地和遠端所用到的各個樹分支的資訊),它有heads、 remotes、stash、tags四個子目錄,分別儲存對不同的根、遠端版本庫、Git棧和標籤的四種引用,你可以通過命令'git show-ref'更清晰地檢視引用資訊;logs目錄根據不同的引用儲存了日誌資訊。因此,Git只需要程式碼根目錄下的這一個.git目錄就可以記錄完 整的版本控制資訊,而不是像SVN那樣根目錄和子目錄下都有.svn目錄。那麼下面就來看一下Git與SVN的區別吧
5、Git與SVN的不同
SVN(Subversion)是當前使用最多的版本控制工具。與它相比較,Git最大的優勢在於兩點:易於本地增加分支和分散式的特性。
下面兩幅圖可以形象的展示Git與SVN的不同之處
對於易於本地增加分支,圖中Git本地和伺服器端結構都很靈活,所有版本都儲存在一個目錄中,你只需要進行分支的切換即可達到在某個分支工作的效果。 而SVN則完全不同,如果你需要在本地試驗一些自己的程式碼,只能本地維護多個不同的拷貝,每個拷貝對應一個SVN伺服器地址。舉一個實際的例子,以前我所 在的小組使用SVN作為版本控制工具,當我正在試圖增強一個模組,工作做到一半,由於會改變原模組的行為導致程式碼伺服器上許多測試的失敗,所以並沒有提交 程式碼。這時候上級對我說,現在有一個很緊急的Bug需要處理, 必須在兩個小時內完成。我只好將本地的所有修改diff,並輸出成為一個patch檔案,然後回滾有關當前任務的所有程式碼,再開始修改Bug的任務,等到 修改好後,在將patch應用回來。前前後後要完成多個繁瑣的步驟,這還不計中間程式碼發生衝突所要進行的工作量。可是如果使用Git, 我們只需要開一個分支或者轉回到主分支上,就可以隨時開始Bug修改的任務,完成之後,只要切換到原來的分支就可以優雅的繼續以前的任務。只要你願意,每 一個新的任務都可以開一個分支,完成後,再將它合併到主分支上,輕鬆而優雅。
分散式對於Git而言,你可以本地提交程式碼,所以在上面的圖中,Git有利於將一個大任務分解,進行本地的多次提交,而SVN只能在本地進行大量的一 次性更改,導致將來合併到主幹上造成巨大的風險。Git的程式碼日誌是在本地的,可以隨時檢視。SVN的日誌在伺服器上的,每次檢視日誌需要先從伺服器上下 載下來。我工作的小組,程式碼伺服器在美國,每次檢視小組幾年前所做的工作時,日誌下載就需要十分鐘,這不能不說是一個痛苦。後來我們遷移到Git上,利用 Git日誌在本地的特性,我用Ruby編寫了一個Rake指令碼,可以檢視某個具體任務的所有程式碼歷史,每次只需要幾秒鐘,大大方便我的工作。當然分散式並 不是說用了Git就不需要一個程式碼中心伺服器,如果你工作在一個團隊裡,還是需要一個伺服器來儲存所有的程式碼的。
總結
本篇介紹了Git的基本概念、一些常用命令和原理,大家可以嘗試動手體會一下,下一篇會重點介紹Git命令的使用技巧,Git附帶的工具,最後會在Git Hub上建立一個開源專案
SVN
重要:
SVN不是記錄每一個版本的實際內容,只是記錄版本間的差異
SVN使用延遲拷貝來實現svn copy,其只是原始檔案的一個連結,對拷貝的修改被svn記錄為相對於原始檔案的修改
1.建立儲存庫
假設d:/dev/svnrepo為存放svn儲存庫的目錄
svnadmin create d:/dev/svnrepo/test 建立一名為test的儲存庫
2.匯入專案
假設你的專案在d:/dev/eclipse中的Test資料夾,你的當前目錄為d:/dev/eclipse,你的svn儲存庫路徑為http://localhost/svn/test
svn import Test http://localhost/svn/test/OnlyTest -m "Initial Import"
解釋:匯入的是Test資料夾下的內容 ;另外,注意要起一個路徑名OnlyTest,否則全匯入到http://localhost/svn/test下了;-m 為日誌
3.匯出專案
svn export <專案資料夾> <你的資料夾>
svn export -r <version> <專案資料夾> <你的資料夾>
-------------------------
4.取出
svn co(checkout) http://localhost/svn/test/OnlyTest --- 將OnlyTest資料夾其下的檔案取出來並建立預設資料夾OnlyTest
svn co -r <url> -- 取出特定版本
svn co http://localhost/svn/test/OnlyTest MyTest -- 將OnlyTest資料夾下的檔案取出,放入新建立的資料夾MyTest中
5.新增
svn add * -- svn會將未納入版本控制的檔案加入版本控制中(必須svn commit)
svn add --non-recursive * 非遞迴新增
6.刪除
svn delete(rm,remove,del) <filename> -- 刪除檔案和目錄(必須svn commit)
7.提交
svn commit -m "you log" -- 提交
svn commit --changelist <changelist name> -- 提交指定的changelist
8.建立目錄
svn mkdir <dirname>
svn mkdir <url>
9.移動檔案或目錄
svn move <source_name> <dist_name>
svn move <source_url> <dist_url>
10.輸出特定檔案或URL的內容
svn cat <file or url> -- 輸出特定檔案或URL的內容
svn cat -r <version> <file or url>
------------------------------
11.顯示本地或遠端某一檔案或目錄的詳細資訊
svn info <filename>
svn info -r <version> <filename>
12.列表
svn list(ls)
svn list -r <version>
13.當前目錄或檔案的狀態
svn status <filename>
svn status --show-updates(或-u) 從專案儲存庫中找出哪些檔案有更新
狀態:
第一列:指出條目的狀態
空 無改動
A 新增
C 衝突
D 刪除
G 合併
M 修改
X 無版本記錄,被svn:externals使用
? 未用版本控制管理
第二列:屬性狀態
空 無改動
C 衝突
M 修改
第三列:工作拷貝是否被鎖定
空 未鎖
L 鎖了
14.清理
svn cleanup -- 遞迴清理工作拷貝
15.幫助
svn help
svn help <subcommand> -- 顯示子命令的幫助,如:svn help add
-----------------------
18.鎖定某一目錄或檔案
svn propset svn:needs-lock true <二進位制檔案> -- 設定需要鎖[svn會將其設定為只讀,提示使用者編輯這個檔案前先加鎖]
svn lock <dir or file>
svn lock --force <dir or file> -- 強制對檔案加鎖,即使此檔案已被別人加鎖
19.解鎖
svn unlock <dir or file>
svn unlock --force <dir or file> -- 可以解鎖其他使用者鎖定的檔案
20.顯示特定檔案和URL每一行的作者和修訂版本資訊
svn blame <file or url> -- 每一行文字在開頭都放了最後修改的作者(使用者名稱)和修訂版本號。
svn blame -r <version> <file or url>
21.更新
svn update -r<version> -- 改變到某一個版本
狀態:
A 新增 add
D 刪除 delete
U 更新 update
C 衝突 conflict
M 合併 merge
22.找不同
svn diff <file> -- 找出工作版本和最後更新的版本中的不同
svn diff -c <version> <file> 檢視檔案<file>
在修訂版本<version>修改的內容,是version和version-1比較
svn diff -r <version> <file> 察看你的工作拷貝對舊的修訂版本<version>的修改
svn diff -r <version1>:<version2> <file> 使用範圍符號來比較修訂版本<version1>和<version2>
svn diff -r <version1>:<version2> <url>
svn diff --changelist <changelist name>
23.拷貝
svn copy <source> <dist> -- 其中source和dist既可以是工作目錄檔案也可以是url
如:svn copy foo.txt bar.txt
svn copy near.txt file:///tmp/repos/test/far-away.txt -m "Remote copy."
svn copy file:///tmp/repos/test/far-away near-here
svn copy file:///tmp/repos/test/far-away file:///tmp/repos/test/over-there -m "remote copy."
24. 顯示提交日誌資訊
svn log -r <version> <path>
svn log -r <version1>:<version2> <path>
svn log <path>
svn log -r {iso8601日期} <path>
svn log -r {iso8601日期}:{iso8601日期} <path>
svn log -v <path> 顯示詳細的資訊(包括每個版本有哪些檔案有變動)
svn log --stop-on-copy <path> 得出分支是什麼時候建立的
25.刪除工作拷貝檔案或目錄的“衝突”狀態(相關的衝突檔案檔案)
svn resolved <path>
26.取消所有的本地編輯
svn revert <path>
svn revert --recursive <path> 遞迴
27.解決衝突
svn resolve --accept <status> <path>
status:
base:選擇你更新你的工作拷貝前的你checkout出的未經修改的版本
working:手工處理後,選擇當前你工作拷貝中的版本
mine-full:選擇在你svn update前的工作拷貝
theirs-full:選擇svn update取出的檔案拷貝
28.將檔案放入到一個改變列表中
svn changelist(cl) <changelist name> <path1> <path2> <path...>
svn commit --changelist <changelist name> -- 只提交此change list的檔案
29.版本號標識
(1)號 87
(2){日期} {2009-09-09}
(3)HEAD 儲存庫中最新版本
(4)BASE 工作拷貝中你最後簽出的版本
(5)COMMITED 最後改動版本,等於或早於BASE
(6)PREV COMMITED之前的一個版本
30.產生和應用補丁
svn diff > file.patch
patch <options> file.patch
31.svn專案組織
project/
trunk/ --主幹
branches/ --分支
tags/ --標籤
32.常用示例
(1)提交改動
svn update -- 更新到專案的當前狀態
# resolve conflicts 解決衝突
編輯檔案
svn resolved
# run tests 執行測試
svn commit -m "your logs" -- 提交
(2)簡單bug修正
a.在一個分支中修正bug並提交
b.將其合併到存在此bug的其他分支中(svn merge -r<version1>:<version2>)
(3)複雜bug修正
a.建立一個bug修正分支(svn copy) name=bug-trackid
b.為這個修正分支在修正前打標籤(svn copy) name=bugpre-trackid
c.修正bug
d.為這個修正在修正後打標籤(svn copy) name=bugpost-trackid
e.合併此bug修正到其他分支(svn merge -r bugpre-trackid:bugpost-trackid)
-------------------------
svn是subversion的客戶端
subversion使用的是copy-modify-merge模型,因此一旦我們從subversion服務器獲得工作拷貝 (check
out)之後,就可以像修改普通本地檔案那樣修改這些拷貝。
subversion與vss 6.0(visual sourcesafe)的lock-modify-unlock模型很不一樣;它甚至與vss
8.0(visual studio 2005 附帶的vss版本)也有一點不一樣:對於vss
8.0,獲得檔案的操作是get
latest version,而請求修改檔案的操作是check
out;而subversion的checkout操作不是請求修改檔案,而是獲得私有的工作拷貝,這個意義上,checkout有點類似於vss的get
latest version,但是subversion並不需要vss的checkout操作,一旦你獲得這些工作拷貝之後,你就可以立即開始工作了!
2.常用操作下面假設subversion倉庫的地址是http://server/svn
a) check out
svn checkout http://server/svn
即可在當前目錄下建立一個工作拷貝,目錄名是svn
b) update
使用命令svn update可以用服務器的版本更新你的工作拷貝
c) add
使用命令 svn add filename可以把filename這個檔案或者目錄以及目錄下面的所有檔案標志為新增狀態(實際上它並沒有立即新增,你可以查看服