linus研發(fā),分布式版本控制工具;
- Git is :
- 目錄內容管理系統(tǒng)
- 樹狀的歷史存儲系統(tǒng)
- 傻瓜式的內容追蹤器
- 一個工具箱:a toolkit
- git 命令有兩種
- the “plumbing”:低級命令
- the “porcelain”:高級命令
- 版本控制系統(tǒng)的兩種常見的邏輯:
- delta storage:增量存儲系統(tǒng)
- DAG storage:有向無環(huán)圖
- 版本控制系統(tǒng)的三種形式:
- local:本地版本控制系統(tǒng)
- centralized:有中心節(jié)點的集中版本控制系統(tǒng)
- distributed:分布式的版本控制系統(tǒng)
- 常見版本控制系統(tǒng)解決方案:
- delta storage:
- local:rcs
- centralized:cvs-->svn,perfirce
- distributed:darcs, mercurial(商業(yè)化)
- DAG storage:
- local:cp -r,timemachine
- centralized:bitkeeper
- distributed:git,bazaar
- delta storage:
git是通過記錄快照的方式來實現(xiàn)文件內容保留的,它不是記錄差異;但是,git在倉庫中保留的每一個文件進行追蹤時,采用獨特的方式,沒一個文件的名稱在倉庫中,這個倉庫只是文件追蹤系統(tǒng),它只追蹤內容,意味著僅保留文件內容的變化,至于文件叫什么名,文娛哪個目錄下,倉庫在文件內部是不加任何保留的;
git倉庫是一個對象存儲系統(tǒng),所謂對象存儲,每一個文件的所有數(shù)據,無論是數(shù)據還是元數(shù)據都是自包含的,往存儲空間里存放的每一個文件,這個文件的所有屬性都是自包含;
所以每一個文件都是由著自己對自我結構描述屬性等信息的內容,所有稱作是完成而獨立的對象;
引用每一個對象時,只需要引用對象的一個符號鏈接或一個名稱就行;git版本倉庫里的內容就是對象存儲系統(tǒng);
例如,有一個文件需要保存到倉庫中,將來必要時能在倉庫中檢索出來原來的某個版本;這個文件在工作區(qū)中看是文件,而且是保存在文件系統(tǒng)上的文件,但是一旦把它納入到版本庫中去,就以為這它要被版本庫生成一個文件對象而保存在版本庫中;
git對每一個文件對象的名稱追蹤時,就需要對文件另起一個名字,這個名字很獨特是文件內容的哈希值;注意:文件名是文件內容的哈希值;可以使用MD5或sha取得文件的哈希碼,只要文件內容變化,它的哈希一定會改變;本來git的倉庫就是通過保存文件快照進行的,而它的快照保存機制就是只要文件內容變了就把這個文件復制一份新版本出來,重新創(chuàng)建個對象;
如果在工作區(qū)中有兩個文件不在同一個目錄下,但內容一摸一樣,在對象庫中起始只保存一個版本
在開發(fā)應用程序時,通常要創(chuàng)建個目錄,里面存放程序的代碼:
[root@node1 ~]# mkdir testproj
[root@node1 ~]# cd testproj/
為了能夠使這個代碼目錄下,將來把所有版本內容的變化可以基于版本進行追償,可以隨時回到過去的某個版本,通常就需要在這個目錄下創(chuàng)建一個隱藏目錄,里面記錄這個工作目錄當中的每一個文件在需要保存狀態(tài)時的狀態(tài)變化;
所以,對應testproj就叫做工作目錄,在工作目錄下就會有版本庫自動生成版本倉庫;
-
.git 隱藏目錄不需要手動創(chuàng)建,使用git init 命令自動生成:
[root@node1 testproj]# git init Initialized empty Git repository in /root/testproj/.git/ [root@node1 testproj]# ls -a . .. .git -
git隱藏目錄(版本庫)內部有兩個主要部分組成,第一個部分叫索引(暫存區(qū)),第二部分叫對象庫
工作目錄中有2個文件,當需要記錄過去狀態(tài)是要保存版本庫,就把工作目錄中的文件創(chuàng)建成文件對象,添加到對象庫中;這個添加過程分2步:- 第一步叫暫存
暫存就是在索引中把當前工作目錄中一共有多少文件、每個文件路徑、和它對應的哈希碼在倉庫中記錄一個快照;索引中記錄的就是工作目錄中的文件名和對象庫中的文件名一一對應的表,而這個內容就是一個快照,酷照是工作目錄中的目錄結構和對象庫中文件的對應關系,這就是暫存;還有個快照是在對象庫中快照的文件內容; - 第二步叫提交
所謂提交就是把索引中的快照,也要保存在對象庫中;保存在對象庫中的索引叫版本樹,因為它記錄的是文件的目錄樹結構,所以被稱作樹對象;文件被稱作文件對象;還有一個對象叫分支;一旦完成了提交,就意味著把索引中記錄的當前的樹快照,也給它保存在對象庫當中,生成一個樹對象,將來為了引用樹序列,需要一個紙箱這個數(shù)最開始出的指針;這個就稱作一個分支;
提交后,索引中的內容依然存在是指向對象庫中的文件對象的,而對象庫中的索引樹也是指向文件對象的;
當對工作目錄中的文件修改后,再做暫存時,對象庫中就會又創(chuàng)建一個新對象;
此時,索引中的內容發(fā)生變化了,但對象庫中的索引對象并沒有變;所以,當修改文件再次暫存時,文件內容發(fā)生改變,文件對象也發(fā)生改變,由此索引當中的樹對象,對于沒改變的文件依然指向老版本,對于已發(fā)生改變的文件則指向新版本;但是,此前的提交就是為了追蹤過去版本的,是不會改變的;
這只是暫存,當你再做提交時,就會在對象庫中自動生成一個新的索引對象,就是把索引中的內容做個快照保存一個新的樹(索引)對象;這個新的樹對象則指向文件的新版本,沒有變化的文件還是指向老版本;而這兩個樹對象是有先后關系的;
不斷暫存、提交時間久了以后,會生成一個鏈式關系;使用head可以指向去過對象庫中的老版本;如果當前工作目錄中有文件指向老版本時,可能會丟失;
- 第一步叫暫存
git的安裝基本使用
-
安裝:git官方站點:https://git-scm.com/
[root@node1 ~]# yum info git #git已經收錄在base倉庫 [root@node1 ~]# yum list all git* Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * epel: mirrors.tuna.tsinghua.edu.cn Installed Packages git.x86_64 1.8.3.1-14.el7_5 @updates Available Packages GitPython.noarch 1.0.1-7.el7 epel git.x86_64 1.8.3.1-20.el7 updates git-all.noarch 1.8.3.1-20.el7 updates git-annex.x86_64 5.20140221-1.2.el7 epel git-bzr.noarch 1.8.3.1-20.el7 updates git-cal.noarch 0.9.1-3.el7 epel git-cola.noarch 2.10-1.el7 epel git-cvs.noarch 1.8.3.1-20.el7 updates git-daemon.x86_64 1.8.3.1-20.el7 updates git-email.noarch 1.8.3.1-20.el7 updates git-extras.noarch 4.6.0-3.el7 epel git-gnome-keyring.x86_64 1.8.3.1-20.el7 updates git-gui.noarch 1.8.3.1-20.el7 updates git-hg.noarch 1.8.3.1-20.el7 updates git-instaweb.noarch 1.8.3.1-20.el7 updates git-lfs.x86_64 2.4.2-2.el7 epel git-merge-changelog.x86_64 0-14.20150325git.el7 epel git-p4.noarch 1.8.3.1-20.el7 updates git-publish.noarch 1.4.4-4.el7 epel git-review.noarch 1.24-5.el7 epel git-svn.x86_64 1.8.3.1-20.el7 updates git-tools.noarch 2017.10-1.el7 epel git-xcleaner.noarch 1.5-1.el7 epel git2cl.noarch 2.0-0.8.git8373c9f.el7 epel gitflow.noarch 0.4.2.20120723git53e9c76-4.el7 epel gitg.x86_64 3.26.0-1.el7 epel gitg-devel.x86_64 3.26.0-1.el7 epel gitg-libs.x86_64 3.26.0-1.el7 epel github2fedmsg.noarch 0.3.6-1.el7 epel gitk.noarch 1.8.3.1-20.el7 updates gitolite3.noarch 1:3.6.10-1.el7 epel gitstats.noarch 0-0.6.20130723gita923085.el7 epel gitweb.noarch 1.8.3.1-20.el7 updates
git在本地工作的模式
-
在本地如何實現(xiàn)版本控制:
[root@node1 ~]# yum -y install git [root@node1 ~]# git --help 用法: git [--version] [--help] [-c name=value] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path] [-p|--paginate|--no-pager] [--no-replace-objects] [--bare] [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>] <command> [<args>] 最常用的git命令: add Add file contents to the index #添加文件內容至索引 bisect Find by binary search the change that introduced a bug #通過二分查找丁文引入bug branch List, create, or delete branches #列出、創(chuàng)建或刪除分支 checkout Checkout a branch or paths to the working tree #檢出一個分支或路徑到工作區(qū) clone Clone a repository into a new directory #克隆一個版本庫到一個新目錄 commit Record changes to the repository #記錄變更到版本庫 diff Show changes between commits, commit and working tree, etc #顯示提交之間、提交和工作區(qū)之間等的差異 fetch Download objects and refs from another repository #從另外一個版本庫下載對象和引用 grep Print lines matching a pattern #輸出和模式匹配的行 init Create an empty Git repository or reinitialize an existing one #創(chuàng)建一個空的git版本看或重新初始化一個已存在的版本庫 log Show commit logs #顯示提交日志 merge Join two or more development histories together #合并兩個或更多開發(fā)歷史 mv Move or rename a file, a directory, or a symlink #移動或重命名一個文件目錄或符號鏈接 pull Fetch from and merge with another repository or a local branch #獲取合并另外的版本庫或一個本地分支 push Update remote refs along with associated objects #更新遠程引用和相關的對象 rebase Forward-port local commits to the updated upstream head #本地提交轉移至跟新后的上游分支中 reset Reset current HEAD to the specified state #重置當前HEAD到指定狀態(tài) rm Remove files from the working tree and from the index #從工作去和索引中刪除文件 show Show various types of objects #顯示各種類型的對象 status Show the working tree status #顯示工作區(qū)狀態(tài) tag Create, list, delete or verify a tag object signed with GPG #創(chuàng)建、列出、刪除或校驗一個GPG簽名的tag對象示例:
如上文中創(chuàng)建的目錄testproj[root@node1 ~]# cd testproj/ [root@node1 testproj]# tree .git .git ├── branches ├── config ├── description ├── HEAD ├── hooks │ ├── applypatch-msg.sample │ ├── commit-msg.sample │ ├── post-update.sample │ ├── pre-applypatch.sample │ ├── pre-commit.sample │ ├── prepare-commit-msg.sample │ ├── pre-push.sample │ ├── pre-rebase.sample │ └── update.sample ├── info │ └── exclude ├── objects │ ├── info │ └── pack └── refs ├── heads └── tags
初始化以后,創(chuàng)建了好多文件:
branches:分支
config:當前版本倉庫的配置;對于git配置有三個等級:
- 系統(tǒng)等級:對所有工作在當前系統(tǒng)上的用戶都有效的配置;
- 全局等級:對當前用戶全局;一個用戶可能維護有n個倉庫,這n個倉庫都共享的配置;
- 倉庫等級:每個倉庫自己獨有的配置;
HEAD:指向最新的樹對象
objects:對象庫目錄
演示:
此時沒有index目錄,因為還沒有添加文件,創(chuàng)建文件后自動生成
[root@node1 testproj]# cp /etc/passwd ./
[root@node1 testproj]# vim README
Project: test project
[root@node1 testproj]# ls
passwd README
[root@node1 testproj]# git add . #暫存工作目錄下所有文件,也可以使用git add -a
[root@node1 testproj]# tree .git
.git
├── branches
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── objects
│ ├── 63
│ │ └── 452156647080f0f17e0d0cb14d7c1f1f90e22e
│ ├── 78
│ │ └── 270f5908030219758738a85d499b8bfe6baa2b
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
11 directories, 16 files
此時自動創(chuàng)建了index目錄,用來存放暫存區(qū)的數(shù)據
[root@node1 testproj]# file .git/index
.git/index: Git index, version 2, 2 entries
[root@node1 testproj]# vim README
[root@node1 testproj]# git add README
Project: test project
version1.1.0
[root@node1 testproj]# tree .git
.git
├── branches
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── objects
│ ├── 63
│ │ └── 452156647080f0f17e0d0cb14d7c1f1f90e22e
│ ├── 78
│ │ └── 270f5908030219758738a85d499b8bfe6baa2b
│ ├── 7a
│ │ └── 7f3b22a21932aefe2b204fe528475ca358d422
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
12 directories, 17 files
此時修改了README文件內容后重新暫存后objects目錄下多了一個目錄
[root@node1 testproj]# mkdir docs
[root@node1 testproj]# touch docs/changelog
[root@node1 testproj]# git add docs
[root@node1 testproj]# tree .git
.git
├── branches
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── objects
│ ├── 63
│ │ └── 452156647080f0f17e0d0cb14d7c1f1f90e22e
│ ├── 78
│ │ └── 270f5908030219758738a85d499b8bfe6baa2b
│ ├── 7a
│ │ └── 7f3b22a21932aefe2b204fe528475ca358d422
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
12 directories, 17 files
此時暫存區(qū)未發(fā)生改變,因為git add 不追蹤空目錄
[root@node1 testproj]# vim docs/changelog
auth: magedu
[root@node1 testproj]# git add docs/
[root@node1 testproj]# tree .git
.git
├── branches
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── objects
│ ├── 63
│ │ └── 452156647080f0f17e0d0cb14d7c1f1f90e22e
│ ├── 78
│ │ └── 270f5908030219758738a85d499b8bfe6baa2b
│ ├── 7a
│ │ └── 7f3b22a21932aefe2b204fe528475ca358d422
│ ├── 7e
│ │ └── 184b2a7d9bd622e74df67fbc6a9f75345090db
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
13 directories, 18 files
此時在objects目錄下多了一個目錄,有內容的東西才能作為對象存儲
[root@node1 testproj]# git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: README
# new file: docs/changelog
# new file: passwd
#
[root@node1 testproj]# git rm --cached passwd
rm 'passwd'
[root@node1 testproj]# ls
docs passwd README
[root@node1 testproj]# git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: README
# new file: docs/changelog
#
--cached是指刪除緩存內的文件,不刪除工作目錄下的文件
git配置文件分為三種:
- 系統(tǒng)級:/etc/git/gitconfig
- 全局:~/.gitconfig --global
- 倉庫特有: REPO/.git/config --system
git 提交時必須要指明提交的用戶名和email信息,因此,在提交前需要先手動配置
[root@node1 testproj]# git config -l #列出當前版本庫的配置,此命令要在版本庫下執(zhí)行或直接查看.git/config
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
[root@node1 testproj]# cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
user.email:指明用戶的郵箱;
user.name:指明用戶的用戶名
[root@node1 testproj]# git config --global user.name "MageEdu"
[root@node1 testproj]# git config --global user.email "magedu@magedu.com"
[root@node1 testproj]# git config -l
user.name=MageEdu
user.email=magedu@magedu.com
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
因為使用的是全局級別,在用戶家目錄下會生成.gitconfig文件;
[root@node1 testproj]# ls -a /root/.gitconfig
/root/.gitconfig
[root@node1 testproj]# cat /root/.gitconfig
[user]
name = MageEdu
email = magedu@magedu.com
如果沒指明則是倉庫級別的:
[root@node1 testproj]# cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
git提交
每一次提交要指明變化說明,會自動打一個文件名;
如果不想使用文本編輯的交互式進行說明變化信息,也可以是用-m <msg>
[root@node1 testproj]# git commit -m "v0.0.1"
[master (root-commit) 7adf5fc] v0.0.1
3 files changed, 28 insertions(+)
create mode 100644 README
create mode 100644 docs/changelog
create mode 100644 passwd
[root@node1 testproj]# cd .git/objects/
[root@node1 objects]# ls 其中的兩數(shù)字的目錄為分層管理眾多的文件對象;
47 5d 63 78 7a 7e 89 be fc info pack
[root@node1 objects]# ll
total 0
drwxr-xr-x. 2 root root 52 Dec 19 23:10 47
drwxr-xr-x. 2 root root 52 Dec 19 23:11 5d
drwxr-xr-x. 2 root root 52 Dec 19 22:31 63
drwxr-xr-x. 2 root root 52 Dec 19 22:31 78
drwxr-xr-x. 2 root root 98 Dec 19 23:06 7a
drwxr-xr-x. 2 root root 52 Dec 19 22:43 7e
drwxr-xr-x. 2 root root 52 Dec 19 23:10 89
drwxr-xr-x. 2 root root 52 Dec 19 23:06 be
drwxr-xr-x. 2 root root 52 Dec 19 23:06 fc
drwxr-xr-x. 2 root root 6 Dec 19 20:35 info
drwxr-xr-x. 2 root root 6 Dec 19 20:35 pack
[root@node1 objects]# ll 89 #文件名就是文件內容的哈希碼;
total 4
-r--r--r--. 1 root root 111 Dec 19 23:10 6049330e920c53a53017258b8334e75b41c779
git-clone
- 用法:
git clone <repository> [<directory>]<repository>:指明要克隆的倉庫;-
<directory>:克隆到哪個位置;[root@node1 ~]# ls anaconda-ks.cfg testproj [root@node1 ~]# git clone testproj/ new Cloning into 'new'... done. [root@node1 ~]# ls #自動生成new目錄 anaconda-ks.cfg new testproj [root@node1 ~]# cat new/README Project: test project version1.1.0 version1.1.1
這就叫遠程倉庫,把遠程倉庫克隆到本地;這也是生成倉庫的第二種辦法;
所以,生成倉庫有兩種辦法:第一,創(chuàng)建新目錄,里面創(chuàng)建文件,添加、提交就生成倉庫了;第二,把別人的倉庫克隆到本地;
[root@node1 testproj]# vim INSTALL
[root@node1 testproj]# ls
docs INSTALL passwd README
[root@node1 testproj]# git add INSTALL
[root@node1 testproj]# git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: INSTALL
#
[root@node1 testproj]# git rm --cached INSTALL
rm 'INSTALL'
[root@node1 testproj]# git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# INSTALL
nothing added to commit but untracked files present (use "git add" to track)
[root@node1 testproj]# git ls-files
README
docs/changelog
passwd
[root@node1 testproj]# git add INSTALL
[root@node1 testproj]# git ls-files #顯示目錄樹種的內容
INSTALL
README
docs/changelog
passwd
[root@node1 testproj]# tree .git
.git
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 09
│ │ └── 5e68cb0e446afdccc74ca4f6e08add47106ab8
│ ├── 47
│ │ └── 9abf23993860872cded7d081e4a8622900dbca
│ ├── 5d
│ │ └── 6ed1a098f588ab6526fd3b53a1331d298d44af
│ ├── 63
│ │ └── 452156647080f0f17e0d0cb14d7c1f1f90e22e
│ ├── 78
│ │ └── 270f5908030219758738a85d499b8bfe6baa2b
│ ├── 7a
│ │ ├── 7f3b22a21932aefe2b204fe528475ca358d422
│ │ └── df5fc60c3e8829843257e47d22f30fdfb78d42
│ ├── 7e
│ │ └── 184b2a7d9bd622e74df67fbc6a9f75345090db
│ ├── 89
│ │ └── 6049330e920c53a53017258b8334e75b41c779
│ ├── be
│ │ └── 0e31953e749a2d94f7386c508c2b7900112b50
│ ├── fc
│ │ └── bc6dac21cf3af7e7acf87c602a7d96fa836a6a
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master
└── tags
22 directories, 29 files
git ls-files:列出文件;
git cat-fles:查看文件;
git hash-object:計算文件的hash碼;
git write-tree:根據當前索引中的內容創(chuàng)建樹對象;
簡單總結git版本庫:
git的版本庫就是存儲了所有用來維護和管理當前項目的修訂版本和歷史信息數(shù)據的一個數(shù)據庫;
所以版本庫就是數(shù)據庫里面記錄的大量的數(shù)據,存儲了版本庫當中所有文件的完整副本,甚至包括版本庫自身的副本都有;
除此之外,每個版本庫還保存了跟版本庫相關的一組元數(shù)據,就是版本庫提交者的用戶信息郵箱地址等;
克隆還可以復制倉庫內容,但只復制數(shù)據不復制元數(shù)據;
版本庫中有非常重要的兩個區(qū)域:緩存區(qū)和對象庫;
對象庫中有四類對象:塊、樹、提交、標簽;
而索引是個臨時的動態(tài)的二進制文件,用于描述某個時刻,整個工作目錄當中或整個版本庫當中某一個版本的狀態(tài)信息;
因為索引里面反應了要么是當前目錄里add進去的文件,要么是某一版本庫當中已經被提交的文件的映射信息;索引內容的隨時能變化的;
如果有多個版本都提交了, 如果此時整個工作目錄反應的是第一個版本,那么索引當中顯示的信息都是第一個版本中所有文件的映射信息;
如果此時讓工作目錄反應了第二個版本,索引中的文件立即會改變成第二個版本中所有文件映射信息了;所以說索引里面是臨時的、動態(tài)的信息;
如果當前沒有提交任何版本,只是add了一些數(shù)據,那么索引里反應的都是add進去文件的映射路徑;