.gitignore kecualikan folder tetapi sertakan subfolder tertentu


965

Saya memiliki folder application/yang saya tambahkan ke .gitignore. Di dalam application/folder ada folder application/language/gr. Bagaimana saya bisa memasukkan folder ini?

Saya sudah mencoba ini

application/
!application/language/gr/

tanpa keberuntungan ...


1
Mudah-mudahan, .gitignoredokumentasi "format pola" menjadi lebih jelas (Desember 2013). Lihat jawaban saya di bawah ini
VonC

Pertanyaan dan jawaban favorit saya, ditambahkan ke favorit serta bookmark browser.
codekiddy

Jawaban:


1614

Jika Anda mengecualikan application/, maka semua yang ada di bawahnya akan selalu dikecualikan (bahkan jika beberapa pola pengecualian negatif nanti ("unignore") mungkin cocok dengan sesuatu di bawah application/).

Untuk melakukan apa yang Anda inginkan, Anda harus "unignore" setiap direktori induk dari apa pun yang Anda ingin "unignore". Biasanya Anda akhirnya menulis aturan untuk situasi ini berpasangan: abaikan semua yang ada di direktori, tetapi tidak pada subdirektori tertentu.

# you can skip this first one if it is not already excluded by prior patterns
!application/

application/*
!application/language/

application/language/*
!application/language/gr/

Catatan
Trailingnya /*signifikan:

  • Pola dir/mengecualikan direktori bernama dirdan (secara implisit) semuanya di bawahnya.
    Dengan dir/, Git tidak akan pernah melihat apa pun di bawah dir, dan dengan demikian tidak akan pernah menerapkan pola "tidak termasuk" apa pun di bawah ini dir.
  • Polanya dir/*tidak mengatakan apa-apa tentang dirdirinya sendiri; itu hanya mengecualikan semua yang ada di bawah dir. Dengan dir/*, Git akan memproses konten langsung dari dir, memberikan pola lain kesempatan untuk "membatalkan" sebagian dari konten ( !dir/sub/).

12
Apakah tanda bintang tambahan itu penting? Jika demikian, apa perbedaan artinya? Per algoritma yang dijelaskan dalam dokumentasi gitignore , diakhiri dengan garis miring cocok dengan direktori dan jalur di bawah direktori itu. Berakhir dengan tanda bintang maka akan jatuh ke pengobatan sebagai pola gumpalan. Eksperimen menunjukkan varian asterisk berfungsi, tetapi bukan yang berakhiran hanya garis miring. Saya ingin mengerti mengapa begitu.
seh

123
@ Seh: Ya, jejaknya /*signifikan. Jika suatu direktori dikecualikan, Git tidak akan pernah melihat isi direktori itu. Pola dir/mengecualikan direktori bernama dirdan (secara implisit) semuanya di bawahnya. Polanya dir/*tidak mengatakan apa-apa tentang dirdirinya sendiri; itu hanya mengecualikan semua yang ada di bawah dir. Dengan dir/, Git tidak akan pernah melihat apa pun di bawah dir, dan dengan demikian tidak akan pernah menerapkan pola "tidak termasuk" apa pun di bawah ini dir. Dengan dir/*, Git akan memproses konten langsung dari dir, memberikan pola lain kesempatan untuk "membatalkan" sebagian dari konten ( !dir/sub/).
Chris Johnsen

7
Ah, itu menjelaskannya. Tidak peduli berapa kali saya membaca dokumentasi gitignore , saya tidak pernah mengerti ketika pola yang dikembalikan tidak bekerja. Dengan penjelasan Anda, sekarang jelas. The gitignore Dokumentasi membutuhkan "resep" untuk menjelaskan bagaimana untuk melakukan hal ini.
seh

8
Saya tidak bisa mendapatkan ini berfungsi (file .gitignore gila!), Jadi alih-alih saya hanya memaksa menambahkan file setelah cd'ing ke direktori yang saya inginkan. git add -f .
K0D4

2
Perhatikan bahwa Anda tidak dapat mengandalkan output dari git status, yang hanya akan memberi tahu Anda bahwa direktori tingkat atas akan ditambahkan. Sebagai gantinya, lakukan git adddirektori tingkat atas dan kemudian git statusakan (mudah-mudahan) daftar subset file yang telah dicocokkan dengan pola.
Matthew Strawbridge

136

Komit 59856de dari Karsten Blees (kblees) untuk Git 1.9 / 2.0 (Q1 2014) mengklarifikasi kasus itu:

gitignore.txt: memperjelas sifat rekursif dari direktori yang dikecualikan

Awalan opsional " !" yang meniadakan pola; setiap file yang cocok dikecualikan oleh pola sebelumnya akan dimasukkan lagi.

Tidak mungkin untuk memasukkan kembali file jika direktori induk dari file itu dikecualikan. ( *)
( *: kecuali kondisi tertentu terpenuhi di git 2.8+, lihat di bawah)
Git tidak mencantumkan direktori yang dikecualikan karena alasan kinerja, sehingga pola apa pun pada file yang terkandung tidak memiliki efek, di mana pun mereka didefinisikan.

Letakkan backslash (" \") di depan " !" pertama untuk pola yang dimulai dengan " !" literal , misalnya, " \!important!.txt".

Contoh untuk mengecualikan semua kecuali direktori tertentu foo/bar(perhatikan /*- tanpa slash, wildcard juga akan mengecualikan semua yang ada di dalamnya foo/bar):

 --------------------------------------------------------------
     $ cat .gitignore
     # exclude everything except directory foo/bar
     /*
     !/foo
     /foo/*
     !/foo/bar
 --------------------------------------------------------------

Dalam kasus Anda:

application/*
!application/**/
application/language/*
!application/language/**/
!application/language/gr/**

Anda harus membuat daftar putih folder terlebih dahulu, sebelum dapat membuat daftar putih file dalam folder yang diberikan.


Pembaruan Februari / Maret 2016:

Perhatikan bahwa dengan git 2.9.x / 2.10 (pertengahan 2016?), Dimungkinkan untuk memasukkan kembali file jika direktori induk dari file tersebut dikecualikan jika tidak ada wildcard di jalur yang disertakan kembali .

Nguyễn Thái Ngọc Duy ( pclouds) sedang mencoba untuk menambahkan fitur ini:

Jadi dengan git 2.9+, ini bisa saja berhasil, tetapi pada akhirnya dikembalikan:

application/
!application/language/gr/

Saya mencoba menggunakan sintaks yang disertakan kembali yang diposting di akhir jawaban Anda di git untuk windows v2.8.1.windows.1tetapi tampaknya tidak berhasil :(
David Hancock

1
@ Davidvidock Maaf, saya telah mengedit jawaban: ini belum tersedia.
VonC

1
@ Davidvidancock saya juga: itu lebih dari 13 jawaban Stack Overflow yang harus saya edit berulang kali!
VonC

5
Git 2.9 dirilis kemarin. Mengonfirmasi pola application/+ !application/language/gr/yang disebutkan dalam jawaban berfungsi seperti yang diharapkan.
Ray Shan

1
@RayShan Strange: Saya telah melihat komit pengembalian membatalkan fitur itu, tapi saya belum melihat (dan catatan rilis github.com/git/git/blob/master/Documentation/RelNotes/2.9.0.txt tidak menyebutkan) komit apa pun yang memperbaiki aturan .gitignore.
VonC

52

Jawaban @Chris Johnsen bagus, tetapi dengan versi Git yang lebih baru (1.8.2 atau lebih baru), ada pola tanda bintang ganda yang dapat Anda manfaatkan untuk solusi yang lebih singkat:

# assuming the root folder you want to ignore is 'application'
application/**/*

# the subfolder(s) you want to track:
!application/language/gr/

Dengan cara ini Anda tidak perlu "membatalkan" direktori induk dari subfolder yang ingin Anda lacak.


Dengan Git 2.17.0 (Tidak yakin seberapa awal sebelum versi ini. Mungkin kembali ke 1.8.2), menggunakan **pola yang dikombinasikan dengan kecualikan untuk setiap subdirektori yang mengarah ke file Anda. Sebagai contoh:

# assuming the root folder you want to ignore is 'application'
application/**

# Explicitly track certain content nested in the 'application' folder:
!application/language/
!application/language/gr/
!application/language/gr/** # Example adding all files & folder in the 'gr' folder
!application/language/gr/SomeFile.txt # Example adding specific file in the 'gr' folder

9
Sayangnya, ini gagal (Git 1.8.4.msysgit.0) karena polanya **bisa cocok dengan nol subfolder, dan *akan cocok languagedan mengecualikannya, mencegah dimasukkannya gr. Rantai penuh orang tua yang direkomendasikan oleh @Chris Johnson tampaknya masih perlu.
Sean Gugler

3
Kedengarannya sempurna tetapi tidak bekerja untuk saya di git 2.3.7 ... /www/**/* !/www/config.xml !/www/resconfig.xml dan direktori res masih diabaikan.
Rob

@Rob, Anda juga harus menambahkan !/www/res/. Anda dapat menggunakan folder/**/*pola, tetapi Anda masih perlu menambahkan kecualikan untuk setiap subdirektori yang ingin Anda tambahkan. Itu masih lebih pendek dan lebih mudah dibaca daripada kombo diabaikan / kecualikan.
Ben Kane

Saya tahu itu komentar lama, tapi kalau-kalau Anda penasaran. Saya telah menambahkan hasil edit ke jawaban yang mendokumentasikan pendekatan ini.
Ben Kane

21

Ada banyak pertanyaan serupa tentang ini, jadi saya akan memposting apa yang saya tulis sebelumnya:

Satu-satunya cara saya mendapatkan ini untuk bekerja pada mesin saya adalah melakukannya dengan cara ini:

# Ignore all directories, and all sub-directories, and it's contents:
*/*

#Now ignore all files in the current directory 
#(This fails to ignore files without a ".", for example 
#'file.txt' works, but 
#'file' doesn't):
*.*

#Only Include these specific directories and subdirectories:
!wordpress/
!wordpress/*/
!wordpress/*/wp-content/
!wordpress/*/wp-content/themes/
!wordpress/*/wp-content/themes/*
!wordpress/*/wp-content/themes/*/*
!wordpress/*/wp-content/themes/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*/*

Perhatikan bagaimana Anda harus secara eksplisit mengizinkan konten untuk setiap level yang ingin Anda sertakan. Jadi jika saya memiliki subdirektori 5 tema yang jauh di bawah, saya masih perlu menjelaskannya.

Ini dari komentar @ Yarin di sini: https://stackoverflow.com/a/5250314/1696153

Ini adalah topik yang bermanfaat:

Saya juga mencoba

*
*/*
**/**

dan **/wp-content/themes/**

atau /wp-content/themes/**/*

Tidak ada yang berhasil untuk saya. Banyak trial and error!


1
Catatan: Ingatlah bahwa pesanan juga penting dalam file .gitignore, jadi pastikan Anda meletakkan !aturan di bagian bawah.
starbeamrainbowlabs


8

Cara paling sederhana dan mungkin terbaik adalah mencoba menambahkan file secara manual (umumnya ini lebih diutamakan daripada .gitignoreaturan gaya):

git add /path/to/module

Anda bahkan mungkin ingin -N niat untuk menambahkan bendera, untuk menyarankan Anda akan menambahkannya, tetapi tidak segera. Saya sering melakukan ini untuk file baru saya belum siap untuk panggung.


Ini salinan jawaban yang diposting pada QA duplikat yang bisa dengan mudah. Saya memposting ulang di sini untuk meningkatkan visibilitas — saya merasa lebih mudah untuk tidak memiliki kekacauan aturan gitignore.


2
Terima kasih atas jawaban ini. Saya harus menambahkan -f karena ada di dalam .gitignore saya jadi seperti: git add -f path / to / file
jasonflaherty

6

Jadi, karena banyak programmer menggunakan node. kasus penggunaan yang memenuhi pertanyaan ini adalah untuk mengecualikan node_moduleskecuali satu modul module-amisalnya:

!node_modules/

node_modules/*
!node_modules/module-a/

2
Tidak berfungsi untuk versi git 2.10.2.windows.1.
Sebastian

1
Untuk git versi 2.10.2 ikuti jawaban ini
nalexn

👌 hebat 👋 👋.
Abdennour TOUMI

6

Tambahkan jawaban tambahan:

!/.vs/              <== include this folder to source control, folder only, nothing else
/.vs/*              <== but ignore all files and sub-folder inside this folder
!/.vs/ProjectSettings.json <== but include this file to source control
!/.vs/config/       <== then include this folder to source control, folder only, nothing else
!/.vs/config/*      <== then include all files inside the folder

ini hasilnya:

masukkan deskripsi gambar di sini


2
Ini adalah jawaban yang paling berguna bagi saya karena visual membantu. Terima kasih!
Joel Murphy

4

Khusus untuk versi Git yang lebih lama, sebagian besar saran tidak akan bekerja dengan baik. Jika itu masalahnya, saya akan meletakkan .gitignore terpisah di direktori di mana saya ingin konten untuk dimasukkan terlepas dari pengaturan lain dan memungkinkan di sana apa yang diperlukan.

Sebagai contoh: /.gitignore

# ignore all .dll files
*.dll

/dependency_files/.gitignore

# include everything
!*

Jadi semua yang ada di / dependency_files (bahkan file .dll) disertakan dengan baik.


4

Saya telah menemukan kasus serupa di sini, di mana di laravel secara default, .gitignoremengabaikan semua menggunakan asterix, kemudian menimpa direktori publik.

*
!public
!.gitignore

Ini tidak cukup jika Anda mengalami skenario OP.

Jika Anda ingin melakukan suatu subfolder tertentu public, mengatakan untuk misalnya dalam Anda public/productsdirektori Anda ingin menyertakan file yang satu subfolder dalam misalnya untuk memasukkan public/products/a/b.jpgmereka wont dideteksi dengan benar, bahkan jika Anda menambahkan mereka secara khusus seperti ini !/public/products, !public/products/*, dll ..

Solusinya adalah memastikan Anda menambahkan entri untuk setiap level jalur seperti ini untuk menimpa semuanya.

*
!.gitignore
!public/
!public/*/
!public/products/
!public/products/*
!public/products/*/
!public/products/*/
!public/products/*/*

3

Contoh lain berjalan menyusuri struktur direktori untuk mendapatkan apa yang Anda inginkan. Catatan: Saya tidak mengecualikan Library/tetapiLibrary/**/*

# .gitignore file
Library/**/*
!Library/Application Support/
!Library/Application Support/Sublime Text 3/
!Library/Application Support/Sublime Text 3/Packages/
!Library/Application Support/Sublime Text 3/Packages/User/
!Library/Application Support/Sublime Text 3/Packages/User/*macro
!Library/Application Support/Sublime Text 3/Packages/User/*snippet
!Library/Application Support/Sublime Text 3/Packages/User/*settings
!Library/Application Support/Sublime Text 3/Packages/User/*keymap
!Library/Application Support/Sublime Text 3/Packages/User/*theme
!Library/Application Support/Sublime Text 3/Packages/User/**/
!Library/Application Support/Sublime Text 3/Packages/User/**/*macro
!Library/Application Support/Sublime Text 3/Packages/User/**/*snippet
!Library/Application Support/Sublime Text 3/Packages/User/**/*settings
!Library/Application Support/Sublime Text 3/Packages/User/**/*keymap
!Library/Application Support/Sublime Text 3/Packages/User/**/*theme

> git add Library

> git status

On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   Library/Application Support/Sublime Text 3/Packages/User/Default (OSX).sublime-keymap
    new file:   Library/Application Support/Sublime Text 3/Packages/User/ElixirSublime.sublime-settings
    new file:   Library/Application Support/Sublime Text 3/Packages/User/Package Control.sublime-settings
    new file:   Library/Application Support/Sublime Text 3/Packages/User/Preferences.sublime-settings
    new file:   Library/Application Support/Sublime Text 3/Packages/User/RESTer.sublime-settings
    new file:   Library/Application Support/Sublime Text 3/Packages/User/SublimeLinter/Monokai (SL).tmTheme
    new file:   Library/Application Support/Sublime Text 3/Packages/User/TextPastryHistory.sublime-settings
    new file:   Library/Application Support/Sublime Text 3/Packages/User/ZenTabs.sublime-settings
    new file:   Library/Application Support/Sublime Text 3/Packages/User/adrian-comment.sublime-macro
    new file:   Library/Application Support/Sublime Text 3/Packages/User/json-pretty-generate.sublime-snippet
    new file:   Library/Application Support/Sublime Text 3/Packages/User/raise-exception.sublime-snippet
    new file:   Library/Application Support/Sublime Text 3/Packages/User/trailing_spaces.sublime-settings

Persis apa yang ingin saya lakukan juga ;-)
Kitze

3

Di WordPress, ini membantu saya:

wp-admin/
wp-includes/
/wp-content/*
!wp-content/plugins/
/wp-content/plugins/*
!/wp-content/plugins/plugin-name/
!/wp-content/plugins/plugin-name/*.*
!/wp-content/plugins/plugin-name/**

3

gitignore - Menentukan file yang sengaja dilacak untuk diabaikan.

Contoh untuk mengecualikan semua kecuali foo / bar direktori tertentu (perhatikan / * - tanpa slash, wildcard juga akan mengecualikan semua dalam foo / bar ):

$ cat .gitignore
# exclude everything except directory foo/bar
/*
!/foo
/foo/*
!/foo/bar

Contoh lain untuk WordPress :

!/wp-content
wp-content/*
!/wp-content/plugins
wp-content/plugins/*
!wp-content/plugins/my-awesome-plugin

Informasi lebih lanjut di sini: https://git-scm.com/docs/gitignore


2

Saya sering menggunakan solusi ini di CLI di mana alih-alih mengkonfigurasi saya .gitignore, saya membuat .includefile terpisah di mana saya mendefinisikan direktori (sub) yang ingin saya sertakan meskipun direktori secara langsung atau secara rekursif diabaikan oleh .gitignore.

Jadi, saya juga menggunakan

git add `cat .include`

selama pementasan, sebelum melakukan.

Untuk OP, saya sarankan menggunakan .includeyang memiliki baris berikut:

<parent_folder_path>/application/language/gr/*

CATATAN: Menggunakan cattidak memungkinkan penggunaan alias (di dalam .include) untuk menentukan $ HOME (atau direktori spesifik lainnya). Ini karena garis homedir/app1/* ketika dilewatkan untuk git addmenggunakan perintah di atas muncul sebagai git add 'homedir/app1/*', dan melampirkan karakter dalam tanda kutip tunggal ('') menjaga nilai literal setiap karakter dalam tanda kutip, sehingga mencegah alias (seperti homedir ) dari berfungsi (lihat Bash Tunggal Kutipan ).

Berikut adalah contoh .includefile yang saya gunakan di repo saya di sini .

/home/abhirup/token.txt
/home/abhirup/.include
/home/abhirup/.vim/*
/home/abhirup/.viminfo
/home/abhirup/.bashrc
/home/abhirup/.vimrc
/home/abhirup/.condarc

1

Saya ingin melacak file js produksi jquery dan ini berhasil:

node_modules/*
!node_modules/jquery
node_modules/jquery/*
!node_modules/jquery/dist/*

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.