Abaikan subdirektori dari direktori yang diabaikan di Git

100

Katakanlah saya telah mengabaikan sebuah direktori, tetapi saya ingin menghilangkan subdirektori tertentu di dalamnya. Jadi saya sudah menyiapkannya:

/uploads/
/uploads/rubbish/
/uploads/rubbish/stuff/KEEP_ME/
/uploads/foo/
/uploads/foo/bar/lose/

Dan saya ingin mengabaikan semuanya kecuali KEEP_MEdirektori. Saya berharap pengabaian akan terlihat seperti:

/uploads/*
!/uploads/rubbish/stuff/KEEP_ME/

Tapi itu tidak berhasil, dan juga tidak ada beberapa permutasi pada tema yang sama.

Salah satu yang berhasil adalah

/uploads/**/**/**/
!/uploads/rubbish/stuff/KEEP_ME/

Tapi itu terasa sedikit membatasi dan bertele-tele?

Wil
sumber
1
Kode yang Anda berikan tidak berfungsi untuk saya (menggunakan git versi 1.9.1). Salah satu yang berhasil adalah / uploads / *! / Uploads / rubbish / / uploads / rubbish / *! / Uploads / rubbish / stuff / uploads / rubbish / stuff / *! / Uploads / rubbish / stuff / keep (yang mirip dengan contoh di git-scm.com/docs/gitignore ). Struct folder saya; └ README.md └ unggah / foo / bar / kehilangan / kehilangan.txt └ unggah / sampah / barang / simpan / simpan.txt
gihanchanuka

Jawaban:

119

Menurut bagian format pola dari dokumentasi gitignore :

Awalan opsional "!" yang meniadakan pola; file apa pun yang cocok yang dikecualikan oleh pola sebelumnya akan disertakan lagi. Tidak mungkin untuk memasukkan kembali file jika direktori induk dari file itu dikecualikan. Git tidak mencantumkan direktori yang dikecualikan untuk alasan kinerja, jadi pola apa pun pada file yang ditampung tidak akan berpengaruh, di mana pun mereka didefinisikan. Letakkan garis miring terbalik ("\") di depan yang pertama "!" untuk pola yang dimulai dengan "!" literal, misalnya, "! penting! .txt".

Oleh karena itu /uploads/rubbish/stuff/keep/pola direktori induk yang sebelumnya dikecualikan harus dinegasikan secara eksklusif sebelum meniadakan isinya:

#ignore everything within /uploads/ 
/uploads/*

#include everything within /uploads/rubbish/stuff/keep
!/uploads/rubbish/stuff/keep/  
!/uploads/rubbish/stuff/keep/*

Untuk memasukkan subdirektori di dalam /uploads/rubbish/stuff/keep/tambahkan baris ketiga:

!/uploads/rubbish/stuff/keep/**/*
Seni Shayderov
sumber
1
Versi git apa yang Anda gunakan? Mungkin itu sesuatu yang hanya tersedia di versi tertentu.
Malu. Saya lupa saya memposting komentar ini. Tapi aku berhasil melakukannya. FWIW, saya tidak menggunakan garis miring di depan. Saya tidak ingat apakah itu masalahnya. Saya menggunakan 1.7.2.5.
Saya memiliki file gitignore global tempat saya mengabaikan semua file * .zip. Namun untuk proyek tertentu, saya ingin menyertakan file zip. Saya menambahkan baris ini ke proyek itu .gitignoredan itu berfungsi dengan baik !:!*.zip
Jinghao Shi
Saya merasa perlu untuk secara eksplisit menentukan direktori sewenang-wenang sebelum dan sesudah folder yang diberikan baik saat mengecualikan folder dan saat termasuk sub-folder . ( Jawaban lengkap ).
Josiah Yoder
Metode ini tidak berfungsi (mulai git 2.25 - mungkin sesuatu di git berubah). Saya memposting stackoverflow.com/a/60288435/295691 di bawah sebagai koreksi.
pengguna295691
34

Bahkan jika Anda menambahkan sesuatu .gitignore, Anda dapat memaksa git untuk menambahkannya ke indeks

git add --force uploads/rubbish/stuff/KEEP_ME/

Namun, "KEEP_ME" tampaknya merupakan direktori dan git biasanya tidak menyukai folder kosong, jadi Anda harus menambahkan file pemegang "placeholder", jika folder tersebut kosong

git add --force uploads/rubbish/stuff/KEEP_ME/.keep_me
KingCrunch
sumber
Satu-satunya masalah adalah bahwa contoh khusus ini mengacu pada gitignore global yang seharusnya saya sebutkan. Saya tahu saya dapat memaksa menambahkan item, tetapi saya harus melakukannya jika ada item baru yang ditambahkan, serta pada awalnya untuk setiap repositori baru. Apakah .keep memastikan konten tidak diabaikan?
Wil
1
Melakukan sedikit tes. Ya, Anda harus menggunakan git add --forceuntuk setiap item atau folder baru di KEEP_ME. tetapi setelah itu, pembaruan baru saja ditambahkan (ketika melakukan git add -umisalnya) seolah-olah file tersebut 'tidak diabaikan'. Itu .keep_metidak melakukan apa-apa, itu hanya sebuah file sehingga git beroperasi pada folder tersebut.
Commonpike
1
git add --forceadalah solusi yang salah untuk ini. Jika Anda memindahkan direktori atau memindahkan file ke direktori lain, pelacakan git akan menghapus file tetapi tidak menambahkannya ke lokasi baru dan Anda harus melakukannya git add --forcelagi. dengan tidak mengabaikan pola umum, git akan melacak pergerakan file di dalam repo.
Merlin
Ini adalah satu-satunya solusi yang berhasil untuk saya. Folder saya TIDAK diabaikan, tetapi saya tidak dapat menambahkannya dengan cara apa pun. Cara ini memecahkannya untuk saya.
Akito
6

Mencoba mencari cara untuk menyertakan folder tertentu saat mengecualikan semua folder dengan pengecualian umum

**/build

jika Anda menambahkan /*akhir dari pengecualian umum Anda, Anda terus mengecualikan semua file build**/build/*

Kemudian Anda menambahkan baris lain untuk mengoreksi jalur yang ingin Anda sertakan agar terlihat seperti

!**/folder/build/* 

meninggalkan kami gitignore yang berbunyi

**/build/* 
!**/folder/build/* 
John
sumber
2

Jawaban Buo-Ren Lin dan John cukup membantu, tetapi saya perlu menggabungkan keduanya.

Ketika ingin mengecualikan sub-folder lain serta file dalam unggahan, saya merasa perlu untuk secara eksplisit menentukan direktori sewenang-wenang sebelum folder yang diberikan baik saat mengecualikan folder dan saat memasukkan sub-folder

**/uploads/*
!**/uploads/rubbish/
!**/uploads/rubbish/*

Saya juga merasa perlu untuk secara eksplisit memasukkan kembali sub-folder dan isinya untuk menampilkan kedua item di dalam folder dan sub-folder.

Josiah Yoder
sumber
Mendesah. Nol keberuntungan di sini. Saat ini selama berjam-jam sekarang. Git 2.20.1
RichieHH
@ HörmannHH Maaf mendengarnya. Mungkin sudah waktunya untuk mengajukan pertanyaan baru?
Josiah Yoder
2

Solusi yang disajikan sebagai jawaban dengan suara terbanyak adalah salah, dan dengan mudah dapat dibuktikan.

Mulailah dengan mengabaikan semua yang ada di unggahan / *:

mkdir -p uploads/rubbish/stuff/KEEP_ME
touch uploads/a uploads/rubbish/a uploads/rubbish/stuff/a uploads/rubbish/stuff/KEEP_ME/a
echo '/uploads/*' >> .gitignore
git init
git add .
git commit -m "Initial commit"

Sekarang hilangkan direktori induk dari hal-hal yang diabaikan seperti di atas:

echo 'uploads/rubbish/stuff/KEEP_ME/' >> .gitignore
echo 'uploads/rubbish/stuff/KEEP_ME/*' >> .gitignore
git status -u

Tidak menampilkan file yang tidak terlacak.

Untuk membuatnya berfungsi, Anda perlu mengabaikan semua file di bawah uploads/pohon ( uploads/**/*, bukan hanya tingkat atas, uploads/*) dan kemudian menambahkan semua direktori induk dari pohon yang ingin Anda pertahankan

echo '/uploads/**/*' > .gitignore
echo '!/uploads/rubbish/' >> .gitignore
echo '!/uploads/rubbish/stuff' >> .gitignore
echo '!/uploads/rubbish/stuff/KEEP_ME' >> .gitignore
echo '!/uploads/rubbish/stuff/KEEP_ME/*' >> .gitignore
git status -u

Pemberian yang mana:

On branch master
...
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        uploads/rubbish/stuff/KEEP_ME/a

Jika kita telah menggunakan uploads/*di .gitignoreatas, maka semua file perantara akan disertakan juga, jadi misalnya uploads/rubbish/aakan muncul di perintah status di atas.

pengguna295691
sumber