Git基本概念及操作(2)

想要深入的瞭解GIT,還得回到常見版本管理系統中的version概念。前面我們說到一個文件在不同的時間會產生不同的版本,那版本管理系統怎麼記錄這些不同的版本,是每一個時間保存一個文件,還是保存這些差異點,然後合併呢?這裏通常有兩種實現方式,一種是保存變更差異,如下圖所示:

image

這種方式廣泛採用在CVS/SVN中,好處是管理系統保存單個版本所用的空間不需要很大。但壞處很明顯,比喻說我在版本4處想要拿到File A/B/C的拷貝,需要經過三次比較計算才能拿到準備的版本數據。並且這當中任何一個版本數據丟失了我就不能得到當前版本數據。第二種是每次都保存,只要有變化就保存。如下圖所示:

image

這種方式就是對每一個版本的每一個文件進行HASH計算,一旦發現HASH不同就誕生一個新的文件,如果相同說明文件沒變化。因此,這種管理下每個版本實際是保存單獨的文件,與前一個版本不需要進行差異化比較。取出一個新版本的效率大大增強。所獲得的好處是非常明顯的。GIT就是採用這種方案的。GIT採用SHA-1計算出每種管理對象(Element)的HASH值,通過這些HASH值來組成一個管理對象樹。

前面我們講的集中式版本管理系統通常都是C/S架構,一個Repository,多個Client。那麼對GIT這種分佈式版本管理系統,其基本架構怎麼樣呢?其實也類似,只是說C/S都在本地。GIT對源碼的管理分成三塊,一塊是Repository通常是以.git目錄下保存的數據,一塊是工作區 working area,是與.git目錄同級的其它目錄及子目錄都是工作區,注意工作區中不一定是所有的文件都是受控的,只有當你的文件加入REPO後纔是受控的。第三塊就是比較難以理解的暫定區staging area. Staging area實際上是.git目錄中一個索引文件,也就是這個文件的HASH值。如下圖所示:

image

其中Working directory是項目的檢出版本,這個檢出版本跟你當前的工作分支是相關的。缺省工作分支是master。這個有點類似於CC中VIEW概念。一旦你將當前工作目錄中的所有文件都commit後,這些目錄中的文件實際上是可以刪除的。這一點同CC中VIEW非常相似。Staging area是一個記錄暫存區,在GIT目錄中表現爲索引文件,與正式COMMIT區別就是狀態未變。如下圖所示:

image

瞭解了上面兩大基本概念之後,我們可以結合實際操作來深入瞭解GIT的一些基本理念,這些理念實際上也就是在GIT下是如何定義版本與分支、TAG、HEAD及其之間的關係。

【1】GIT配置。GIT目前是沒有權限系統的,或者說權限非常弱的。GIT的權限目前主要是靠操作系統,所以GIT配置中是沒有權限配置的。GIT配置分成全局配置、用戶配置和項目配置。全局配置適用於操作系統的所有用戶,用戶配置適用於當前用戶,項目配置適用於當前項目。每一個級別的配置都會覆蓋上層的相同配置。這三種配置區別在於存儲目錄和使用命令選項不同。

1)全局配置 /etc/gitconfig(相對於安裝路徑,有時候沒有) 命令git config –system

2)用戶配置 ~/.gitconfig 或者$HOME/.gitconfig git-config –global

3)項目配置 項目.git目錄中config目錄下 git config

[root@wrlinux3 mygit]# cat /root/.gitconfig
[core]
    gitproxy = /work/bongos/bin/git-proxy
[merge]
    tool = vimdiff
[root@wrlinux3 mygit]# ls -latr /etc/gitconfig
ls: cannot access /etc/gitconfig: No such file or directory
[root@wrlinux3 mygit]# ls -latr ~/.gitconfig
-rw-r--r--. 1 root root 70 Apr 20 16:01 /root/.gitconfig
[root@wrlinux3 mygit]# ls -latr .git/config
.git/   test.c 
[root@wrlinux3 mygit]# ls -latr .git/config
-rw-r--r--. 1 root root 92 Apr 20 15:27 .git/config
[root@wrlinux3 mygit]# git config --list
core.gitproxy=/work/bongos/bin/git-proxy
merge.tool=vimdiff
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true

[root@wrlinux3 mygit]# git config --global user.name "ROOT root"
[root@wrlinux3 mygit]# git config --global user.emal "[email protected]"
[root@wrlinux3 mygit]# cat ~/.gitconfig
[core]
    gitproxy = /work/bongos/bin/git-proxy
[merge]
    tool = vimdiff
[user]
    name = ROOT root
    emal = [email protected]
[root@wrlinux3 mygit]# git config user.name "PROJ proj"
[root@wrlinux3 mygit]# git config user.email "[email protected]"
[root@wrlinux3 mygit]# cat .git/config
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[user]
    name = PROJ proj
    email = [email protected]
[root@wrlinux3 mygit]# git config --list
core.gitproxy=/work/bongos/bin/git-proxy
merge.tool=vimdiff
user.name=ROOT root
[email protected]
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
user.name=PROJ proj
[email protected]
[root@wrlinux3 mygit]# git config user.name
PROJ proj
[root@wrlinux3 mygit]# git config --global user.name
ROOT root
[root@wrlinux3 mygit]#

GIT配置還有三個其他配置,一個就是命令的自動完成,還有一個命令別名。最後一個就是gitignore .自動完成需要一個BASH,這個文件通常在contrib目錄下,需要進行如下圖所示的配置:

image

別名是使用git config 來定義alias.*

1008  git config --global alias.co checkout
1009  git config --global alias.br branch
1010  git config --global alias.ci commit
1011  git config --global alias.st status
1012  git config --global alias.unstage 'reset HEAD --'
1013  git config --global alias.last 'log -1 HEARD'
1014  git last
1015  git config --global alias.last 'log -l HEAD'
1016  git last
1017  git log -l
1018  git log -1 HEAD
1019  git help log
1020  git log -1 HEAD
1021  git log -l HEAD
1022  history
[root@wrlinux3 mygit]# git config --list
core.gitproxy=/work/bongos/bin/git-proxy
merge.tool=vimdiff
user.name=ROOT root
[email protected]
alias.co=checkout
alias.br=branch
alias.ci=commit
alias.st=status
alias.unstage=reset HEAD --
alias.last=log -l HEAD
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
user.name=PROJ proj
[email protected]
[root@wrlinux3 mygit]#

對一個項目如果不想將工作目錄中一些臨時或者編譯產生的文件納入git管理,可以通過創建.gitignore文件來告訴git。

image

【2】倉庫建立。建立GIT項目倉庫,一種是完全新的創建,也就是說讓項目所在的目錄成爲GIT受控,只需要執行命令git init,另一種是別的已有的克隆一個出來,執行git clone 如git clone git://github.com/schacon/grit.git。

[root@wrlinux3 mygit]# git init
Reinitialized existing Git repository in /work/bongos/mygit/.git/
[root@wrlinux3 mygit]# git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#    new file:   test.c
#
[root@wrlinux3 mygit]# ls
test.c
[root@wrlinux3 mygit]# vi README
[root@wrlinux3 mygit]# git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#    new file:   test.c
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#    README
[root@wrlinux3 mygit]#

GIT是分佈式,GIT在任何一個地方的倉庫都保存全部的信息,但絕大部分項目團隊爲了開發協同的需要,通常建立一個遠程倉庫來協同相互之間的開發,也就是說大家都與遠程倉庫進行同步,就實現了相互之間的同步。GIT本地與遠程之間支持多種協議,常見git/https等。遠程倉庫通常以URL形貌提供,但實際上它是一個有命名的。通常默認是origin。對遠程倉庫如何操作管理,有一些常用的命令,如下:

1)查看遠程庫 git remote –v  或者git remote show origin

[root@wrlinux3 android]# git remote -v
origin    git://git.videolan.org/vlc-ports/android.git (fetch)
origin    git://git.videolan.org/vlc-ports/android.git (push)
[root@wrlinux3 android]# git remote
origin
[root@wrlinux3 android]# git remote show origin
* remote origin
  Fetch URL: git://git.videolan.org/vlc-ports/android.git
  Push  URL: git://git.videolan.org/vlc-ports/android.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (local out of date)
[root@wrlinux3 android]#

2)添加遠程庫 git remote add pt git://github.com/paulboone/ticgit.gi

3)抓取數據  git fetch pb這裏有兩個需要注意的是無端分支與本地分支它不是自動合併的到本地分支的。

[root@wrlinux3 android]# git fetch origin
remote: Counting objects: 86, done.
remote: Compressing objects: 100% (50/50), done.
remote: Total 60 (delta 40), reused 0 (delta 0)
Unpacking objects: 100% (60/60), done.
From git://git.videolan.org/vlc-ports/android
   628d90c..b88d59d  master     -&gt; origin/master
[root@wrlinux3 android]# cd vlc

4)推送數據 git push origin master

5)刪除遠程倉庫 git remote rename pb paul或者git remote rm paul

【3】git常用操作 GIT的操作方式與一般的SCM不同,通常的SCM是先檢出後工作再受近。GIT是在創建倉庫之後就可以對當前文件進行修改,也就是說默認狀態下所有文件都是可以修改的。修改後文件用戶可以提交倉庫GIT進行監管。如下圖所示:

image

下面將常用的操作命令結合起來示例如下圖所示:

image

下面演示一些常用的操作,這些操作包括刪除文件、重命名文件、撤消提交、撤消跟蹤、撤消修改及查看日誌:

1)刪除,採用git rm,單獨的rm只會將工作區中文件刪除,倉庫中沒有刪除,還有可能通過checkout檢出來進行恢復。如果使用git rm則會將文件從倉庫中刪除,不能恢復。

[root@wrlinux3 mygit]# git status
# On branch master
nothing to commit (working directory clean)
[root@wrlinux3 mygit]# ls
README  test.c
[root@wrlinux3 mygit]# rm README
rm: remove regular file `README'? y
[root@wrlinux3 mygit]# git status
# On branch master
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#    deleted:    README
#
no changes added to commit (use "git add" and/or "git commit -a")
[root@wrlinux3 mygit]# git checkout README
[root@wrlinux3 mygit]# ls
README  test.c
[root@wrlinux3 mygit]# git rm README
rm 'README'
[root@wrlinux3 mygit]# git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#    deleted:    README
#
[root@wrlinux3 mygit]# ls -latr
total 16
drwxr-xr-x. 12 root root 4096 Apr 20 15:27 ..
-rw-r--r--.  1 root root   18 Apr 20 15:27 test.c
drwxr-xr-x.  3 root root 4096 Apr 26 16:35 .
drwxr-xr-x.  8 root root 4096 Apr 26 16:35 .git
[root@wrlinux3 mygit]# git checkout README
error: pathspec 'README' did not match any file(s) known to git.
[root@wrlinux3 mygit]# git commit -m "delete "
[master 24c6871] delete
1 file changed, 7 deletions(-)
delete mode 100644 README
[root@wrlinux3 mygit]# git statue
git: 'statue' is not a git command. See 'git --help'.

Did you mean this?
    status
[root@wrlinux3 mygit]# git st
# On branch master
nothing to commit (working directory clean)
[root@wrlinux3 mygit]#

2)重命名文件,相當於先刪除後加入 git mv

[root@wrlinux3 mygit]# vi readme
[root@wrlinux3 mygit]# git commit -a -m "new readme commit"
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#    readme
nothing added to commit but untracked files present (use "git add" to track)
[root@wrlinux3 mygit]# git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#    readme
nothing added to commit but untracked files present (use "git add" to track)
[root@wrlinux3 mygit]# git commit -a -m "new readme commit"
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#    readme
nothing added to commit but untracked files present (use "git add" to track)
[root@wrlinux3 mygit]# ls
readme  test.c
[root@wrlinux3 mygit]# git add readme
[root@wrlinux3 mygit]# git commit -a -m "new readme commit"
[master e529597] new readme commit
1 file changed, 1 insertion(+)
create mode 100644 readme
[root@wrlinux3 mygit]# git status
# On branch master
nothing to commit (working directory clean)
[root@wrlinux3 mygit]# git mv readme README
[root@wrlinux3 mygit]# git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#    renamed:    readme -&gt; README
#
[root@wrlinux3 mygit]# git commit -a -m "move file name"
[master 1868051] move file name
1 file changed, 0 insertions(+), 0 deletions(-)
rename readme =&gt; README (100%)
[root@wrlinux3 mygit]# git status
# On branch master
nothing to commit (working directory clean)

3)git log 可以顯示操作日誌,有多種方式,格式化也行,使用gitk圖形化展示也可以。
[root@wrlinux3 mygit]# git log
commit 1868051cb93d4223a27f91b55b15e5b1cc3ab980
Author: PROJ proj <[email protected]>
Date:   Thu Apr 26 16:44:18 2012 +0800

    move file name

commit e529597105dded8688536ab5b37118e2597f8956
Author: PROJ proj <[email protected]>
Date:   Thu Apr 26 16:43:19 2012 +0800

    new readme commit

commit 24c68710bad22d65319acb3776ea70ca1720df0a
Author: PROJ proj <[email protected]>
Date:   Thu Apr 26 16:37:43 2012 +0800

    delete

commit 5399ad857c13085e00af125f04e5d3be2d22febc
Author: PROJ proj <[email protected]>
Date:   Wed Apr 25 17:31:12 2012 +0800

    the forth commit

commit 5cb0791c037545f3167c6af179a13dbdd5f395fe
Author: PROJ proj <[email protected]>
Date:   Wed Apr 25 17:30:07 2012 +0800

    third commit

commit 1776744b25f0c15d1d3947307bbf9aaf7cefbb7e
Author: PROJ proj <[email protected]>
Date:   Wed Apr 25 15:24:05 2012 +0800

    second commit
[root@wrlinux3 mygit]#

4)撤消暫存文件 git reset HEAD filename

[root@wrlinux3 mygit]# vi teset1.c
[root@wrlinux3 mygit]# git add teset1.c
[root@wrlinux3 mygit]# git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#    new file:   teset1.c
#
[root@wrlinux3 mygit]# git reset HEAD teset1.c
[root@wrlinux3 mygit]# git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#    teset1.c
nothing added to commit but untracked files present (use "git add" to track)
[root@wrlinux3 mygit]#

5)撤消當前的修改,如果當前的修改還未提交,不想修改時,可以使用checkout恢復,但是修復僅限於兩個狀態之間,也就是如果文件當前在COMMIT時,可以直接恢復工作區的版本。如果當前文件在STAGE時,這時只能用RESET來恢復。

[root@wrlinux3 mygit]# vi test.c
[root@wrlinux3 mygit]# git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#    modified:   test.c
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#    teset1.c
no changes added to commit (use "git add" and/or "git commit -a")
[root@wrlinux3 mygit]# git checkout test.c
[root@wrlinux3 mygit]# git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#    teset1.c
nothing added to commit but untracked files present (use "git add" to track)
[root@wrlinux3 mygit]# vi tes
6)撤消提交操作git commit --amend

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