ฉันจะแยกไฟล์เดียว (หรือเปลี่ยนเป็นไฟล์) จากที่เก็บ git ได้อย่างไร


773

ฉันต้องการทราบว่าเป็นไปได้หรือไม่ที่จะแยกไฟล์เดียวหรือแตกต่างจากไฟล์จาก git stash โดยไม่ต้องหยุดเซ็ตการแก้ไขที่ซ่อน

ใครบ้างที่สามารถให้คำแนะนำ / แนวคิดเกี่ยวกับเรื่องนี้ได้บ้าง

คำตอบ:


1130

บนmanpage git stashคุณสามารถอ่านได้ (ในส่วน "Discussion" หลังจากคำอธิบาย "Options") ที่:

Stash จะถูกแสดงเป็นคอมมิชชันที่ทรีบันทึกสถานะของไดเร็กทอรีการทำงานและพาเรนต์แรกของมันคือ commit ที่ HEAD เมื่อสแตชถูกสร้าง

ดังนั้นคุณสามารถรักษาที่ซ่อน (เช่นstash@{0}เป็นที่แรก / ที่เก็บสูงสุด) เป็นการรวมที่กระทำและใช้:

$ git diff stash@{0}^1 stash@{0} -- <filename>

คำอธิบาย: stash@{0}^1หมายถึงผู้ปกครองคนแรกของที่เก็บที่กำหนดซึ่งตามที่ระบุไว้ในคำอธิบายข้างต้นคือการกระทำที่การเปลี่ยนแปลงถูกเก็บซ่อนไว้ เราใช้รูปแบบนี้ของ "git diff" (มีสองคอมมิท) เนื่องจากstash@{0}/ refs/stashเป็นการรวมที่คอมมิชชันและเราต้องบอกคอมไพล์ว่าผู้ปกครองใดที่เราต้องการแตกต่าง ความลับเพิ่มเติม:

$ git diff stash@{0}^! -- <filename>

ควรใช้งานได้ด้วย (ดูgit rev-parse manpage สำหรับคำอธิบายเกี่ยวกับrev^!ไวยากรณ์ในส่วน "การระบุช่วง")

ในทำนองเดียวกันคุณสามารถใช้การชำระเงิน gitเพื่อตรวจสอบไฟล์เดียวจากที่เก็บ:

$ git checkout stash@{0} -- <filename>

หรือเพื่อบันทึกภายใต้ชื่อไฟล์อื่น:

$ git show stash@{0}:<full filename>  >  <newfile>

หรือ

$ git show stash@{0}:./<relative filename> > <newfile>

( โปรดทราบว่าที่นี่ <ชื่อไฟล์เต็ม> เป็นชื่อพา ธ เต็มของไฟล์ที่สัมพันธ์กับไดเรกทอรีบนสุดของโครงการ (คิดว่า: สัมพันธ์กับstash@{0}))


คุณอาจจำเป็นต้องปกป้องstash@{0}จากการขยายตัวของเปลือกใช้ IE หรือ"stash@{0}"'stash@{0}'


8
นี่มันเจ๋งมาก ... ฉันไม่เข้าใจจริง ๆว่าที่เก็บทำงานได้อย่างไรจนกว่าฉันจะอ่านคำตอบของคุณ ฉันไม่ได้รับจริง ๆ เมื่อคุณทำที่เก็บซ่อนคอมไพล์บันทึกสองคอมมิชชัน - หนึ่งสำหรับสถานะของดัชนีและหนึ่งสำหรับสถานะของสำเนาการทำงานซึ่งเป็นการผสานระหว่างดัชนีและหัวเดิม สิ่งนี้อธิบายต้นไม้แปลก ๆ ที่ฉันเห็นเมื่อฉันเห็นภาพของที่เก็บด้วย "gitk --all" เมื่อมีการหยุดทำงาน
Pat Notz

4
ส่วนใหญ่ฉันพบว่าแอปพลิเคชันชำระเงิน git เป็นวิธีที่ดีที่สุดในการบรรลุสิ่งที่ฉันต้องการจะทำ อย่างไรก็ตามฉันเป็นคนอยากรู้อยากเห็นและตรวจสอบgit checkoutหน้าคนอีกครั้ง ไม่สามารถวางไฟล์ลงในตำแหน่งอื่นได้ มีการอ้างอิงถึงสิ่งนี้ใน: stackoverflow.com/questions/888414/…
Danny

84
$ git checkout stash @ {0} - <filename> มีประโยชน์มากขอบคุณ
ความโน้มถ่วง

43
โปรดทราบว่าgit checkoutวิธีการคัดลอกไฟล์ที่ถูกต้องจากที่เก็บ - มันไม่ได้รวมกับสิ่งที่อยู่ในไดเรกทอรีการทำงานของคุณเช่นgit stash applyจะ (ดังนั้นหากคุณมีการเปลี่ยนแปลงใด ๆ จากฐานที่สะสมถูกสร้างขึ้นพวกเขาจะหายไป)
peterflynn

4
โปรดทราบว่าในgit stash applyการรวมการเปลี่ยนแปลงในไฟล์ที่ถูกแก้ไขในแผนผังการทำงานตั้งแต่ไฟล์ถูก stashed ไฟล์นั้นในแผนผังการทำงานจะต้องถูกจัดฉาก เพื่อให้การผสานอัตโนมัติทำงานไฟล์เดียวกันไม่สามารถแก้ไขได้ทั้งในสำเนาการทำงานและในการคัดลอกเพื่อรวมเข้าด้วยกัน ในที่สุดที่ซ่อนใช้ไม่ได้ลบรายการออกจากที่ซ่อนเช่นgit stash popหากว่า
วิลล์

46

หากคุณใช้git stash applyมากกว่าgit stash popจะใช้ที่เก็บฝังกับต้นไม้ทำงานของคุณ แต่ก็ยังคงเก็บไว้

เมื่อทำสิ่งนี้แล้วคุณสามารถadd/ commitไฟล์ที่คุณต้องการแล้วรีเซ็ตการเปลี่ยนแปลงที่เหลือ


2
จะปรากฏที่ซ่อนที่เฉพาะเจาะจง: git stash pop stash@{0}(รายการการเปลี่ยนแปลง stashed: git stash list)
MrYoshiji

หากไฟล์อื่น ๆ ในที่เก็บของก่อให้เกิดข้อขัดแย้งในการรวมคอมไพล์ไม่อนุญาตให้ฉันส่งไฟล์ที่ฉันต้องการ :(
cambunctious

33

มีวิธีง่ายๆในการรับการเปลี่ยนแปลงจากสาขาใด ๆ รวมถึงการหยุด:

$ git checkout --patch stash@{0} path/to/file

คุณอาจละเว้นข้อกำหนดไฟล์หากคุณต้องการแก้ไขในหลายส่วน หรือละเว้นแพทช์ (แต่ไม่ใช่พา ธ ) เพื่อรับการเปลี่ยนแปลงทั้งหมดในไฟล์เดียว แทนที่0ด้วยหมายเลขที่เก็บจากgit stash listหากคุณมีมากกว่าหนึ่ง โปรดทราบว่านี่เป็นสิ่งที่ชอบdiffและเสนอที่จะใช้ความแตกต่างทั้งหมดระหว่างสาขา ที่จะได้รับการเปลี่ยนแปลงจากเพียงคนเดียวกระทำ / ซ่อน, git cherry-pick --no-commitมีลักษณะที่


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

2
@Danijel git help checkoutอ่าน --patchทำการผสานแบบโต้ตอบมันจะใช้สิ่งใดก็ตามที่คุณอนุมัติก้อนในเชลล์ (หรืออะไรก็ตามที่คุณบันทึกถ้าคุณเลือกที่จะeแก้ไขแพตช์) เส้นทางเพียงอย่างเดียวจะเขียนทับไฟล์เช่นฉันเขียนว่า "การเปลี่ยนแปลงทั้งหมด"
Walf

1
การปรับปรุงเล็กน้อย: git config --global alias.applydiffat '!git checkout --patch "$1" -- $(git diff --name-only "$1"^ "$1")' - จากนั้นgit applydiffat stash@{4}ใช้ไฟล์ที่เปลี่ยนแปลงระหว่างที่เก็บข้อมูลและพาเรนต์เท่านั้น
Mark

25

คำตอบสั้น ๆ

หากต้องการดูไฟล์ทั้งหมด: git show stash@{0}:<filename>

เพื่อดูความแตกต่าง: git diff stash@{0}^1 stash@{0} -- <filename>


1
ฉันไม่คิดว่าเขา / เธอเกี่ยวข้องกับการดูที่เก็บสำหรับไฟล์เฉพาะ - เพียงแค่เปิดไฟล์นั้น
Amalgovinus

1
นี่คือสิ่งที่ฉันกำลังมองหา จากนั้นคุณสามารถแทนที่diffด้วยdifftoolเพื่อใช้ diff ภายนอกที่คุณชื่นชอบ
Peet Brits

19
$ git checkout stash@{0} -- <filename>

หมายเหตุ:

  1. ตรวจสอบให้แน่ใจว่าคุณใส่ช่องว่างหลัง "-"และพารามิเตอร์ชื่อไฟล์

  2. แทนที่ศูนย์ (0) ด้วยหมายเลขที่เก็บเฉพาะของคุณ ในการรับรายการที่ซ่อนใช้:

    git stash list
    

ตามคำตอบของ Jakub Narębski - เวอร์ชั่นที่สั้นลง


11

คุณสามารถรับส่วนต่างสำหรับสะสมด้วย " git show stash@{0}" (หรือจำนวนที่เก็บคือดู "รายการ gash สะสม") มันง่ายที่จะแยกส่วนของ diff สำหรับไฟล์เดียว


2
ยังง่ายกว่าสำหรับจิตใจอย่างฉัน: ใช้git show stashเพื่อแสดงที่ซ่อนสูงสุด (โดยปกติแล้วจะมีเพียงอันเดียวที่คุณมี) git diff head stashในทำนองเดียวกันคุณสามารถแสดงความแตกต่างระหว่างสาขาปัจจุบันของคุณและสะสมด้วย
Dizzley

5

แนวคิดที่ง่ายที่สุดที่จะเข้าใจแม้ว่าอาจจะไม่ดีที่สุดคือคุณมีสามไฟล์ที่เปลี่ยนแปลงและคุณต้องการซ่อนไฟล์หนึ่งไฟล์

หากคุณgit stashต้องการซ่อนทั้งหมดgit stash applyเพื่อนำพวกเขากลับมาอีกครั้งและจากนั้นgit checkout f.cในไฟล์ที่เป็นปัญหาเพื่อรีเซ็ตอย่างมีประสิทธิภาพ

เมื่อคุณต้องการคลายการเรียกใช้ไฟล์นั้นให้ทำgit reset --hardและเรียกใช้git stash applyอีกครั้งโดยใช้ประโยชน์จากข้อเท็จจริงที่git stash applyไม่ได้ลบส่วนต่างจากสแต็กสแต็ก


1

หากไฟล์ที่ถูกซ่อนจำเป็นต้องรวมกับเวอร์ชันปัจจุบันดังนั้นให้ใช้วิธีการก่อนหน้านี้โดยใช้ diff มิฉะนั้นคุณอาจใช้git popสำหรับการคลายพวกเขาgit add fileWantToKeepสำหรับการจัดเตรียมไฟล์ของคุณและทำgit stash save --keep-indexเพื่อเก็บทุกอย่างยกเว้นสิ่งที่อยู่บนเวที โปรดจำไว้ว่าความแตกต่างของวิธีนี้กับตัวก่อนหน้าคือ "pops" ไฟล์จากที่เก็บ คำตอบก่อนหน้าเก็บไว้git checkout stash@{0} -- <filename>เพื่อให้เป็นไปตามความต้องการของคุณ


0

ใช้สิ่งต่อไปนี้เพื่อนำการเปลี่ยนแปลงไปใช้กับไฟล์ในที่เก็บของต้นไม้การทำงานของคุณ

git diff stash^! -- <filename> | git apply

โดยทั่วไปจะดีกว่าการใช้git checkoutเพราะคุณจะไม่สูญเสียการเปลี่ยนแปลงใด ๆ ที่คุณทำกับไฟล์ตั้งแต่คุณสร้างที่เก็บ


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