Git創建一個自己的本地倉庫


如果我們要把一個項目加入到Git的版本管理中,可以在項目所在的目錄用git init命令建立一個空的本地倉庫,然后再用git add命令把它們都加入到Git本地倉庫的暫存區(stage or index)中,最后再用git commit命令提交到本地倉庫里。

創建一個新的項目目錄,並生成一些簡單的文件內容:

$ mkdir test_proj

$ cd test_proj

$ echo “hello,world” > readme.txt

在項目目錄創建新的本地倉庫,並把項目里的所有文件全部添加、提交到本地倉庫中去:

$ git init #在當前的目錄下創建一個新的空的本地倉庫Initialized empty Git repository in /home/user/test_proj/.git/

$ git add . #把前目錄下的所有文件全部添加到暫存區

$ git commit -m 'project init' #創建提交[master (root-commit) b36a785] project init 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 readme.txt

Git目錄的結構

git init命令在項目的頂層目錄中建了一個名為:“.git”的目錄,它的別名是 “Git目錄”(Git directory)。這時”Git目錄”中雖然有一些文件,但是沒有任何提交(commit)在里面,所以我們叫它是空倉庫(empty Git repository)。

和 SVN不同,一個Git項目一般只在項目的根目錄下建一個“.git”目錄,而SVN則會在項目的每一個目錄下建一個”.svn”目錄;這也我喜歡Git的原因之一:

Git把所有的歷史提交信息全部存儲在“Git目錄”里,它就是一個Git項目的倉庫;你對本地的源代碼進行編輯修改后創建的提交也都會先保存在這 里面,然后再推送到遠端的服務器。當我們我把項目目錄和“Git目錄”一起拷到其它電腦里,它能馬上正常的工作(所有的提交信息全都保存在Git目錄 里);甚至可以只把“Git目錄”拷走也行,但是要再簽出(checkout)一次。

Git為了 調試的方便,它可以指定項目的Git目錄的位置。有兩種辦法:一是設置“GIT_DIR”環境變量,二是在命令行里設定“--git-dir--git-dir”參數指定它的位置,大家可以看一下這里(git(1) Manual Page)。

 

庖丁解牛

前面的這些東東我在第一篇里也大概的講過一些,但是今天我們想不但要開動這輛叫“Git”的跑車,還想看看它里面有些什么樣的零件,是怎么構成的。

OK,我們來看看“test_proj”項目里的“Git目錄”的結構:

$cd test_proj/.git 
$ ls | more 
branches/ # 新版的Git已經不再使用這個目錄,所以大家看到它 #一般會是空的
COMMIT_EDITMSG # 保存着上一次提交時的注釋信息
config # 項目的配置信息
description # 項目的描述信息
HEAD # 項目當前在哪個分支的信息
hooks/ # 默認的“hooks” 腳本文件
index # 索引文件,git add 后把要添加的項暫存到這里
info/ # 里面有一個exclude文件,指定本項目要忽略的文件 #,看一下這里
logs/ # 各個refs的歷史信息
objects/ # 這個目錄非常重要,里面存儲都是Git的數據對象
# 包括:提交(commits), 樹對象(trees),二進制對象 #(blobs),標簽對象(tags)。
#不明白沒有關系,后面會講的。
refs/ # 標識着你的每個分支指向哪個提交(commit)。

我先用git log命令來看一下這個Git項目里有哪些提交:

$ git logcommit 58b53cfe12a9625865159b6fcf2738b2f6774844
Author: liuhui998 <liuhui998@nospam.com>
Date: Sat Feb 19 18:10:08 2011 +0800
project init

大家可以看到目前只有一個提交(commit)對象,而它的名字就 是:”58b53cfe12a9625865159b6fcf2738b2f6774844”。這個名字就是對象內容的一個SHA簽名串值,只要對象里面的內容不同,那么我們就可以認為對象的名字不會相同,反之也成立。我在使用時一般不用把這個40個字符輸全,只要把前面的5~8個字符輸完就可以(前提是 和其它的對象名不沖突)。為了方便表示,在不影響表達的情況下,我會只寫SHA串值的前6個字符。

我們可以用git cat-file來看一下這個提交里的內容是什么:

$ git cat -file -p 58b53c tree 2bb9f0c9dc5caa1fb10f9e0ccbb3a7003c8a0e13author liuhui998 <liuhui998@nospam.com> 1298110208 +0800
committer liuhui998 <liuhui998@nospam.com> 1298110208 +0800
project init

大家可以看到:提交“58b53c” 是引用一個名為“2bb9f0”的樹對象(tree)。一個樹對象(tree)可以引用一個或多個二進制對象(blob), 每個二進制對象都對應一個文件。 更進一步, 樹對象也可以引用其他的樹對象,從而構成一個目錄層次結構。我們再看一下這個樹對象(tree)里面有什么東東:

$ git cat-file -p 2bb9f0100644 blob 2d832d9044c698081e59c322d5a2a459da546469 readme.txt

不難看出,2bb9f0”這個樹對象(tree)包括了了一個二進制對象(blob),對應於我們在前面創建的那個叫 ”readme.txt”的文件。現在我們來看看這個”blob”里的數據是不是和前面的提交的內容一致:

$ git cat-file -p 2d832dhello,world

哈哈,熟悉的“hello,world”又回來了。

想不想看看提交對象、樹對象和二進制對象是怎么在”Git目錄“中存儲的;沒有問題,執行下面的命令,看看”.git/objects”目錄里的內容:

$ find .git/objects.git/objects
.git/objects/2b
.git/objects/2b/b9f0c9dc5caa1fb10f9e0ccbb3a7003c8a0e13.git/objects/2d
.git/objects/2d/832d9044c698081e59c322d5a2a459da546469.git/objects/58
.git/objects/58/b53cfe12a9625865159b6fcf2738b2f6774844.git/objects/info
.git/objects/pack

如果大家仔細看上面命令執行結果中的粗體字,所有的對象都使用SHA簽名串值作為索引存儲在”.git/objects”目錄之下;SHA串的前兩個字符作為目錄名,后面的38個字符作為文件名。

這些文件的內容其實是壓縮的數據外加一個標注類型和長度的頭。類型可以是提交對象(commit)、二進制對象(blob)、 樹對象(tree)或者標簽對象(tag)。

如何clone一個遠程項目

我身邊的很多朋友是因為要得到某個開源項目的代碼,所以才開始學習使用Git。而獲取一個項目的代碼的一般的做法就是用git clone命令進行直接復制。

例如,有些朋友可能想看一下最新的linux內核源代碼,當我們打開它的網站時,發現有如下面的一段提示:

URL
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

URL下面的三行字符串表示三個地址,我們可以通過這三個地址得到同樣的一份Linux內核源代碼。

也就是說下面這三條命令最終得到的是同一份源代碼:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
git clone http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
git cone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

我們先來看一下URL,git://、http://、https://這些代表是傳輸git倉庫的協議形式,而“git.kernel.org“則代表了Git倉庫存儲的服務器名字(域名),“/pub/scm/linux/kernel/git/torvalds/linux-2.6.git” 則代表了Git倉庫在服務器上位置。

Git 倉庫除了可以通過上面的git、http、https協議傳輸外還可以通過ssh、ftp(s)、rsync等協議來傳輸。git clone的本質就是把“Git目錄”里面的內容拷貝過來,大家想想看,一般的“Git目錄”里有成千上萬的各種對象(提交對象,樹對象,二進制對象......),如果逐一復制的話,其效率就可想而知。

如果通過git、ssh協議傳輸,服務器端會在傳輸前把需要傳輸的各種對象先打好包再進行傳輸;而http(s)協議則會反復請求要傳輸的不同對 象。如果倉庫里面的提交不多的話,前者和后者的效率相差不多;但是若倉庫里有很多提交的話,git、ssh協議進行傳輸則會更有效率。

不過現在Git對http(s)協議傳輸Git倉庫做了一定的優化,http(s)傳輸現在也能達到ssh協議的效率,有興趣的朋友可以看一下這里(Smart HTTP Transport)。

好的,現在我們執行了下面這條命令,把linux-2.6的最新版源代碼clone下來:

$cd ~/$mkdir temp$git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.gitInitialized empty Git repository in /home/liuhui/temp/linux-2.6/.git/
remote: Counting objects: 1889189, done.
remote: Compressing objects: 100% (303141/303141), done.
Receiving objects: 100% (1889189/1889189), 385.03 MiB | 1.64 MiB/s, done.
remote: Total 1889189 (delta 1570491), reused 1887756 (delta 1569178)
Resolving deltas: 100% (1570491/1570491), done.
Checking out files: 100% (35867/35867), done.

當我們執行了“git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git”這條命令后大家可以看到這條輸出:

Initialized empty Git repository in /home/user/temp/linux-2.6/.git/

這就是意味着我們在本地先建了一個“linux-2.6”目錄,然后在這個目錄建了一個空的Git本地倉庫(Git目錄);里面將會存儲從網上拉下來的歷史提交。

下面兩條輸入代表服務器現在調用 git-pack-objects 對它的倉庫進行打包和壓縮:

remote: Counting objects: 1888686, done.
remote: Compressing objects: 100% (302932/302932), done.

然后客戶端接收服務器端發過送過來的數據:

Receiving objects: 100% (1889189/1889189), 385.03 MiB | 1.64 MiB/s, done.

在我們執行完上面的clone linux-2.6代碼的的操作后,Git會從“Git目錄”里把最新的代碼到簽出(checkout)到“linux-2.6”這個目錄里面。我們一般 把本地的“linux-2.6”這個目錄叫做”工作目錄“(work directory),它里面保存着你從其它地方clone(or checkout)過來的代碼。當你在項目的不同分支間切換時,“工作目錄”中的文件可能會被替換或者刪除;“工作目錄”只是保存着當前的工作,你可以修 改里面文件的內容直到下次提交為止。

大家還記得前面的“庖丁解牛”嗎,是不是覺得只殺一頭叫“hello,world”的小牛太不過癮了。沒有問題,拿起前面的那把小刀,來剖析一下現在躺在你硬盤里這頭叫“linux-2.6”大牛看看,我想一定很好玩。

 

向本地倉庫中增加文件

下面我們向版本庫中增加文件,需要注意的是,在版本庫中只能跟蹤和管理文本文件,比txt文件、js文件、php文件、java文件等,所有的程序 代碼都可以的。但是像視頻、圖片等這些二進制文件,雖然能由git管理,但是只能記錄大小,無法跟蹤具體修改了什么,嘿嘿。大家懂了吧。好了,下面我們來 增加一個readme.txt文件,其內容如下:

 

 

1

2

3

 

This is git test.

 

Git is a version of the best controller.

 

……

 

 

 

 

readme

 

 

注意,新建的readme.txt文件,一定要在pro目錄,不然git無法管理這里文件哦,嘿嘿!下面我們把個文件放到版本庫中。

 

 

git add

git add

 

1).git status 命令

 

我們先用git status命令查看一下,如上圖。大家可以看到git記錄我們新增加一個文件readme.txt,並且提示這個文件還沒有被提交。下面我們用git add命令提交一下。

 

2).git add 命令

 

git add 命令是告訴git,我們要把什么文件提交到倉庫中去,大家可以看我們執行git add readme.txt命令后,沒有任何提示。那就說明我們提交完成了。下面我們通過git commit命令,將readme.txt文件提交到版本庫中。

 

3).git commit 命令

 

 

1

2

3

4

 

$ git commit -m "add readme.txt"

 

[master (root-commit) e5d662b] add readme. 

 

file changed, 3 insertions(+) 

 

create mode 100644 readme.txt

 

 

 

大家可以看到我們用git commit命令提交readme.txt文件,給出的提示是  1 file changed, 3 insertions(+),一個文件改變,插入了三行內容。與我們上面增加三行內容一致。嘿嘿!下面我們簡單的說明一下git commit命令,其中的參數-m后面輸入的是本次提交的版本說明,可以輸入任意內容,但需要說明的是,最好寫有意義的說明,便於以后查看。

 

4).git status 命令

 

最后我們再用git status命令查看一下版本庫的狀態,提示沒有任何內容需要提交說明我們向版本庫增加文件成功了,嘿嘿。

 

 

 

4.總結

 

1).初始化一個Git倉庫,使用git init命令

 

2).添加文件到本地Git倉中,分為兩步:

 

  • 使用git add命令,注意,可以多次使用,添加多個文件

     

  • 使用git commit命令,完成添加。

     

 

為什么Git添加文件需要兩步呢?一步add,一步commit。嘿嘿,因為commit命令可以一次提交多個文件,所以你可以多次使用add命令呢。下面是個案例:(我們也經常這么用)

 

1

2

3

4

 

$ git add file1.php

 

$ git add file2.php

 

$ git add file3.php

 

$ git commit –m “add file1.php file2.php file3.php”

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM