เพิ่มไฟล์ซ้ำตามรูปแบบซ้ำ ๆ


172

ฉันจะเพิ่มไฟล์ซ้ำโดยใช้รูปแบบ (หรือ glob) ในไดเรกทอรีอื่นได้อย่างไร

ตัวอย่างเช่นฉันต้องการเพิ่มA/B/C/foo.javaและD/E/F/bar.java(และไฟล์ java อื่น ๆ อีกหลายไฟล์) ด้วยคำสั่งเดียว:

git add '*.java'

น่าเสียดายที่มันใช้งานไม่ได้ตามที่คาดไว้


2
มันใช้งานได้สำหรับฉัน (Mac OS X, Git 1.7.1+) คุณใช้ OS และ Git เวอร์ชั่นใด?
Chris Johnsen

3
ถ้าคุณมีบางคน (การติดตามแล้ว) .javaไฟล์ในไดเรกทอรีปัจจุบันของคุณคุณอาจจะทำงานเป็นเอ่อจัดการสัญลักษณ์แทนความซับซ้อนระหว่างทุบตีและ MSYS บรรทัดคำสั่ง“ผู้ช่วย” ฉันไม่แน่ใจเกี่ยวกับวิธีแก้ปัญหา คุณอาจลองใช้อัญประกาศหลายเลเยอร์: git add '"*.java"'(อัญประกาศเดี่ยวถูกใช้โดยbashเพื่อป้องกันการขยาย glob, อัญประกาศคู่ถูกใช้โดยเลเยอร์ msys เพื่อป้องกันการขยายตัวของ glob)
Chris Johnsen

1
ขอบคุณสำหรับการบันทึก น่าเสียดายที่มันไม่ได้ผลเหมือนกัน พวกเขาบอกว่าได้รับการแก้ไขแล้ว แต่ฉันมีเวอร์ชันล่าสุดแล้ว
Michel Krämer


1
git add *.javaทำงานได้สำหรับฉัน (บน PowerShell กับลูกค้า GitHub)
ThaDafinser

คำตอบ:


89

คำตอบของ Sergio Acosta อาจเป็นทางออกที่ดีที่สุดของคุณหากไฟล์ที่จะเพิ่มบางไฟล์อาจยังไม่ถูกติดตาม หากคุณต้องการ จำกัด ตัวเองให้เป็นไฟล์ที่คอมไพล์รู้อยู่แล้วคุณสามารถรวมgit-ls-filesกับตัวกรองได้:

git ls-files [path] | grep '\.java$' | xargs git add

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


8
ขอบคุณ! ฉันปรับปรุงคำสั่งของคุณเล็กน้อยและตอนนี้มันกำลังทำสิ่งที่ฉันกำลังมองหา:git ls-files -co --exclude-standard | grep '\.java$' | xargs git add
Michel Krämer

169

คุณสามารถใช้git add [path]/\*.javaเพื่อเพิ่มไฟล์ java จากไดเรกทอรีย่อย
เช่นgit add ./\*.javaสำหรับไดเรกทอรีปัจจุบัน

จากgit addเอกสาร :

เพิ่มเนื้อหาจาก*.txtไฟล์ทั้งหมดภายใต้Documentationไดเรกทอรีและไดเรกทอรีย่อย:

$ git add Documentation/\*.txt

โปรดสังเกตว่าเครื่องหมายดอกจัน*ถูกยกมาจากเชลล์ในตัวอย่างนี้ สิ่งนี้อนุญาตให้คำสั่งรวมไฟล์จากไดเร็กทอรีย่อยของDocumentation/ไดเร็กทอรี


2
@ MichelKrämerอาจไม่ใช่ แต่ตอนนี้
Alberto

7
นี่เป็นทางออกที่ดีที่สุดทำงานใน windows ได้เช่นกัน
TheTFo

1
"เครื่องหมายดอกจัน * ถูกยกมาจากเชลล์" ฉันคิดว่าคุณหมายถึง "หลบหนี" ไม่ว่าในกรณีใดแบ็กสแลชจะป้องกันเชลล์จากการขยาย
gwideman

1
@ gwideman ฉันคิดว่าคุณพูดถูก แต่ไม่ใช่ฉัน มันเป็นคำพูดจาก docs git-scm.com/docs/git-add#_examples
Sergey Glotov

62

ด้วยzshคุณสามารถเรียกใช้:

git add "**/*.java"

และ*.javaไฟล์ทั้งหมดของคุณจะถูกเพิ่มซ้ำ


ขอบคุณสำหรับสิ่งนั้น แต่ฉันกำลังทำงานกับ msysgit บน Windows และมีการทุบตีเท่านั้น
Michel Krämer

1
ฉันเห็นว่ามีzshเปลือกสำหรับ windows ... คุณจะทำเองชอบใช้แทนทุบตี imho
Olivier Verdier

1
พอร์ต zsh ของ Windows นั้นใช้รุ่นเก่ามากและล่มตลอดเวลา (เช่นเมื่อฉันป้อนls)
Michel Krämer

ว้าวสมบูรณ์แบบ ฉันไม่รู้เกี่ยวกับคุณสมบัตินั้น!
Tomáš Votruba

1
นี่คืออะไรจะทำอย่างไรกับ zsh ฉันคิดว่าคำตอบนี้พลาดจุดที่คุณต้องการผ่านเส้นทางด้วย wildcards เหมือนเดิมเพื่อคอมไพล์และปล่อยให้คอมไพล์ประมวลผลมัน ดังนั้นคุณต้องการป้องกันเชลล์ที่คุณใช้ไม่ให้ขยาย wildcard ในการทำเช่นนี้คุณต้องอ้างมันด้วยวิธีที่เหมาะสมกับเชลล์ที่คุณใช้ ดูคำตอบอื่น ๆ สำหรับรายละเอียด
gwideman

55

หัวข้อเล็กน้อย (ไม่เกี่ยวข้องกับคอมไพล์โดยเฉพาะ) แต่ถ้าคุณอยู่ใน linux / unix วิธีแก้ปัญหาอาจเป็น:

find . -name '*.java' | xargs git add

และหากคุณคาดว่าเส้นทางที่มีช่องว่าง:

find . -name '*.java' -print0 | xargs -0 git add

แต่ฉันรู้ว่านั่นไม่ใช่สิ่งที่คุณถาม


6
ปัญหาเล็กน้อยเกี่ยวกับวิธีการนี้ - หากคุณ "ค้นหา" ไฟล์ที่ตรงกับ. gitignore ของคุณ git ก็บ่นว่าคุณพยายามที่จะเพิ่มไฟล์ที่คุณบอกว่าจะเพิกเฉย
yoyo

2
@yoyo - ฉันเพิ่งเพิ่ม -f ในตอนท้ายและนั่นก็แก้ไขได้
Maslow

5
@Maslow ที่จะบังคับให้เพิ่มไฟล์แม้ว่ามันจะถูกละเว้น (ตาม. gitignore) ฉันต้องการรับการร้องเรียนและไม่เพิ่มไฟล์ (ซึ่งเป็นพฤติกรรมเริ่มต้น)
yoyo

นี่เป็นวิธีที่ดีกว่าการปล่อยให้คอมไพล์ทำการขยาย wildcard ได้อย่างไร?
gwideman

12

คำตอบของ Sergey (อย่าให้เครดิตฉัน) ใช้งานได้:

You can use git add [path]/\*.java

ด้วยคอมไพล์ล่าสุด:

$git version
git version 1.7.3.4

ไฟล์สำหรับการทดสอบ:

$find -name .git -prune -o -type f -print | sort
./dirA/dirA-1/dirA-1-1/file1.txt
./dirA/dirA-1/dirA-1-2/file2.html
./dirA/dirA-1/dirA-1-2/file3.txt
./dirA/dirA-1/file4.txt
./dirB/dirB-1/dirB-1-1/file5.html
./dirB/dirB-1/dirB-1-1/file6.txt
./file7.txt

สถานะ Git:

$git status -s
?? dirA/
?? dirB/
?? file7.txt

กำลังเพิ่ม * .txt:

$git add \*.txt

อัพเดทสถานะ:

$git status -s
A  dirA/dirA-1/dirA-1-1/file1.txt
A  dirA/dirA-1/dirA-1-2/file3.txt
A  dirA/dirA-1/file4.txt
A  dirB/dirB-1/dirB-1-1/file6.txt
A  file7.txt
?? dirA/dirA-1/dirA-1-2/file2.html
?? dirB/dirB-1/dirB-1-1/file5.html

8

หากคุณติดตามไฟล์ของคุณอยู่แล้วและทำการเปลี่ยนแปลงกับไฟล์เหล่านั้นและตอนนี้คุณต้องการเพิ่มไฟล์ตามแบบที่เลือกคุณสามารถใช้การ--modifiedตั้งค่าสถานะ

git ls-files --modified | grep '<pattern>' | xargs git add

ตัวอย่างเช่นหากคุณต้องการเพิ่มการเปลี่ยนแปลง CSS ในการส่งข้อมูลนี้คุณสามารถทำได้

git ls-files --modified | grep '\.css$' | xargs git add

ดูman git-ls-filesธงเพิ่มเติม


5

git add *\*.javaใช้เพียงแค่ สิ่งนี้จะเพิ่มไฟล์. java ทั้งหมดในไดเรกทอรีรากและไดเรกทอรีย่อยทั้งหมด


คำตอบที่ดี ฉันทำ git add * / pom.xml เพื่อเพิ่มชื่อไฟล์ทั้งหมด pom.xml
ฟิลิป Rego

4

การเพิ่มโซลูชันบรรทัดคำสั่งของ Windows ที่ยังไม่ได้กล่าวถึง:

for /f "delims=" %G in ('dir /b/s *.java') do @git add %G

3

ฉันต้องการเพิ่มเฉพาะไฟล์ที่มีสตริงที่แน่นอนตามgit status:

git status | grep string | xargs git add

และจากนั้นก็สามารถที่จะgit commit -m 'commit msgส่งมอบไฟล์ที่เปลี่ยนแปลงทั้งหมดด้วย "สตริง" ในชื่อของไฟล์


2

ดังที่ได้กล่าวไว้ใน " git: ฉันจะเพิ่มไฟล์ทั้งหมดซ้ำ ๆ ในทรีย่อยของไดเรกทอรีที่ตรงกับรูปแบบ glob ได้อย่างไร " ถ้าคุณหลบหนีหรืออ้างคำพูดของคุณเป็นอย่างดี spsp globbing (เช่น'*.java' ) แล้วใช่เพิ่มคอมไพล์'*.java'

Git 2.13 (Q2 2017) ปรับปรุงให้ดีขึ้นสำหรับการเพิ่มแบบโต้ตอบ:

ดูกระทำ 7288e12 (14 มีนาคม 2017) โดยเจฟฟ์คิง (peff )
(รวมโดยJunio C Hamano - gitster-ในการกระทำ 153e0d7 , 17 มีนาคม 2017)

add --interactive: ห้ามขยาย pathspecs ด้วย ls-files

เมื่อเราต้องการได้รับรายชื่อไฟล์ที่ถูกแก้ไขอันดับแรกเราจะขยาย pathspecs ที่ผู้ใช้กำหนดด้วย " ls-files" จากนั้นฟีดรายการพา ธ ผลลัพธ์ที่ได้จะเป็นอาร์กิวเมนต์ของ " diff-index" และ " diff-files"
หากเส้นทางของคุณขยายไปสู่เส้นทางจำนวนมากคุณอาจพบปัญหาข้อใดข้อหนึ่งดังนี้

  1. ระบบปฏิบัติการอาจบ่นเกี่ยวกับขนาดของรายการอาร์กิวเมนต์และปฏิเสธที่จะทำงาน ตัวอย่างเช่น:

    $ (ulimit -s 128 && git add -p drivers)
    Can't exec "git": Argument list too long at .../git-add--interactive line 177.
    Died at .../git-add--interactive line 177.
    

ที่อยู่ในlinux.gitพื้นที่เก็บข้อมูลซึ่งมีไฟล์ประมาณ 20K ในไดเรกทอรี "drivers" (ไม่มีไฟล์ใดที่แก้ไขในกรณีนี้) "การulimit -s" เคล็ดลับเป็นสิ่งจำเป็นที่จะแสดงปัญหาบน Linux แม้สำหรับเช่นชุดขนาดยักษ์ของเส้นทาง
ระบบปฏิบัติการอื่นมีขีด จำกัด ที่น้อยกว่ามาก (เช่นกรณีที่เกิดขึ้นจริงกับไฟล์ 5K บน OS X เท่านั้น)

  1. แม้ว่ามันจะใช้งานได้มันก็ช้าจริงๆ รหัส pathspec ไม่ได้รับการปรับให้เหมาะสมกับเส้นทางจำนวนมาก นี่เป็นกรณีเดียวกันโดยไม่มี ulimit:

    $ time git add -p drivers
      No changes.
    
    real  0m16.559s
    user    0m53.140s
    sys 0m0.220s
    

เราสามารถปรับปรุงสิ่งนี้ได้โดยการข้าม " ls-files" อย่างสมบูรณ์และเพียงป้อนพา ธ สเปคดั้งเดิมไปยังคำสั่ง diff

ในอดีตภาษาพา ธ สเปคที่รองรับโดย " diff-index" นั้นอ่อนแอกว่า แต่ก็ไม่เป็นเช่นนั้นอีกต่อไป


1

ใส่บรรทัดใน ~ / .gitconfig

[alias] addt = !sh -c 'git ls-files | grep \"\\.$1*\" | xargs git add' -

หากคุณต้องการเพิ่มไฟล์ java ที่แก้ไขทั้งหมดสามารถทำได้ดังนี้: git addt java

ถ้าคุณต้องการเพิ่มไฟล์ python ที่แก้ไขทั้งหมดสามารถทำได้ดังนี้: git addt py

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