內(nèi)容提要
- 忽略文件
- 忽略目錄的四種不同方式
/mytmp
/mytmp/*
**/mytmp
**/mytmp/*
- 例外
- 用
!
表示例外挚赊; - 作用于
/mytmp/*
突雪,不能作用于/mytmp
- ignore 生效的前提
- 通配符語法
- 一個星表示任意字符交播;
- 兩個星表示任意路徑摔敛。
- 兩種形式:共享式和獨(dú)享式
- 官方模板
語法
當(dāng)我們進(jìn)行代碼開發(fā)時,把代碼存到遠(yuǎn)程代碼庫上掷漱。但是總有一些代碼是不需要上傳的粘室,比如編譯的中間文件,單元測試自動生成的測試報告等卜范。這個時候我們需要告訴git
衔统,哪些文件應(yīng)該忽略,git
提供了這種機(jī)制海雪,它通過.gitignore
配置文件來實(shí)現(xiàn)锦爵。通常該文件放在項(xiàng)目的根目錄下,我們可以手動創(chuàng)建它奥裸,然后編輯內(nèi)容险掀。
忽略文件
在 .gitignore
文件中編輯:
#.gitignore for java
*.class
第一行以#
開頭的是注釋,*.class
表示忽略“所有”以.class
為后綴的文件(其中*
號表示glob模式匹配的通配符)湾宙。這里的“所有”無論它在哪個目錄下樟氢。
實(shí)驗(yàn)驗(yàn)證下,創(chuàng)建多級子目錄创倔,每個目錄創(chuàng)建一個.class
文件嗡害,結(jié)構(gòu)如下:
? demo-gitignore git:(master) tree
.
├── L1.class
└── child1
├── L2.class
└── child2
├── L3.class
└── child3
└── L4.class
3 directories, 4 files
執(zhí)行git status
,看看有沒有被忽略畦攘?
? demo-gitignore git:(master) git status
On branch master
Initial commit
nothing to commit (create/copy files and use "git add" to track)
當(dāng)然也可以不用通配符,例如
# project specified gitignore
Hello.xml
表示忽略“所有”名字叫Hello.xml
的文件十电。
忽略目錄
語法上知押,以/
開頭的表示忽略目錄。比如/mytmp
表示忽略“根目錄下”名叫mytmp
的目錄鹃骂,并非表示“所有”台盯。
在上述3個childX目錄下,各自創(chuàng)建一個mytmp
子目錄(實(shí)驗(yàn)時請勿用tmp
畏线,以免用戶目錄下的~/.gitignore
已經(jīng)配置過忽略tmp
)静盅,并在每個mytmp
目錄下創(chuàng)建Hello.xml
文件(因?yàn)槿绻麤]有文件,git不會理會空目錄的)。
形如:
demo-gitignore
├── child1
│ ├── child2
│ │ ├── child3
│ │ │ └── mytmp
│ │ │ └── Hello.xml
│ │ └── mytmp
│ │ └── Hello.xml
│ └── mytmp
│ └── Hello.xml
└── mytmp
└── Hello.xml
? demo-gitignore git:(master) ? git status -s
?? child1/
?? mytmp/
在.gitignore
中添加/mytmp
忽略后蒿叠,再看status:
? demo-gitignore git:(master) ? git status -s
M .gitignore
?? child1/
首先發(fā)現(xiàn)?? mytmp/
已經(jīng)不見了(被忽略了)明垢。第一行.gitignore的變化是因?yàn)閯偺砑?code>/mytmp,尚未提交市咽;第二行?? child1/
為什么還在痊银?因?yàn)槲覀冎皇呛雎粤?code>/mytmp目錄,并沒有忽略其下的文件Hello.xml施绎?其實(shí)是只忽略根目錄下的/mytmp
溯革,子目錄下的/mytmp
并不被忽略。
? demo-gitignore git:(master) ? git add child1
? demo-gitignore git:(master) ? git status -s
M .gitignore
A child1/child2/child3/mytmp/Hello.xml
A child1/child2/mytmp/Hello.xml
A child1/mytmp/Hello.xml
上述唯獨(dú)沒有提到根目錄demo-gitignore
下的mytmp
目錄谷醉。如果要讓所有目錄下的mytmp
目錄都被忽略呢致稀? 前綴加兩個*
號(即:**
)。
# project specified gitignore
**/mytmp
此時mytmp
,都不再顯示帘靡,無論是哪級子目錄:
? demo-gitignore git:(master) ? git status -s
M .gitignore
如果我們要“排除(不忽略)” /child1/child2/mytmp
目錄呢斧蜕?
用!/child1/child2/mytmp
排除。
# project specified gitignore
**/mytmp
!/child1/child2/mytmp
結(jié)果驗(yàn)證如下:
? demo-gitignore git:(master) ? git status -s
M .gitignore
A child1/child2/mytmp/Hello.xml
總結(jié)備忘
以
/
開頭忽略目錄臭猜,表示當(dāng)前。例如/mytmp
表示忽略根目錄下的mytmp押蚤。
以**/
開頭蔑歌,忽略所有目錄。例如**/mytmp
表示忽略所有層級下的mytmp目錄揽碘。
用!
開頭表示例外次屠。例如!/child1/child2/mytmp
表示單獨(dú)強(qiáng)調(diào)“不忽略”/child1/child2/mytmp的 mytmp 目錄。
忽略的例外
如前文所說雳刺,例外用!
表示劫灶。這里補(bǔ)充下關(guān)于“文件”的例外。在上述的實(shí)驗(yàn)環(huán)境中掖桦,新創(chuàng)建文件 demo-gitignore/mytmp/HelloExpectional.xml
本昏,并配置.gitignore
如下:
# project specified gitignore
/mytmp/*
!/mytmp/HelloExpectional.xml
它表示忽略根目錄/下的mytmp子目錄下的所有文件(星號表示),但是/mytmp/HelloExpectional.xml
文件例外(不忽略)枪汪。
? demo-gitignore git:(master) ? git add .
? demo-gitignore git:(master) ? git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: .gitignore
new file: child1/child2/child3/mytmp/Hello.xml
new file: child1/child2/mytmp/Hello.xml
new file: child1/mytmp/Hello.xml
new file: mytmp/HelloExpectional.xml
如上結(jié)果涌穆,只有mytmp/Hello.xml被忽略。如預(yù)期雀久。如果要所有mytmp呢宿稀?用**/tmp
呀。
為什么ignore 沒生效赖捌?
緊接著上面祝沸,把.gitignore
內(nèi)容修改為:
# project specified gitignore
**/mytmp/*
!/mytmp/HelloExpectional.xml
查看status,發(fā)現(xiàn)并沒有變化?
? demo-gitignore git:(master) ? git status -s
MM .gitignore
A child1/child2/child3/mytmp/Hello.xml
A child1/child2/mytmp/Hello.xml
A child1/mytmp/Hello.xml
A mytmp/HelloExpectional.xml
預(yù)期應(yīng)該是只有mytmp/HelloExceptional.xml
不被忽略罩锐,其他均被忽略奉狈。新配置為什么沒生效?因?yàn)榍拔?code>git add .的時候唯欣,已經(jīng)加入git索引了嘹吨,gitignore只能對untracked
狀態(tài)的資源起作用。
先把他們從tracked (to be committed)
中撤掉:
? demo-gitignore git:(master) ? git rm --cached -r child1
rm 'child1/child2/child3/mytmp/Hello.xml'
rm 'child1/child2/mytmp/Hello.xml'
rm 'child1/mytmp/Hello.xml'
? demo-gitignore git:(master) ? git rm --cached -r mytmp
rm 'mytmp/HelloExpectional.xml'
? demo-gitignore git:(master) ?
命令解釋如下:
git rm --cached
表示直接刪除“索引區(qū)”的內(nèi)容(不是導(dǎo)出到Working dir境氢,也不是提交到版本庫)蟀拷。后面接文件,表示操作對象萍聊;-r
是當(dāng)操作對象為目錄時问芬,表示遞歸。
接著實(shí)驗(yàn)看看新的ignore規(guī)則:
? demo-gitignore git:(master) ? git add .
? demo-gitignore git:(master) ? git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: .gitignore
new file: mytmp/HelloExpectional.xml
目錄忽略寿桨,它的子目錄和文件呢此衅?
當(dāng)我們忽略一個目錄時,它下面的子目錄和文件也一起被忽略嗎亭螟?
在demo-gitignore/mytmp
創(chuàng)建一級子目錄son-of-mytmp
和二級子目錄grandson-of-mytmp
挡鞍,并各自放一個文件,如下結(jié)構(gòu):
? demo-gitignore git:(master) ? tree mytmp
mytmp
├── Hello.xml
├── HelloExpectional.xml
└── son-of-mytmp
├── grandson-of-mytmp
│ └── grandson.xml
└── son.xml
2 directories, 4 files
ignore配置:
# project specified gitignore
/mytmp
!/mytmp/HelloExpectional.xml
查看狀態(tài):
? demo-gitignore git:(master) ? git status -s
M .gitignore
?? child1/
的的確確 根目錄下的mytmp目錄及其子目錄预烙,都被忽略了墨微。但與此同時奇怪的是!/mytmp/HelloExpectional.xml
“例外設(shè)置”并沒有生效?
如果調(diào)整 ignore 設(shè)置:
# project specified gitignore
/mytmp/*
!/mytmp/HelloExpectional.xml
從/mytmp
調(diào)整為/mytmp/*
扁掸,結(jié)果例外生效了翘县。
? demo-gitignore git:(master) ? git add .
? demo-gitignore git:(master) ? git status -s
M .gitignore
A child1/child2/child3/mytmp/Hello.xml
A child1/child2/mytmp/Hello.xml
A child1/mytmp/Hello.xml
A mytmp/HelloExpectional.xml
總結(jié)備忘
忽略目錄
/mytmp
和/mytmp/*
,都會遞歸影響其子目錄和文件的忽略谴分。
只有/mytmp/*
忽略锈麸,才能添加形如!/mytmp/HelloExpectional.xml
的例外。
glob模式語法
所謂“glob模式”就是我們常見的bash下簡化的正則表達(dá)式牺蹄。就4招:
- 星號
*
忘伞,通配多個字符; - 兩個星號
**
沙兰,表示任意中間層目錄虑省。例如a/**/z
可以匹配目錄a/z
,a/b/z
或a/b/c/z
等。 - 問號
?
僧凰,通配單個字符; - 方號
[]
熟丸,枚舉單個字符训措。例如[abc]
表示要么a
,要么b
,要么c
绩鸣,但是ab
兩個字符是不能匹配的怀大,只能是1個。 - 范圍
[0-9]
或[a-z]
表示任意一個數(shù)字或字母呀闻。 - 嘆號
!
化借,表示“取反”,表示“不忽略”的語義捡多。
使用習(xí)慣
基本概念
-
.gitignore
文件是項(xiàng)目根目錄下的一個隱藏文件蓖康,不是.git
子目錄下的。 -
.gitignore
文件對其所在的目錄及其全部子目錄均有效垒手。當(dāng)然用戶級HOME目錄下~/.gitignore
文件全局有效蒜焊,項(xiàng)目的ignore繼承覆蓋用戶級的。 - 配置文件
.gitignore
本身需要加入版本庫科贬,以便其他組員能共享同一套資源忽略管理規(guī)則泳梆。
? demo-gitignore git:(master) ? touch .gitignore
? demo-gitignore git:(master) ? git status -s
?? .gitignore
? demo-gitignore git:(master) ? git add .gitignore
? demo-gitignore git:(master) ? git commit .gitignore -m 'create project specified gitignore conf'
共享式 與 獨(dú)享式
ignore 規(guī)則既可以選擇“共享式”讓全組員使用同樣的規(guī)則(文件位置是項(xiàng)目根目錄下的.gitignore
文件),好處是大家的配置一樣榜掌,不好是.gitignore
內(nèi)容太多优妙,維護(hù)太累。也可以選擇“獨(dú)享式”憎账,只對自己生效套硼,其他組員看不到(因?yàn)槎疾簧蟼鞯桨姹編欤鼠哥!蔼?dú)享式”有兩種形式:
- 用戶級的 位置在
~/.gitignore
用戶HOME目錄下熟菲; - 項(xiàng)目級的 位置在
.git/info/exclude
,它也是一個ignore文件朴恳,語法規(guī)則是一樣的抄罕。注意:盡管.git
目錄一定是要上傳到版本庫的(它就是版本庫本身),但是卻留下了exclue
是不上傳的于颖。感覺.git
的設(shè)計(jì)者很有用心呆贿。
那我們什么時候共享式,什么時候獨(dú)享式呢森渐?個人覺得做入,更多的是團(tuán)隊(duì)的一個約定。我們可以先對需要ignore的東西同衣,做個大致分類:
-
操作系統(tǒng)層面的 比如Mac OS的
.DS_Store
竟块, windows的Thumbs.db
; -
IDE層面的 比如Eclipse的
.project
,.settings/
和.classpath
耐齐。 IDE層面還包括“樸素IDE”浪秘,比如臨時用VIM應(yīng)急修改了個東西蒋情,意外的閃崩生成了一個.swap
文件或有些編輯器會生成.bak
備份文件。 - 中間結(jié)果類 比如程序運(yùn)行一下耸携,就打些日志到文件棵癣。再比如嵌入式數(shù)據(jù)庫生成的臨時文件。
- 語言相關(guān)的 剛說的“中間結(jié)果”日志類的是通用的夺衍,無論哪種語言開發(fā)的程序都會輸出日志狈谊,除此外,還有喝多跟語言編譯相關(guān)的沟沙,比如JAVA的.class字節(jié)碼河劝,比如Web項(xiàng)目構(gòu)建時生成的.war包。
了解這些后尝胆,或許我們可以把前面兩類作為“獨(dú)享式”只作用于自己本地丧裁,比如你用Mac那你配Mac的ignore,用Eclipse配Eclipse的含衔;別人用Window煎娇,他自己配置Windows的。然后把中間結(jié)果和語言相關(guān)的贪染,弄成“共享式”的缓呛,在全組員中共享。
這么多配置需要我們自己寫嗎杭隙? 當(dāng)然不用哟绊,這些問題很多開發(fā)者都是要遇到同樣的問題的,把各種環(huán)境窮舉下痰憎? 事實(shí)上有人給我們做了票髓。
官方ignore模板
官方提供ignore模板 https://github.com/github/gitignore
它的組織形式就是按上文說的“分層組織”。比如:
- 系統(tǒng)層
- Mac的: macOS.gitignore
- Linux的: Linux.gitignore
- IDE層
- Eclipse的: Eclipse.gitignore
- VIM樸素編輯器的: Vim.gitignore
- NetBeans的: NetBeans.gitignore
- 語言層
- JAVA的:Java.gitignore
- GO的: Go.gitignore
- LUA的: Lua.gitignore
- C的:C.gitignore
- C++的: C++
附錄1:如何刪除已經(jīng)提交铣耘,但不需要提交的資源洽沟?
盡管提倡項(xiàng)目開始的時候,就需要對資源ignore 規(guī)則進(jìn)行設(shè)置蜗细。但是現(xiàn)實(shí)常常沒有那么理想裆操,往往提交后才發(fā)現(xiàn)提交了一些不應(yīng)該提交的東西。怎么刪除它們炉媒?
首先要區(qū)分兩類刪除:
真的不需要的踪区,比如每次編譯產(chǎn)生的
.class
,這些文件真的不需要吊骤。需要缎岗,但不想提交到版本庫的。比如某些臨時的document白粉,你打算提交到wiki密强,而不是版本庫茅郎。
找出“已經(jīng)提交,但不需要提交的”資源
從遠(yuǎn)程拷貝一份或渤。之所以這么做,不用當(dāng)前本地的奕扣,是因?yàn)閕gnore規(guī)則的存在薪鹦,本地一定與遠(yuǎn)程不是完全一致的(從文件系統(tǒng)的角度說的完全一致,不是git diff角度)惯豆。
git clone http://10.77.144.192:11824/blueocean/passport.git
然后池磁,比如假設(shè)我們之前誤提交了.class
文件,那么需要找出:
find . -name "*.class"
發(fā)現(xiàn)./WebRoot/WEB-INF/classes/
下面居然有楷兽,刪除它們地熄。同時在新拷貝的和本地現(xiàn)有的都刪除。