1. 程式人生 > >Git基本操作 vs SVN

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使用基礎篇

        git reset:將當前的工作目錄完全回滾到指定的版本號,假設如下圖,我們有A-G五次提交的版本,其中C 的版本號是 bbaf6fb5060b4875b18ff9ff637ce118256d6f20,我們執行了'git reset bbaf6fb5060b4875b18ff9ff637ce118256d6f20'那麼結果就只剩下了A-C三個提交的版本

                                              Git使用基礎篇

        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資料夾,會有如下這樣的目錄結構:

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使用基礎篇

                                                                Git使用基礎篇

        對於易於本地增加分支,圖中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)

-------------------------

svnsubversion的客

subversion
使用的是copy-modify-merge模型,因此一旦我subversion得工作拷 (check out)之後,就可以像修改普通本地檔案那修改些拷
subversion
vss 6.0(visual sourcesafe)lock-modify-unlock模型很不一;它甚至與vss 8.0visual studio 2005 vss版本)也有一點不一vss 8.0得檔案的操作是get latest version,而求修改檔案的操作是check out;而subversioncheckout操作不是求修改檔案,而是得私有的工作拷個意上,checkout有點似於vssget latest version,但是subversion並不需要vsscheckout操作,一旦你些工作拷之後,你就可以立即始工作了!
2.常用操作下面假subversion倉庫的地址是http://server/svn
a) check out
svn checkout http://server/svn
即可在當前目下建立一個工作拷,目名是svn
b) update
使用命令svn update可以用服器的版本更新你的工作拷
c) add
使用命令 svn add filename可以把filename個檔案或者目以及目下面的所有檔案新增狀實際上它並沒有立即新增,你可以看服