ยกเลิกไดเร็กทอรีย่อยของไดเร็กทอรีที่ละเว้นใน Git


103

สมมติว่าฉันไม่สนใจไดเร็กทอรี แต่ฉันต้องการยกเลิกไดเร็กทอรีย่อยเฉพาะในนั้น ดังนั้นฉันจึงมีการตั้งค่า:

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

และฉันต้องการละเว้นทุกอย่างยกเว้นKEEP_MEไดเรกทอรี ฉันหวังว่าการเพิกเฉยจะมีลักษณะดังนี้:

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

แต่ไม่ได้ผลและไม่มีการเรียงสับเปลี่ยนหลายรายการในธีมเดียวกัน

สิ่งหนึ่งที่ได้ผลคือ

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

แต่รู้สึกว่ามีข้อ จำกัด และละเอียดอ่อนเล็กน้อย?


1
รหัสที่คุณระบุใช้ไม่ได้สำหรับฉัน (ใช้ git เวอร์ชัน 1.9.1) สิ่งที่ใช้ได้คือ / uploads / *! / uploads / rubbish / / uploads / rubbish / *! / uploads / rubbish / stuff / uploads / rubbish / stuff / *! / uploads / rubbish / stuff / keep (ซึ่งคล้ายกับตัวอย่าง ในgit-scm.com/docs/gitignore ) โครงสร้างโฟลเดอร์ของฉัน; └ README.md └อัปโหลด / foo / bar / lose / lose.txt └อัปโหลด / ขยะ / สิ่งของ / เก็บ / keep.txt
gihanchanuka

คำตอบ:


119

ตามส่วนรูปแบบรูปแบบของเอกสาร gitignore :

คำนำหน้า "!" ซึ่งลบล้างรูปแบบ ไฟล์ที่ตรงกันใด ๆ ที่ถูกยกเว้นโดยรูปแบบก่อนหน้านี้จะรวมอีกครั้ง ไม่สามารถรวมไฟล์ใหม่ได้หากไม่รวมไดเร็กทอรีหลักของไฟล์นั้น Git ไม่แสดงรายการไดเรกทอรีที่ยกเว้นเนื่องจากเหตุผลด้านประสิทธิภาพดังนั้นรูปแบบใด ๆ ในไฟล์ที่มีจะไม่มีผลไม่ว่าจะกำหนดไว้ที่ใด ใส่แบ็กสแลช ("\") ไว้ข้างหน้า "!" อันแรก สำหรับรูปแบบที่ขึ้นต้นด้วยตัวอักษร "!" เช่น "! important! .txt"

ดังนั้น/uploads/rubbish/stuff/keep/รูปแบบไดเร็กทอรีพาเรนต์ที่ถูกยกเว้นก่อนหน้านี้จะต้องถูกทำให้เป็นลบก่อนที่จะลบเนื้อหา:

#ignore everything within /uploads/ 
/uploads/*

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

หากต้องการรวมไดเรกทอรีย่อยภายในให้/uploads/rubbish/stuff/keep/เพิ่มบรรทัดที่สาม:

!/uploads/rubbish/stuff/keep/**/*

1
คุณใช้คอมไพล์เวอร์ชันใด อาจเป็นบางอย่างที่มีเฉพาะในบางเวอร์ชัน

อาย. ฉันลืมฉันโพสต์ความคิดเห็นนี้ ฉันทำให้มันใช้งานได้ FWIW ฉันไม่ใช้เครื่องหมายทับ ฉันจำไม่ได้ว่าเป็นปัญหาหรือไม่ ฉันใช้ 1.7.2.5

ฉันมีไฟล์ gitignore ส่วนกลางที่ฉันไม่สนใจไฟล์ * .zip ทั้งหมด แต่สำหรับโปรเจ็กต์เฉพาะฉันต้องการรวมไฟล์ zip ฉันเพิ่มบรรทัดนี้ในโครงการนั้น.gitignoreและมันก็ใช้งานได้ดี!:!*.zip
Jinghao Shi

ผมพบว่ามันจำเป็นที่จะต้องระบุอย่างชัดเจนไดเรกทอรีโดยพลการทั้งก่อนและหลังที่กำหนดโฟลเดอร์ทั้งในขณะที่ยังไม่รวมโฟลเดอร์และในขณะที่รวมทั้งโฟลเดอร์ย่อย ( คำตอบแบบเต็ม ).
Josiah Yoder

1
วิธีนี้ใช้ไม่ได้ (ณ git 2.25 - อาจมีการเปลี่ยนแปลงบางอย่างในคอมไพล์) ฉันโพสต์stackoverflow.com/a/60288435/295691ด้านล่างเพื่อเป็นการแก้ไข
user295691

35

แม้ว่าคุณจะเพิ่มบางสิ่งลงไป.gitignoreคุณสามารถบังคับให้คอมไพล์เพิ่มลงในดัชนีได้

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

อย่างไรก็ตาม "KEEP_ME" ดูเหมือนจะเป็นไดเร็กทอรีและโดยปกติ git จะไม่เหมือนโฟลเดอร์ว่างดังนั้นคุณควรเพิ่มไฟล์ "ตัวยึดตำแหน่ง" แทนหากโฟลเดอร์ว่างเปล่า

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

ปัญหาเดียวที่เกิดขึ้นคือตัวอย่างเฉพาะนี้อ้างถึง gitignore ระดับโลกที่ฉันควรกล่าวถึง ฉันรู้ว่าฉันสามารถบังคับให้เพิ่มรายการได้ แต่ฉันจะต้องทำเช่นนั้นหากมีการเพิ่มรายการใหม่รวมทั้งเริ่มต้นสำหรับที่เก็บใหม่แต่ละรายการ ทำให้แน่ใจว่าเนื้อหาจะไม่ถูกละเลยหรือไม่?
วิล

1
ได้ทำการทดสอบเล็กน้อย ใช่คุณต้องใช้สำหรับรายการใหม่ทุกหรือโฟลเดอร์ในgit add --force KEEP_MEแต่หลังจากนั้นจะมีการเพิ่มการอัปเดต (เมื่อทำgit add -uตัวอย่าง) ราวกับว่าไฟล์นั้น 'ไม่มีเครื่องหมาย' .keep_meไม่ทำอะไรเลยเพียงแค่ไฟล์เพื่อให้คอมไพล์ที่ดำเนินการบนโฟลเดอร์
commonpike

1
git add --forceเป็นทางออกที่ผิดสำหรับสิ่งนี้ หากคุณย้ายไดเร็กทอรีไปรอบ ๆ หรือย้ายไฟล์ไปยังไดเร็กทอรีอื่นการติดตามของ git จะลบไฟล์ แต่ไม่เพิ่มลงในตำแหน่งใหม่และคุณต้องทำgit add --forceอีกครั้ง โดยการยกเลิกการให้ความสำคัญกับรูปแบบทั่วไป git จะติดตามการเคลื่อนไหวของไฟล์ภายใน repo
Merlin

นี่เป็นทางออกเดียวที่ใช้ได้ผลสำหรับฉัน โฟลเดอร์ของฉันไม่ถูกเพิกเฉย แต่ฉันไม่สามารถเพิ่มได้ด้วยวิธีใด ๆ วิธีนี้แก้ไขให้ฉัน
Akito

6

กำลังพยายามหาวิธีรวมโฟลเดอร์เฉพาะเมื่อไม่รวมโฟลเดอร์ทั้งหมดด้วยการยกเว้นทั่วไป

**/build

หากคุณเพิ่มส่วน/*ท้ายของการยกเว้นทั่วไปของคุณคุณจะยังคงยกเว้นไฟล์บิลด์ทั้งหมด**/build/*

จากนั้นคุณเพิ่มอีกบรรทัดเพื่อแก้ไขเส้นทางที่คุณต้องการรวมให้มีลักษณะเช่นนี้

!**/folder/build/* 

ปล่อยให้เราเป็น gitignore ที่อ่าน

**/build/* 
!**/folder/build/* 

4

คำตอบของBuo-Ren LinและJohnค่อนข้างมีประโยชน์ แต่ฉันต้องรวมทั้งสองอย่างเข้าด้วยกัน

เมื่อต้องการยกเว้นโฟลเดอร์ย่อยอื่น ๆ รวมทั้งไฟล์ในการอัปโหลดฉันพบว่าจำเป็นต้องระบุไดเร็กทอรีโดยพลการอย่างชัดเจนก่อนโฟลเดอร์ที่กำหนดทั้งในขณะที่ไม่รวมโฟลเดอร์และในขณะที่รวมโฟลเดอร์ย่อย

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

ฉันยังพบว่าจำเป็นต้องรวมทั้งโฟลเดอร์ย่อยและเนื้อหาอีกครั้งอย่างชัดเจนเพื่อแสดงทั้งสองรายการภายในโฟลเดอร์และโฟลเดอร์ย่อย


เฮ้อ. โชคเป็นศูนย์ที่นี่ ตอนนี้เป็นเวลาหลายชั่วโมงแล้ว Git 2.20.1
RichieHH

@ HörmannHHเสียใจที่ได้ยินเช่นนั้น อาจถึงเวลาถามคำถามใหม่
Josiah Yoder

4

วิธีแก้ปัญหาที่แสดงเป็นคำตอบที่มีการโหวตมากที่สุดนั้นไม่ถูกต้องและสามารถพิสูจน์ได้ง่ายเช่นนี้

เริ่มต้นด้วยการละเว้นทุกสิ่งในการอัปโหลด / *:

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"

ตอนนี้ยกเลิกการใส่ไดเร็กทอรีหลักของสิ่งที่ถูกละเว้นตามด้านบน:

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

ไม่แสดงไฟล์ที่ไม่ถูกติดตาม

เพื่อให้มันใช้งานได้คุณต้องละเว้นไฟล์ทั้งหมดที่อยู่ใต้uploads/โครงสร้าง ( uploads/**/*ไม่ใช่แค่ระดับบนสุดuploads/*) จากนั้นเพิ่มไดเร็กทอรีหลักทั้งหมดของต้นไม้ที่คุณต้องการเก็บไว้

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

ซึ่งจะช่วยให้:

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

หากเราใช้uploads/*ใน.gitignoreข้างต้นไฟล์กลางทั้งหมดจะถูกรวมไว้ด้วยเช่นกันตัวอย่างเช่นuploads/rubbish/aจะปรากฏในคำสั่งสถานะด้านบน


ขอบคุณสิ่งเดียวที่ใช้ได้ผลสำหรับฉัน
Sebastien Lorber
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.