Git基礎命令

 創建Git—git-init

    你們曾經創建過CVS的庫麼?應該很少有人操作過吧?因爲很多人都是從CVS庫裏checkout代碼。同樣,在合作開發中,如果你不是一個代碼模塊的發起者,也不會使用到這個命令,更多的是使用git-clone(見2.7節)。但是,如果你想個人開發一個小模塊,並暫時用代碼管理工具管理起來(其實我就常這麼做,至少很多個人開發過程都可以保留下來,以便備份和恢復),創建一個Git庫是很容易和方便的。
對於酷訊來說,當一個代碼的Git庫創建後,會添加代碼文件到庫裏,並將這個庫放到公司一個專門用來進行代碼管理的服務器上,使大家可以在以後clone(不明白?沒關係,繼續往後看就明白了)它。對於個人來說,你可以隨便將這個庫放到哪裏,只要你能訪問的到就行。

    創建一個Git庫是很容易和方便的,只要用命令 git-init 就可以了。在Git1.4之前(包括git1.4)的版本,這個命令是git-init
a)         $ mkdir dir
b)        $ cd dir
c)         $ git-init
   
這樣,一個空的版本庫就創建好了,並在當前目錄中創建一個叫 .git 的子目錄。以後,所以的文件變化信息都會保存到這個目錄下,而不像CVS那樣,會在每個目錄和子目錄下都創建一個討厭的CVS目錄。
.git目錄下有一個config文件,需要我們添加一下個人信息後才能使用。否則我們不能對其中添加和修改任何文件。
   
原始的config文件是這樣的,
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
我們需要加入
[user] 
        name = xxx
        emai= [email protected]
   
現在已經創建好了一個 git 版本庫,但是它是空的,還不能做任何事情,下一步就是怎麼向版本庫中添加文件了。如果希望忽略某些文件,需要在git庫根目錄下添加. gitignore文件。
2.2   一條重要的命令 -- git-update-index
    在介紹如何向git庫中添加文件前,不得不先介紹git-update-index命令。這條命令可能會使很多熟悉CVS的用戶疑惑,一般來說,我們向一個源代碼管理庫提交代碼的更改,都會抽象爲以下的動作:更改文件;向源碼管理系統標識變化;提交。比如從一個CVS庫裏刪除一個文件,需要先刪除文件,然後cvs delete最後cvs commit 
因此, git-update-index就是向源碼管理系統標識文件變化的一個抽象操作。說的簡要一些,git-update-index命令就是通知git庫有文件的狀態發生了變化(新添、修改、刪除等待)。這條命令在早期的git版本中是非常常用的。在新的git版本(1.5版本及以後)已經被其它命令包裝起來,並且不推薦使用了。
    git-update-index
最常用的方式有以下兩種,更多功能請man git-update-index
 
方法一:git-update-index --add 文件名列表。如果文件存在,則這條命令是向git庫標識該文件發生過變化(無論是否該文件確實被修改過),如果文件不存在,則這條命令是向git庫表示需要加入一個新文件。l
 
方法二: git-update-index --force-remove 文件名列表。這表示向git庫表示喲啊從庫中刪除文件。無論該文件是否已經被刪除,這條命令僅僅是通知git庫要從庫中刪除這些文件。這些文件都不會受影響。l
   
因此,git-update-index僅僅是向git庫起到一個通知和標識的作用,並不會操作具體的文件。
2.3   git庫中添加或刪除文件 – git-addgit-rm
    其實,說使用git-add命令向git庫裏添加文件是不對的,或者說至少是不全面的。git-add 命令的本質是命令"git-update-index --add” 的一個包裝。因此,git-add除了可以添加文件,還可以標識文件修改。在調用了git-add後,纔可以做commit操作。git-rm 也是一樣,它是git-update-index --force-remove的一個包裝。
   
對於git-add來說,如果在一個目錄下調用了git-add * ,則默認是遞歸將子目錄中所有文件都addgit庫中。對於git-rm來說,也是一樣。這點和CVS有較大區別。
   
此外,我們還可以通過命令git-ls-files來查看當前的git庫中有那些文件。

2.4   查看版本庫狀態—git-status
   
通過該命令,我們可以查看版本庫的狀態。可以得知那些文件發生了變化,那些文件還沒有添加到git庫中等等。建議每次commit前都要通過該命令確認庫狀態。以避免誤操作。
   
其總,最常見的誤操作是,修改了一個文件,沒有調用git-add通知git庫該文件已經發生了變化就直接調用commit操作,從而導致該文件並沒有真正的提交。如果這時如果開發者以爲已經提交了該文件,就繼續修改甚至刪除這個文件,那麼修改的內容就沒有通過版本管理起來。如果每次在提交前,使用git-status查看一下,就可以發現這種錯誤。因此,如果調用了git-status命令,一定要格外注意那些提示爲“Changed but not updated:”的文件。這些文件都是與上次commit相比發生了變化,但是卻沒有通過git-add標識的文件。
2.5   向版本庫提交變化 – git-commit
    直接調用git-commit命令,會提示填寫註釋。也可以通過如下方式在命令行就填寫提交註釋:git-commit -m "Initial commit of gittutor reposistory"注意,和CVS不同,git的提交註釋必須不能爲空。否則就會提交失敗。
    git-commit
還有一個 –a的參數,可以將那些沒有通過git-add標識的變化一併強行提交,但是不建議使用這種方式。
   
每一次提交,git就會爲全局代碼建立一個唯一的commit標識代碼,用戶可以通過git-revert命令恢復到任意一次提交時的代碼。這比CVS不同文件有不同的版本呢號管理可方便多了。(和SVN類似)
   
如果提交前,想看看具體那些文件發生變化,可以通過git-diff來查看,不過這個命令的輸出並不友好。因此建議用別的工具來實現該功能。在提交後,還可以通過git-log命令來查看提交記錄。
2.6   分支管理 – git-branch
   
我們迎來了git最強大,也是比CVSSVN強大的多的功能分支管理。
   
大概每個程序員都會經常遇到這樣的情況: 
1.      
需要立刻放下手頭的工作,去修改曾經一個版本的bug並上線,然後再繼續當的工作。
2.      
本想向中心庫commit一個重要修改,但是由於需要經常備份代碼,最終不得不頻繁的向中心庫commit。從而導致大量無用的commit信息被保留在中心庫中。
3.      
將一次修改提交同事進行code review但是由於同事code review比較慢,得到反饋時,自己的代碼已經發生了變化,從而倒是合併異常困難
   
這些場景,如果用CVS或者SVN來解決,雖說不一定解決不了,但過程之繁瑣,之複雜,肯定另所有人都有生不如死的感覺吧!究其關鍵,就是CVS或者SNVbranch管理太複雜,基本不具可用性。
   
git 版本庫中創建分支的成本幾乎爲零,所以,不必吝嗇多創建幾個分支。當第一次執行git-init時,系統就會創建一個名爲”master”的分支。而其它分支則通過手工創建。下面列舉一些常見的分支策略,這些策略相信會對你的日常開發帶來很大的便利。 
 1.
創建一個屬於自己的個人工作分支,以避免對主分支 master 造成太多的干擾,也方便與他人交流協作。 l
 2.
當進行高風險的工作時,創建一個試驗性的分支,扔掉一個爛攤子總比收拾一個爛攤子好得多。 l
 3.
合併別人的工作的時候,最好是創建一個臨時的分支用來合併,合併完成後在“fatch”到自己的分支(合併和fatch後面有講述,不明白就繼續往下看好了)l
2.6.1 查看分支 – git-branch
    調用git-branch可以查看程序中已經存在的分支和當前分支
2.6.2 創建分支 – git-branch 分支名
    要創建一個分支,可以使用如下方法:
1.       git-branch
分支名稱
2.       git-checout –b
分支名
   
使用第一種方法,雖然創建了分支,但是不會將當前工作分支切換到新創建的分支上,因此,還需要命令”git-checkout 分支名來切換,而第二種方法不但創建了分支,還將當前工作分支切換到了該分支上。
   
另外,需要注意,分支名稱是有可能出現重名的情況的,比如說,我在master分支下創建了ab兩個分支,然後切換到b分支,在b分支下又創建了ac分支。這種操作是可以進行的。此時的a分支和master下的a分支實際上是兩個不同的分支。因此,在實際使用時,不建議這樣的操作,這樣會帶來命名上的疑惑。
2.6.3 刪除分支 – git-branch –D
    git-branch –D 分支名可以刪除分支,但是需要小心,刪除後,發生在該分支的所有變化都無法恢復。 
2.6.4 切換分支 – git-checkout 分支名
   
如果分支已經存在,可以通過 git-checkout 分支名來切換工作分支到該分支名
2.6.5 查看分支歷史 –git-show-branch
    調用該命令可以查看分支歷史變化情況。如:
* [dev1] d2
! [master] m2
--
* [dev1] d2
* [dev1^] d1
* [dev1~2] d1
*+ [master] m2
   
在上述例子中, “--”之上的兩行表示有兩個分支dev1masterdev分支上最後一次提交的日誌是“d2”,master分支上最後一次提交的日誌是”m2” “--”之下的幾行表示了分支演化的歷史,其中 dev1表示發生在dev分支上的最後一次提交,dev^表示發生在dev分支上的倒數第二次提交。dev1~2表示發生在dev分支上的倒數第三次提交。
2.6.6 合併分支 – git-merge
    git-merge的用法爲:git-merge “some memo” 合併的目標分支合併的來源分支。如:
    git-merge master dev1~2
   
如果合併有衝突,git會由提示,當前,git-merge已經很少用了,git-pull來替代了。
   
用法爲:git-pull 合併的目標分支合併的來源分支。git-pull . dev1^

2.7   遠程獲取一個git git-clone
    2.1節提到過,如果你不是一個代碼模塊的發起者,也不會使用到git-init命令,而是更多的是使用git-clone。通過這個命令,你可以從遠端完整獲取一個git庫,並可以通過一些命令和遠端的git交互。
   
基於git的代碼管理的組織結構,往往形成一個樹狀結構,開發者一般從某個代碼模塊的管理者的git庫通過git-clone取得開發環境,在本地迭代開發後,再提交給該模塊的管理者,該模塊的管理者檢查這些提交併將代碼合併到自己的庫中,並向更高一級的代碼管理者提交自己的模塊代碼。
   
對於酷訊來說,公司會有一箇中心的git庫,大家在開發時,都是從中心庫git-clone獲取最新代碼。
git-clone
的使用方法如下: git-clone [ssh://]username@ipaddr:path其中, “ssh://”可選,也有別的獲取方式,如rsync Path是遠端git的根路徑,也叫repository
   
通過git-clone獲取遠端git庫後,.git/config中的開發者信息不會被一起clone過來。仍然需要爲.git/config文件添加開發者信息。此外,開發者還需要自己添加. gitignore文件
  
另外,通過git-clone獲取的遠端git庫,只包含了遠端git庫的當前工作分支。如果想獲取其它分支信息,需要使用”git-branch –r” 來查看,如果需要將遠程的其它分支代碼也獲取過來,可以使用命令” git checkout -b 本地分支名遠程分支名,其中,遠程分支名爲git-branch –r所列出的分支名,一般是諸如“origin/分支名的樣子。如果本地分支名已經存在,則不需要“-b”參數。

2.8   從遠程獲取一個git分支 – git-pull
    git-clone不同, git-pull可以從任意一個git庫獲取某個分支的內容。用法如下:
    git-pull username@ipaddr:
遠端repository遠端分支名:本地分支名。這條命令將從遠端git庫的遠端分支名獲取到本地git庫的一個本地分支中。其中,如果不寫本地分支名,則默認pull到本地當前分支。
需要注意的是,git-pull也可以用來合併分支。git-merge的作用相同。因此,如果你的本地分支已經有內容,則git-pull會合並這些文件,如果有衝突會報警。

2.9   將本地分支內容提交到遠端分支 – git-push
    git-pushgit-pull正好想反,是將本地某個分支的內容提交到遠端某個分支上。用法:
git-push username@ipaddr:
遠端repository本地分支名:遠端分支名。這條命令將本地git庫的一個本地分支push到遠端git庫的遠端分支名中。

    需要格外注意的是,git-push好像不會自動合併文件。這點我的試驗表明是這樣,但我不能確認是否是我用錯了。因此,如果git-push時,發生了衝突,就會被後push的文件內容強行覆蓋,而且沒有什麼提示。這在合作開發時是很危險的事情。
2.10     庫的逆轉與恢復 – git-reset
   
庫的逆轉與恢復除了用來進行一些廢棄的研發代碼的重置外,還有一個重要的作用。比如我們從遠程clone了一個代碼庫,在本地開發後,準備提交回遠程。但是本地代碼庫在開發時,有功能性的commit,也有出於備份目的的commit等等。總之,commit的日誌中有大量無用log,我們並不想把這些log在提交回遠程時也提交到庫中。因此,就要用到git-reset
    Git-reset
的概念比較複雜。它的命令形式:git-reset [--mixed | --soft | --hard] [<commit-ish>] 
命令的選項:
--mixed 
   
這個是默認的選項。git-reset [--mixed] dev1^(dev1^的定義可以參見2.6.5)。它的作用僅是重置分支狀態到dev1^, 但是卻不改變任何工作文件的內容。即,從dev1^dev1的所有文件變化都保留了,但是dev1^dev1之間的所有commit日誌都被清除了,而且,發生變化的文件內容也沒有通過git-add標識,如果您要重新commit,還需要對變化的文件做一次git-add這樣,commit後,就得到了一份非常乾淨的提交記錄。 
--soft 
   
相當於做了git-reset –mixed,後,又對變化的文件做了git-add。如果用了該選項,就可以直接commit了。
--hard 
   
這個命令就會導致所有信息的回退,包括文件內容。一般只有在重置廢棄代碼時,才用它。執行後,文件內容也無法恢復回來了。

2.11     更多的操作
   
更多的細節可以在linuxman git的文檔。此外,http://www.linuxsir.org/main/doc/git/gittutorcn.htm 也有不少更詳細的介紹。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章