Git忽略提交規則 - .gitignore配置運維總結

在使用Git的過程中,我們喜歡有的文件比如日志,臨時文件,編譯的中間文件等不要提交到代碼倉庫,這時就要設置相應的忽略規則,來忽略這些文件的提交。簡單來說一個場景:在你使用git add .的時候,遇到了把你不想提交的文件也添加到了緩存中去的情況,比如項目的本地配置信息,如果你上傳到Git中去其他人pull下來的時候就會和他本地的配置有沖突,所以這樣的個性化配置文件我們一般不把它推送到git服務器中,但是又為了偷懶每次添加緩存的時候都想用git add .而不是手動一個一個文件添加,該怎么辦呢?很簡單,git為我們提供了一個.gitignore文件只要在這個文件中申明那些文件你不希望添加到git中去,這樣當你使用git add .的時候這些文件就會被自動忽略掉。

有三種方法可以實現忽略Git中不想提交的文件:
1)在Git項目中定義.gitignore文件
對于經常使用Git的朋友來說,.gitignore配置一定不會陌生。這種方式通過在項目的某個文件夾下定義.gitignore文件,在該文件中定義相應的忽略規則,來管理當前文件夾下的文件的Git提交行為。.gitignore 文件是可以提交到公有倉庫中,這就為該項目下的所有開發者都共享一套定義好的忽略規則。在.gitingore 文件中,遵循相應的語法,在每一行指定一個忽略規則。如:

*.log
*.temp
/vendor

2)在Git項目的設置中指定排除文件
這種方式只是臨時指定該項目的行為,需要編輯當前項目下的 .git/info/exclude文件,然后將需要忽略提交的文件寫入其中。需要注意的是,這種方式指定的忽略文件的根目錄是項目根目錄。

3)定義Git全局的 .gitignore 文件
除了可以在項目中定義 .gitignore 文件外,還可以設置全局的git .gitignore文件來管理所有Git項目的行為。這種方式在不同的項目開發者之間是不共享的,是屬于項目之上Git應用級別的行為。這種方式也需要創建相應的 .gitignore 文件,可以放在任意位置。然后在使用以下命令配置Git:

# git config --global core.excludesfile ~/.gitignore

首先要強調一點,這個文件的完整文件名就是".gitignore",注意最前面有個“.”。一般來說每個Git項目中都需要一個“.gitignore”文件,這個文件的作用就是告訴Git哪些文件不需要添加到版本管理中。實際項目中,很多文件都是不需要版本管理的,比如Python的.pyc文件和一些包含密碼的配置文件等等。這個文件的內容是一些規則,Git會根據這些規則來判斷是否將文件添加到版本控制中。

Git忽略文件的原則

  • 忽略操作系統自動生成的文件,比如縮略圖等;
  • 忽略編譯生成的中間文件、可執行文件等,也就是如果一個文件是通過另一個文件自動生成的,那自動生成的文件就沒必要放進版本庫,比如Java編譯產生的.class文件;
  • 忽略你自己的帶有敏感信息的配置文件,比如存放口令的配置文件。

.gitignore文件的使用方法
首先,在你的工作區新建一個名稱為.gitignore的文件。
然后,把要忽略的文件名填進去,Git就會自動忽略這些文件。
不需要從頭寫.gitignore文件,GitHub已經為我們準備了各種配置文件,只需要組合一下就可以使用了。

有時對于git項目下的某些文件,我們不需要納入版本控制,比如日志文件或者IDE的配置文件,此時可以在項目的根目錄下建立一個隱藏文件 .gitignore(linux下以.開頭的文件都是隱藏文件),然后在.gitignore中寫入需要忽略的文件。

[root@kevin ~]# cat .gitignore
*.xml
*.log
*.apk

.gitignore注釋用'#', *表示匹配0個或多個任意字符,所以上面的模式就是要忽略所有的xml文件,log文件和apk文件。

.gitignore配置文件用于配置不需要加入版本管理的文件,配置好該文件可以為版本管理帶來很大的便利。

.gitignore忽略規則的優先級
在 .gitingore 文件中,每一行指定一個忽略規則,Git檢查忽略規則的時候有多個來源,它的優先級如下(由高到低):
1)從命令行中讀取可用的忽略規則
2)當前目錄定義的規則
3)父級目錄定義的規則,依次遞推
4)$GIT_DIR/info/exclude 文件中定義的規則
5)core.excludesfile中定義的全局規則

.gitignore忽略規則的匹配語法
在 .gitignore 文件中,每一行的忽略規則的語法如下:
1)空格不匹配任意文件,可作為分隔符,可用反斜杠轉義
2)以“#”開頭的行都會被 Git 忽略。即#開頭的文件標識注釋,可以使用反斜杠進行轉義。
3)可以使用標準的glob模式匹配。所謂的glob模式是指shell所使用的簡化了的正則表達式。
4)以斜杠"/"開頭表示目錄;"/"結束的模式只匹配文件夾以及在該文件夾路徑下的內容,但是不匹配該文件;"/"開始的模式匹配項目跟目錄;如果一個模式不包含斜杠,則它匹配相對于當前 .gitignore 文件路徑的內容,如果該模式不在 .gitignore 文件中,則相對于項目根目錄。
5)以星號""通配多個字符,即匹配多個任意字符;使用兩個星號"*" 表示匹配任意中間目錄,比如a/**/z可以匹配 a/z, a/b/z 或 a/b/c/z等。
6)以問號"?"通配單個字符,即匹配一個任意字符;
7)以方括號"[]"包含單個字符的匹配列表,即匹配任何一個列在方括號中的字符。比如[abc]表示要么匹配一個a,要么匹配一個b,要么匹配一個c;如果在方括號中使用短劃線分隔兩個字符,表示所有在這兩個字符范圍內的都可以匹配。比如[0-9]表示匹配所有0到9的數字,[a-z]表示匹配任意的小寫字母)。
8)以嘆號"!"表示不忽略(跟蹤)匹配到的文件或目錄,即要忽略指定模式以外的文件或目錄,可以在模式前加上驚嘆號(!)取反。需要特別注意的是:如果文件的父目錄已經被前面的規則排除掉了,那么對這個文件用"!"規則是不起作用的。也就是說"!"開頭的模式表示否定,該文件將會再次被包含,如果排除了該文件的父級目錄,則使用"!"也不會再次被包含。可以使用反斜杠進行轉義。

需要謹記:git對于.ignore配置文件是按行從上到下進行規則匹配的,意味著如果前面的規則匹配的范圍更大,則后面的規則將不會生效;

.gitignore忽略規則簡單說明

#               表示此為注釋,將被Git忽略
*.a             表示忽略所有 .a 結尾的文件
!lib.a          表示但lib.a除外
/TODO           表示僅僅忽略項目根目錄下的 TODO 文件,不包括 subdir/TODO
build/          表示忽略 build/目錄下的所有文件,過濾整個build文件夾;
doc/*.txt       表示會忽略doc/notes.txt但不包括 doc/server/arch.txt
 
bin/:           表示忽略當前路徑下的bin文件夾,該文件夾下的所有內容都會被忽略,不忽略 bin 文件
/bin:           表示忽略根目錄下的bin文件
/*.c:           表示忽略cat.c,不忽略 build/cat.c
debug/*.obj:    表示忽略debug/io.obj,不忽略 debug/common/io.obj和tools/debug/io.obj
**/foo:         表示忽略/foo,a/foo,a/b/foo等
a/**/b:         表示忽略a/b, a/x/b,a/x/y/b等
!/bin/run.sh    表示不忽略bin目錄下的run.sh文件
*.log:          表示忽略所有 .log 文件
config.php:     表示忽略當前路徑的 config.php 文件
 
/mtk/           表示過濾整個文件夾
*.zip           表示過濾所有.zip文件
/mtk/do.c       表示過濾某個具體文件
 
被過濾掉的文件就不會出現在git倉庫中(gitlab或github)了,當然本地庫中還有,只是push的時候不會上傳。
 
需要注意的是,gitignore還可以指定要將哪些文件添加到版本管理中,如下:
!*.zip
!/mtk/one.txt
 
唯一的區別就是規則開頭多了一個感嘆號,Git會將滿足這類規則的文件添加到版本管理中。為什么要有兩種規則呢?
想象一個場景:假如我們只需要管理/mtk/目錄中的one.txt文件,這個目錄中的其他文件都不需要管理,那么.gitignore規則應寫為::
/mtk/*
!/mtk/one.txt
 
假設我們只有過濾規則,而沒有添加規則,那么我們就需要把/mtk/目錄下除了one.txt以外的所有文件都寫出來!
注意上面的/mtk/*不能寫為/mtk/,否則父目錄被前面的規則排除掉了,one.txt文件雖然加了!過濾規則,也不會生效!
 
----------------------------------------------------------------------------------
還有一些規則如下:
fd1/*
說明:忽略目錄 fd1 下的全部內容;注意,不管是根目錄下的 /fd1/ 目錄,還是某個子目錄 /child/fd1/ 目錄,都會被忽略;
 
/fd1/*
說明:忽略根目錄下的 /fd1/ 目錄的全部內容;
 
/*
!.gitignore
!/fw/ 
/fw/*
!/fw/bin/
!/fw/sf/

說明:忽略全部內容,但是不忽略 .gitignore 文件、根目錄下的 /fw/bin/ 和 /fw/sf/ 目錄;注意要先對bin/的父目錄使用!規則,使其不被排除。
溫馨提示:
如果你不慎在創建.gitignore文件之前就push了項目,那么即使你在.gitignore文件中寫入新的過濾規則,這些規則也不會起作用,Git仍然會對所有文件進行版本管理。簡單來說出現這種問題的原因就是Git已經開始管理這些文件了,所以你無法再通過過濾規則過濾它們。所以大家一定要養成在項目開始就創建.gitignore文件的習慣,否則一單push,處理起來會非常麻煩。

.gitignore忽略規則常用示例

1)示例

比如你的項目是java項目,.java文件編譯后會生成.class文件,這些文件多數情況下是不想被傳到倉庫中的文件。這時候你可以直接適用github的.gitignore文件模板。https://github.com/github/gitignore/blob/master/Java.gitignore 將這些忽略文件信息復制到你的.gitignore文件中去:

# Compiled class file
*.class
 
# Log file
*.log
 
# BlueJ files
*.ctxt
 
# Mobile Tools for Java (J2ME)
.mtj.tmp/
 
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
 
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

可以看到github為我們提供了最流行的.gitignore文件配置。保存.ignore文件后我們查看下git status,檢查下是否還有我們不需要的文件會被添加到git中去:

$ git status
On branch master
 
Initial commit
 
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
 
        new file:   .gitignore
        new file:   HelloWorld.java
 
Untracked files:
  (use "git add <file>..." to include in what will be committed)
 
        Config.ini

比如我的項目目錄下有一個Config.ini文件,這個是個本地配置文件我不希望上傳到git中去,我們可以在gitignore文件中添加這樣的配置:

Config.ini

或者你想忽略所有的.ini文件你可以這樣寫:

*.ini

如果有些文件已經被你忽略了,當你使用git add時是無法添加的,比如我忽略了*.class,現在我想把HelloWorld.class添加到git中去:

$ git add HelloWorld.class
The following paths are ignored by one of your .gitignore files:
HelloWorld.class
Use -f if you really want to add them.

git會提示我們這個文件已經被我們忽略了,需要加上-f參數才能強制添加到git中去:

$ git status
On branch master
 
Initial commit
 
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
 
        new file:   .gitignore
        new file:   HelloWorld.class
        new file:   HelloWorld.java

這樣就能強制添加到緩存中去了。如果我們意外的將想要忽略的文件添加到緩存中去了,我們可以使用rm命令將其從中移除:

$ git rm HelloWorld.class --cached
rm 'HelloWorld.class'

如果你已經把不想上傳的文件上傳到了git倉庫,那么你必須先從遠程倉庫刪了它,我們可以從遠程倉庫直接刪除然后pull代碼到本地倉庫這些文件就會本刪除,或者從本地刪除這些文件并且在.gitignore文件中添加這些你想忽略的文件,然后再push到遠程倉庫。

2)示例

下面是曾經線上使用過的一個gerrit里項目代碼的.gitignore的配置(在項目中添加.gitignore過濾文件,在git push到gerrit里即可)
[wangshibo@gerrit-server hq_ios]$ cat .gitignore
#Built application files
*.apk
*.ap_
  
# Files for the Dalvik VM
*.dex
  
# Java class files
*.class
  
# Generated files
*/bin/
*/gen/
*/out/
  
# Gradle files
.gradle/
build/
*/build/
gradlew
gradlew.bat
  
# Local configuration file (sdk path, etc)
local.properties
  
# Proguard folder generated by Eclipse
proguard/
  
# Log Files
*.log
  
# Android Studio Navigation editor temp files
.navigation/
  
# Android Studio captures folder
captures/
  
# Intellij
*.iml
*/*.iml
  
# Keystore files
#*.jks
#gradle wrapper
gradle/
  
#some local files
*/.settings/
*/.DS_Store
.DS_Store
*/.idea/
.idea/
gradlew
gradlew.bat
unused.txt

示例

[wangshibo@gerrit-server hq_ios$ cat .gitignore
# Lines that start with '#' are comments.
# IntelliJ IDEA Project files
.idea
*.iml
*.ipr
*.iws
out
  
# Eclipse Project files
.classpath
.project
.settings/
  
bin/
gen/
local.properties
  
.DS_Store
Thumbs.db
  
*.bak
*.tem
*.temp
#.swp
*.*~
~*.*

.gitignor忽略規則查看
如果你發下.gitignore寫得有問題,需要找出來到底哪個規則寫錯了,可以用git check-ignore命令檢查:

$ git check-ignore -v HelloWorld.class
.gitignore:1:*.class    HelloWorld.class

可以看到HelloWorld.class匹配到了我們的第一條*.class的忽略規則所以文件被忽略了。

簡單來說,要實現過濾掉Git里不想上傳的文件,如上介紹三種方法能達到這種目的,只不過適用情景不一樣:

============第一種方法===========

針對單一工程排除文件,這種方式會讓這個工程的所有修改者在克隆代碼的同時,也能克隆到過濾規則,而不用自己再寫一份,
這就能保證所有修改者應用的都是同一份規則,而不是張三自己有一套過濾規則,李四又使用另一套過濾規則,個人比較喜歡這個。

配置步驟如下:
在工程根目錄下建立.gitignore文件,將要排除的文件或目錄 寫到.gitignore這個文件中,其中有兩種寫入方法:

a)使用命令行增加排除文件
排除以.class結尾的文件 echo "*.class" >.gitignore (>> 是在文件尾增加,> 是刪除已經存在的內容再增加),之后會在當前目錄下
生成一個.gitignore的文件。排除bin目錄下的文件 echo "bin/" >.gitignore

b)最方便的辦法是,用記事本打開,增加需要排除的文件或目錄,一行增加一個,例如:

*.class
*.apk
bin/
gen/
.settings/
proguard/

===========第二種方法===========
全局設置排除文件,這會在全局起作用,只要是Git管理的工程,在提交時都會自動排除不在控制范圍內的文件或目錄。這種方法對開發者來說,
比較省事,只要一次全局配置,不用每次建立工程都要配置一遍過濾規則。但是這不保證其他的開發者在克隆你的代碼后,他們那邊的規則跟你
的是一樣的,這就帶來了代碼提交過程中的各種沖突問題。
配置步驟如下:
a)像方法(1)一樣,也需要建立一個.gitignore文件,把要排除的文件寫進去。
b)但在這里,我們不規定一定要把.gitnore文件放到某個工程下面,而是任何地方,比如我們這里放到了Git默認的Home路徑下,比如:/home/wangshibo/hqsb_ios
c)使用命令方式可以配置全局排除文件:

   # git config --global core.excludesfile ~/.gitignore

你會發現在~/.gitconfig文件中會出現excludesfile = /home/wangshibo/hqsb_ios/.gitignore。
說明Git把文件過濾規則應用到了Global的規則中。

===========第三種方法===========
單個工程設置排除文件,在工程目錄下找到.git/info/exclude,把要排除的文件寫進去:

*.class
*.apk
bin/
gen/
.settings/
proguard/

這種方法就不提倡了,只能針對單一工程配置,而且還不能將過濾規則同步到其他開發者,跟方法一和方法二比較起來沒有一點優勢。
Git忽略規則(.gitignore配置)不生效原因和解決

第一種方法:
.gitignore中已經標明忽略的文件目錄下的文件,git push的時候還會出現在push的目錄中,或者用git status查看狀態,想要忽略的文件還是顯示被追蹤狀態。
原因是因為在git忽略目錄中,新建的文件在git中會有緩存,如果某些文件已經被納入了版本管理中,就算是在.gitignore中已經聲明了忽略路徑也是不起作用的,
這時候我們就應該先把本地緩存刪除,然后再進行git的提交,這樣就不會出現忽略的文件了。
  
解決方法: git清除本地緩存(改變成未track狀態),然后再提交:
[root@kevin ~]# git rm -r --cached .
[root@kevin ~]# git add .
[root@kevin ~]# git commit -m 'update .gitignore'
[root@kevin ~]# git push -u origin master
 
需要特別注意的是:
1).gitignore只能忽略那些原來沒有被track的文件,如果某些文件已經被納入了版本管理中,則修改.gitignore是無效的。
2)想要.gitignore起作用,必須要在這些文件不在暫存區中才可以,.gitignore文件只是忽略沒有被staged(cached)文件,
   對于已經被staged文件,加入ignore文件時一定要先從staged移除,才可以忽略。
 
第二種方法:(推薦)
在每個clone下來的倉庫中手動設置不要檢查特定文件的更改情況。
[root@kevin ~]# git update-index --assume-unchanged PATH                  //在PATH處輸入要忽略的文件

在使用.gitignore文件后如何刪除遠程倉庫中以前上傳的此類文件而保留本地文件
在使用git和github的時候,之前沒有寫.gitignore文件,就上傳了一些沒有必要的文件,在添加了.gitignore文件后,就想刪除遠程倉庫中的文件卻想保存本地的文件。這時候不可以直接使用"git rm directory",這樣會刪除本地倉庫的文件。可以使用"git rm -r –cached directory"來刪除緩沖,然后進行"commit"和"push",這樣會發現遠程倉庫中的不必要文件就被刪除了,以后可以直接使用"git add -A"來添加修改的內容,上傳的文件就會受到.gitignore文件的內容約束。

額外說明:git庫所在的文件夾中的文件大致有4種狀態

Untracked:
未跟蹤, 此文件在文件夾中, 但并沒有加入到git庫, 不參與版本控制. 通過git add 狀態變為Staged.
 
Unmodify:
文件已經入庫, 未修改, 即版本庫中的文件快照內容與文件夾中完全一致. 這種類型的文件有兩種去處, 如果它被修改,
而變為Modified. 如果使用git rm移出版本庫, 則成為Untracked文件
 
Modified:
文件已修改, 僅僅是修改, 并沒有進行其他的操作. 這個文件也有兩個去處, 通過git add可進入暫存staged狀態,
使用git checkout 則丟棄修改過, 返回到unmodify狀態, 這個git checkout即從庫中取出文件, 覆蓋當前修改
 
Staged:
暫存狀態. 執行git commit則將修改同步到庫中, 這時庫中的文件和本地文件又變為一致, 文件為Unmodify狀態.
執行git reset HEAD filename取消暫存, 文件狀態為Modified
 
Git 狀態 untracked 和 not staged的區別
1)untrack     表示是新文件,沒有被add過,是為跟蹤的意思。
2)not staged  表示add過的文件,即跟蹤文件,再次修改沒有add,就是沒有暫存的意思
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374