วิธีการแสดงเฉพาะส่วนของไฟล์ใหม่ด้วย git?


222

ฉันรัก คอมไพล์เพิ่ม --interactive ตอนนี้เป็นส่วนหนึ่งของกระบวนการทำงานประจำวันของฉัน

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

ตัวอย่างเช่นด้วย git add -i ฉันสามารถเลือกตัวเลือกการแก้ไขและแม้แต่แก้ไข hunks แต่ละรายการเพื่อแยกส่วนของรหัสใหม่ออกไป ฉันชอบทำงานในลักษณะนี้เพราะมันทำให้เห็นชัดว่าสถานที่ของโปรแกรมแก้ไข mega ที่ฉันกำลังทำงานอยู่ยังต้องการงาน

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

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

คำตอบ:


415

โอ้โหสิ่งนั้นupdate-indexและเรื่องhash-objectธุรกิจดูซับซ้อนเกินไป วิธีการเกี่ยวกับเรื่องนี้แทน:

git add -N new_file
git add -i

จากgit help add:

-N, --intent-to-add
    Record only the fact that the path will be added later.  An entry
    for the path is placed in the index with no content.  This is useful
    for, among other things, showing the unstaged content of such files
    with git diff and committing them with git commit -a.

9
++ 1! เครดิตเนื่องจาก ฉันเชื่อใจมากเกินไปจนฉันรู้ manpages เหล่านี้ในตอนนี้ ....</shame>
sehe

1
พบกันดี ฉันควรเลื่อน man page ไปอีกเล็กน้อย บางทีฉันควรส่งคืนตรา Git Pro
dave1010

3
สงสัยว่าทำไม git-gui ไม่ได้ใช้สิ่งนี้ภายในเพื่อให้สามารถจัดลำดับบรรทัดจากไฟล์ใหม่
Deiwin

6
การ-Nค้นพบที่ยอดเยี่ยมขอบคุณ! แม้ว่าฉันจะชอบรวมกับ-pในกรณีที่ gid add -N the_file& git add -p. หนึ่งควรเพิ่มว่า-Nยังทำงานร่วมกับ-A
Cyril Chapon

@Deiwin - คุณสามารถเพิ่ม [guitool] ใน. gitconfig ของคุณเพื่อทำ "git add -N $ FILENAME": [guitool "เพิ่มด้วยเจตนา"] cmd = "git เพิ่ม -N $ FILENAME" needsfile = ใช่ noconsole = ใช่
Steve Folly

7

วิธีที่ง่ายที่สุดที่จะทำนี้ (และการแสดงละคร IMHO โต้ตอบทั่วไป) git guiคือ มันมาพร้อมกับ git และควรทำงานบนแพลตฟอร์มเกือบทั้งหมดที่รองรับโดย git

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

ภาพหน้าจอของ Git Gui


นี่เป็นคำตอบที่สร้างสรรค์และบางครั้งมันก็มีประโยชน์มาก
Pablo Olmos de Aguilera C.

3
เพียงทราบว่าการแจกแจงของ git ไม่รวมgit guiทั้งหมด ตัวอย่างเช่นใน Debian มันอยู่ในแพ็คเกจแยกต่างหากที่เรียกว่า 'git-gui'
cristoper

ได้รับการมอง (ไม่ยากพอ) สำหรับคุณสมบัตินี้มานานหลายปีนี่คือการเปลี่ยนชีวิต
austinmarton

2
สำหรับฉันการจัดเตรียมไฟล์บรรทัดเดียวที่git guiไม่ได้ติดตามไม่เคยทำงาน ในความเป็นจริงมันปิดการใช้งานเมนูตัวเลือกเหล่านี้
Deiwin

2
@Deinwin ฉันต้องพลาดจริง ๆ ในคำถาม - ภาพหน้าจอของฉันแสดงไฟล์ที่ถูกติดตามแล้ว หากคุณต้องการใช้git guiไฟล์ใหม่คุณต้องเรียกใช้git add -N new_fileก่อน - ดูคำตอบของ Richard Hansen
Chronial

6
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
git add --interactive newfile

ตัวอย่างง่ายๆ:

mkdir /tmp/demo
cd /tmp/demo
git init .

echo hello > newfile
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
  • คำแนะนำหากคุณแน่ใจว่าหยด 'ว่าง' มีอยู่แล้วในฐานข้อมูลวัตถุ git ของคุณคุณสามารถเข้ารหัสแฮชe69de29bb2d1d6434b8b29ae775ad8c2e48c5391แทนได้ ฉันไม่แนะนำให้ทำเช่นนั้น _
  • คำแนะนำหากคุณใช้ Windows คุณอาจใช้NUL:แทน/dev/nullได้ มิฉะนั้นใช้สิ่งที่ชอบecho -n '' | git hash-object --stdin -w

ตอนนี้ดัชนีจะมีnewfileเป็น blob ที่ว่างเปล่าและ blob ที่ว่างเปล่าได้ถูกป้อนเข้าไปในฐานข้อมูลวัตถุหากยังไม่มี:

$ find .git/objects/ -type f 
.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391

$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   newfile
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   newfile
#

$ git diff
diff --git a/newfile b/newfile
index e69de29..ce01362 100644
--- a/newfile
+++ b/newfile
@@ -0,0 +1 @@
+hello

นี่ควรเป็นสิ่งที่คุณต้องการอย่างแม่นยำ อาจฉันขอแนะนำเป็นกลุ่มผู้ลี้ภัยปลั๊กอินสำหรับการจัดการดัชนีฉลาดมาก (ดูดีกว่า GIT เพิ่ม -p? )


1
ดูเหมือนว่าจะทำงานได้ดี ฉันใช้นามแฝงว่า "ไฟล์ที่ว่างในขั้นตอน" เนื่องจากมันซับซ้อนเล็กน้อยที่จะจำ
dave1010

@ dave1010: ดีใจที่มันช่วยได้! ใช่ฉันคิดเกี่ยวกับการเพิ่มชื่อแทน แต่ฉันไม่รู้ว่าคุณจะคาดหวังได้อย่างไรว่าจะจัดการเช่น wildcard หรืออาร์กิวเมนต์ชื่อไฟล์หลายรายการโดยทั่วไป ดังนั้นฉันเลือกที่จะไม่
sehe

2

แก้ไข:ดูเหมือนจะไม่ทำงานในขณะนี้ ฉันแน่ใจว่ามันเป็นมาก่อน (บน git 1.7.1) ในกรณีที่ใช้งานไม่ได้ผมขอแนะนำให้เตรียมการแสดง/dev/nullตามที่ Sehe แนะนำข้างต้น:

git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile

หากคุณใช้ Windows (ไม่ใช้/dev/null) คุณสามารถแทนที่ด้วยพา ธ ไปยังไฟล์ว่าง

คำตอบเดิม

คุณต้องการ

git add -p # (or --patch)

นี่เป็นการเพิ่มไฟล์ที่ไม่ได้ติดตามสำหรับฉัน จากหน้าคน:

เลือก hunks ของ patch ระหว่างดัชนีและแผนผังการทำงานแบบโต้ตอบและเพิ่มไปยังดัชนี สิ่งนี้จะช่วยให้ผู้ใช้มีโอกาสตรวจสอบความแตกต่างก่อนที่จะเพิ่มเนื้อหาที่แก้ไขไปยังดัชนี

สิ่งนี้รันการเพิ่มอย่างมีประสิทธิภาพ - โต้ตอบ แต่ข้ามเมนูคำสั่งเริ่มต้นและข้ามไปยังคำสั่งย่อย patch โดยตรง ดู“ โหมดโต้ตอบ” สำหรับรายละเอียด


2
อย่างไรก็ตามสิ่งที่น่าสนใจมันไม่ได้ผลสำหรับฉัน (git 1.7.4); git add -p newfileไม่ทำงานเลย (nu effect) และgit add --interactive'[a] dd untracked' มีเอฟเฟกต์ที่git add newfileมี; แก้ไขตรวจสอบด้วย git 1.7.5.3; ไม่มีลูกเต๋า
sehe

คำใบ้ที่ดีสำหรับ Windows เพิ่มคำแนะนำสำหรับสิ่งนั้นในคำตอบของฉัน ขอบคุณ
sehe

-2

เพียงเพื่อบันทึกความเป็นไปได้อื่น: ฉันใช้

git add -N file
git add -p file

และจากนั้นคุณสามารถสเตจล่าหรือแก้ไขได้


1
คำตอบนี้บอกว่าเหมือนกับคำตอบที่ยอมรับซึ่งย้อนกลับไปในปี 2011 Downvote
Stanislav Pankevich

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