手把手帶你玩git之gitignore

內(nèi)容提要

  • 忽略文件
  • 忽略目錄的四種不同方式
  • /mytmp
  • /mytmp/*
  • **/mytmp
  • **/mytmp/*
  • 例外
  • ! 表示例外;
  • 作用于/mytmp/*,不能作用于/mytmp
  • ignore 生效的前提
  • 通配符語(yǔ)法
  • 一個(gè)星表示任意字符;
  • 兩個(gè)星表示任意路徑
  • 兩種形式:共享式和獨(dú)享式
  • 官方模板

語(yǔ)法

當(dāng)我們進(jìn)行代碼開(kāi)發(fā)時(shí),把代碼存到遠(yuǎn)程代碼庫(kù)上。但是總有一些代碼是不需要上傳的,比如編譯的中間文件,單元測(cè)試自動(dòng)生成的測(cè)試報(bào)告等。這個(gè)時(shí)候我們需要告訴git,哪些文件應(yīng)該忽略,git提供了這種機(jī)制,它通過(guò).gitignore 配置文件來(lái)實(shí)現(xiàn)。通常該文件放在項(xiàng)目的根目錄下,我們可以手動(dòng)創(chuàng)建它,然后編輯內(nèi)容。

忽略文件

.gitignore文件中編輯:

#.gitignore for java
*.class

第一行以#開(kāi)頭的是注釋?zhuān)?code>*.class 表示忽略“所有”以.class為后綴的文件(其中*號(hào)表示glob模式匹配的通配符)。這里的“所有”無(wú)論它在哪個(gè)目錄下。

實(shí)驗(yàn)驗(yàn)證下,創(chuàng)建多級(jí)子目錄,每個(gè)目錄創(chuàng)建一個(gè).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,看看有沒(méi)有被忽略?

?  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的文件。

忽略目錄

語(yǔ)法上,以/開(kāi)頭的表示忽略目錄。比如/mytmp表示忽略“根目錄下”名叫mytmp的目錄,并非表示“所有”。

在上述3個(gè)childX目錄下,各自創(chuàng)建一個(gè)mytmp子目錄(實(shí)驗(yàn)時(shí)請(qǐng)勿用tmp,以免用戶(hù)目錄下的~/.gitignore已經(jīng)配置過(guò)忽略tmp),并在每個(gè)mytmp目錄下創(chuàng)建Hello.xml文件(因?yàn)槿绻麤](méi)有文件,git不會(huì)理會(huì)空目錄的)。

形如:

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)不見(jiàn)了(被忽略了)。第一行.gitignore的變化是因?yàn)閯偺砑?code>/mytmp,尚未提交;第二行?? child1/為什么還在?因?yàn)槲覀冎皇呛雎粤?code>/mytmp目錄,并沒(méi)有忽略其下的文件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ú)沒(méi)有提到根目錄demo-gitignore下的mytmp目錄。如果要讓所有目錄下的mytmp目錄都被忽略呢? 前綴加兩個(gè)*號(hào)(即:**)。

# project specified gitignore
**/mytmp

此時(shí)mytmp,都不再顯示,無(wú)論是哪級(jí)子目錄:

?  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é)備忘

/開(kāi)頭忽略目錄,表示當(dāng)前。例如/mytmp表示忽略根目錄下的mytmp。
**/開(kāi)頭,忽略所有目錄。例如**/mytmp表示忽略所有層級(jí)下的mytmp目錄。
!開(kāi)頭表示例外。例如!/child1/child2/mytmp表示單獨(dú)強(qiáng)調(diào)“不忽略”/child1/child2/mytmp的 mytmp 目錄。

忽略的例外

如前文所說(shuō),例外用!表示。這里補(bǔ)充下關(guān)于“文件”的例外。在上述的實(shí)驗(yàn)環(huán)境中,新創(chuàng)建文件 demo-gitignore/mytmp/HelloExpectional.xml,并配置.gitignore如下:

# project specified gitignore
/mytmp/*
!/mytmp/HelloExpectional.xml

它表示忽略根目錄/下的mytmp子目錄下的所有文件(星號(hào)表示),但是/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 沒(méi)生效?

緊接著上面,把.gitignore內(nèi)容修改為:

# project specified gitignore
**/mytmp/*
!/mytmp/HelloExpectional.xml

查看status,發(fā)現(xiàn)并沒(méi)有變化?

?  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不被忽略,其他均被忽略。新配置為什么沒(méi)生效?因?yàn)榍拔?code>git add .的時(shí)候,已經(jīng)加入git索引了,gitignore只能對(duì)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,也不是提交到版本庫(kù))。后面接文件,表示操作對(duì)象;-r是當(dāng)操作對(duì)象為目錄時(shí),表示遞歸。

接著實(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)我們忽略一個(gè)目錄時(shí),它下面的子目錄和文件也一起被忽略嗎?

demo-gitignore/mytmp創(chuàng)建一級(jí)子目錄son-of-mytmp和二級(jí)子目錄grandson-of-mytmp,并各自放一個(gè)文件,如下結(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目錄及其子目錄,都被忽略了。但與此同時(shí)奇怪的是!/mytmp/HelloExpectional.xml“例外設(shè)置”并沒(méi)有生效?

如果調(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/*,都會(huì)遞歸影響其子目錄和文件的忽略。
只有/mytmp/*忽略,才能添加形如!/mytmp/HelloExpectional.xml的例外。

glob模式語(yǔ)法

所謂“glob模式”就是我們常見(jiàn)的bash下簡(jiǎn)化的正則表達(dá)式。就4招:

  • 星號(hào) *,通配多個(gè)字符;
  • 兩個(gè)星號(hào)**,表示任意中間層目錄。例如a/**/z 可以匹配目錄a/z, a/b/za/b/c/z等。
  • 問(wèn)號(hào)?,通配單個(gè)字符;
  • 方號(hào)[],枚舉單個(gè)字符。例如[abc]表示要么a,要么b,要么c,但是ab兩個(gè)字符是不能匹配的,只能是1個(gè)。
  • 范圍[0-9][a-z] 表示任意一個(gè)數(shù)字或字母。
  • 嘆號(hào)!,表示“取反”,表示“不忽略”的語(yǔ)義。

使用習(xí)慣

基本概念

  • .gitignore 文件是項(xiàng)目根目錄下的一個(gè)隱藏文件,不是.git子目錄下的。
  • .gitignore 文件對(duì)其所在的目錄及其全部子目錄均有效。當(dāng)然用戶(hù)級(jí)HOME目錄下~/.gitignore文件全局有效,項(xiàng)目的ignore繼承覆蓋用戶(hù)級(jí)的。
  • 配置文件.gitignore本身需要加入版本庫(kù),以便其他組員能共享同一套資源忽略管理規(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ú)享式”,只對(duì)自己生效,其他組員看不到(因?yàn)槎疾簧蟼鞯桨姹編?kù))。“獨(dú)享式”有兩種形式:

  • 用戶(hù)級(jí)的 位置在~/.gitignore 用戶(hù)HOME目錄下;
  • 項(xiàng)目級(jí)的 位置在.git/info/exclude,它也是一個(gè)ignore文件,語(yǔ)法規(guī)則是一樣的。注意:盡管.git目錄一定是要上傳到版本庫(kù)的(它就是版本庫(kù)本身),但是卻留下了exclue是不上傳的。感覺(jué).git的設(shè)計(jì)者很有用心。

那我們什么時(shí)候共享式,什么時(shí)候獨(dú)享式呢?個(gè)人覺(jué)得,更多的是團(tuán)隊(duì)的一個(gè)約定。我們可以先對(duì)需要ignore的東西,做個(gè)大致分類(lèi):

  • 操作系統(tǒng)層面的 比如Mac OS的 .DS_Store, windows的Thumbs.db
  • IDE層面的 比如Eclipse的.project, .settings/.classpath。 IDE層面還包括“樸素IDE”,比如臨時(shí)用VIM應(yīng)急修改了個(gè)東西,意外的閃崩生成了一個(gè).swap文件或有些編輯器會(huì)生成.bak備份文件。
  • 中間結(jié)果類(lèi) 比如程序運(yùn)行一下,就打些日志到文件。再比如嵌入式數(shù)據(jù)庫(kù)生成的臨時(shí)文件。
  • 語(yǔ)言相關(guān)的 剛說(shuō)的“中間結(jié)果”日志類(lèi)的是通用的,無(wú)論哪種語(yǔ)言開(kāi)發(fā)的程序都會(huì)輸出日志,除此外,還有喝多跟語(yǔ)言編譯相關(guān)的,比如JAVA的.class字節(jié)碼,比如Web項(xiàng)目構(gòu)建時(shí)生成的.war包。

了解這些后,或許我們可以把前面兩類(lèi)作為“獨(dú)享式”只作用于自己本地,比如你用Mac那你配Mac的ignore,用Eclipse配Eclipse的;別人用Window,他自己配置Windows的。然后把中間結(jié)果和語(yǔ)言相關(guān)的,弄成“共享式”的,在全組員中共享。

這么多配置需要我們自己寫(xiě)嗎? 當(dāng)然不用,這些問(wèn)題很多開(kāi)發(fā)者都是要遇到同樣的問(wèn)題的,把各種環(huán)境窮舉下? 事實(shí)上有人給我們做了。

官方ignore模板

官方提供ignore模板 https://github.com/github/gitignore

它的組織形式就是按上文說(shuō)的“分層組織”。比如:

  • 系統(tǒng)層
  • IDE層
  • 語(yǔ)言層

附錄1:如何刪除已經(jīng)提交,但不需要提交的資源?

盡管提倡項(xiàng)目開(kāi)始的時(shí)候,就需要對(duì)資源ignore 規(guī)則進(jìn)行設(shè)置。但是現(xiàn)實(shí)常常沒(méi)有那么理想,往往提交后才發(fā)現(xiàn)提交了一些不應(yīng)該提交的東西。怎么刪除它們?

首先要區(qū)分兩類(lèi)刪除:

  • 真的不需要的,比如每次編譯產(chǎn)生的 .class,這些文件真的不需要。

  • 需要,但不想提交到版本庫(kù)的。比如某些臨時(shí)的document,你打算提交到wiki,而不是版本庫(kù)。

  • 找出“已經(jīng)提交,但不需要提交的”資源

從遠(yuǎn)程拷貝一份。之所以這么做,不用當(dāng)前本地的,是因?yàn)閕gnore規(guī)則的存在,本地一定與遠(yuǎn)程不是完全一致的(從文件系統(tǒng)的角度說(shuō)的完全一致,不是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/ 下面居然有,刪除它們。同時(shí)在新拷貝的和本地現(xiàn)有的都刪除。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,237評(píng)論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,957評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 177,248評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,356評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,081評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,485評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,534評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,720評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,263評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,025評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,204評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,787評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,461評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,874評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,105評(píng)論 1 289
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,945評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,205評(píng)論 2 375

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,806評(píng)論 18 139
  • 本文為 Git教程的學(xué)習(xí)筆記,教程源自廖雪峰的博客。這是一個(gè)由淺入深,學(xué)完后能立刻上手的Git教程。另,附上另一本...
    七弦桐語(yǔ)閱讀 6,267評(píng)論 5 47
  • 1. 安裝 Github 查看是否安裝git: $ git config --global user.name "...
    Albert_Sun閱讀 13,692評(píng)論 9 163
  • November012013-11-01 20:47:02|分類(lèi):大學(xué)日記|字號(hào)訂閱 今天院里迎新晚會(huì),剛開(kāi)始...
    獨(dú)行向日葵閱讀 288評(píng)論 0 1
  • 不做人, 來(lái)到人世干什么。 不做自己, 做人又是為什么。 不投入, 不能成功。 不遁出, 一切沒(méi)用。 不做自己, ...
    再湊熱鬧閱讀 144評(píng)論 0 0