Git stash:“ ไม่สามารถใช้กับแผนผังการทำงานที่สกปรกได้โปรดจัดขั้นตอนการเปลี่ยนแปลงของคุณ”


133

ฉันพยายามใช้การเปลี่ยนแปลงที่เก็บไว้ก่อนหน้านี้git stash popและได้รับข้อความ:

Cannot apply to a dirty working tree, please stage your changes

มีข้อเสนอแนะเกี่ยวกับวิธีจัดการกับสิ่งนั้นหรือไม่?

คำตอบ:


198

เมื่อฉันต้องใช้การเปลี่ยนแปลงที่ซ่อนอยู่กับสำเนาที่ใช้งานได้สกปรกเช่นเปิดชุดการเปลี่ยนแปลงมากกว่าหนึ่งรายการจากที่เก็บฉันใช้สิ่งต่อไปนี้:

$ git stash show -p | git apply -3 && git stash drop

โดยทั่วไปแล้ว

  1. สร้างแพทช์
  2. ไปป์ที่ไปยังคำสั่งใช้
  3. หากมีข้อขัดแย้งใด ๆ พวกเขาจะต้องได้รับการแก้ไขผ่านการผสาน 3 ทาง
  4. ถ้าใช้ (หรือรวม) สำเร็จจะดรอปไอเท็มซ่อนที่เพิ่งใช้ ...

ฉันสงสัยว่าทำไมไม่มี-fตัวเลือก (บังคับ) git stash popที่ควรมีพฤติกรรมเหมือนซับในข้างต้น

ในระหว่างนี้คุณอาจต้องการเพิ่ม one-liner นี้เป็น git alias:

$ git config --global --replace-all alias.unstash \
   '!git stash show -p | git apply -3 && git stash drop'
$ git unstash

ขอบคุณ @SamHasler ที่ชี้ให้เห็น-3พารามิเตอร์ที่ช่วยให้แก้ไขข้อขัดแย้งได้โดยตรงผ่านการผสาน 3 ทาง


คือgit stash show -p | git applyแตกต่างกว่าgit stash apply?
Factor Mystic

1
Jo Factor git stash applyจะไม่ใช้การเปลี่ยนแปลงที่ซ่อนไว้หากคุณมีสำเนาที่ใช้งานได้สกปรก ดังนั้นคุณจะเห็นgit stash show -p | git applyว่ามีการบังคับใช้การเก็บซ่อนบางประเภท
muhqu

1
ไม่ช่วย แต่ช่วย: คอมไพล์รีเซ็ต HEAD และยกเลิกการเปลี่ยนแปลงหลังจากนั้น
Roger Alien

4
ฉันได้รับ "ข้อผิดพลาด: โปรแกรมแก้ไขล้มเหลว ... โปรแกรมแก้ไขใช้ไม่ได้" สำหรับไฟล์ใดไฟล์หนึ่ง ฉันหวังว่ามันจะทำให้เกิดความขัดแย้งในการผสาน
Aleksandr Dubinsky

2
วิธีนี้ใช้ไม่ได้ผลสำหรับฉันมันล้มเหลวerror: <file> does not match indexสำหรับทุกไฟล์ที่แก้ไข อย่างไรก็ตามวิธีอื่นใช้ได้ผล
silvenon

59

ฉันทำในลักษณะนี้:

git add -A
git stash apply

แล้ว (ไม่บังคับ):

git reset

2
+1! วิธีนี้ง่ายกว่าโซลูชันอื่น ๆ ที่เกี่ยวข้องกับการสร้างแพตช์หรือการแก้ไขข้อตกลงและจะช่วยให้การเปลี่ยนแปลงในพื้นที่ของคุณแยกออกจากการเปลี่ยนแปลงที่เก็บข้อมูลที่นำไปใช้อย่างปลอดภัยจนกว่าคุณจะแน่ใจว่าการเปลี่ยนแปลงนั้นรวมเข้าด้วยกันอย่างถูกต้อง
peterflynn

ฉันได้รับข้อผิดพลาด "... มีอยู่แล้วไม่มีการชำระเงิน ... ไม่สามารถกู้คืนไฟล์ที่ไม่ได้ติดตามจากที่ซ่อน"
Aleksandr Dubinsky

3
ฉันใช้git add -uซึ่งก็เหมือนกับ-Aว่ามันไม่ได้เพิ่มไฟล์ที่ไม่ได้ติดตาม
Brad Cupit

9

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

ตัวอย่างเช่นสมมติว่าคุณต้องการใช้ stash @ {0} กับต้นไม้สกปรก:

  1. ส่งออกที่เก็บ @ {0} เป็นแพตช์:

    git stash show -p stash @ {0}> Stash0.patch

  2. ใช้การเปลี่ยนแปลงด้วยตนเอง:

    git ใช้ Stash0.patch

หากขั้นตอนที่สองล้มเหลวคุณจะต้องแก้ไขไฟล์ Stash0.patch เพื่อแก้ไขข้อผิดพลาดจากนั้นลองใช้ git อีกครั้ง


สิ่งนี้ใช้งานได้จริงและใช้งานได้สำหรับกรณีที่ฉันทำการ refactoring บน dir (ลบออกและสร้าง symlink พร้อมชื่อ) Git ไม่สามารถบอกได้ว่าการเปลี่ยนแปลงสำเนาการทำงานของฉันคืออะไร
yclian

1
สิ่งนี้ได้ผลดี ฉันไม่สามารถใช้ที่ซ่อนได้แม้ว่าฉันจะค่อนข้างมั่นใจว่าต้นไม้ทำงานของฉันสะอาด
ชิกิ

ใช่ฉันต้องลบบรรทัดเกี่ยวกับไฟล์ไบนารี
Dorian

8

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

$ git stash save "คำอธิบายการเปลี่ยนแปลงปัจจุบัน"
$ git stash pop stash @ {1}

การดำเนินการนี้จะซ่อนการเปลี่ยนแปลงปัจจุบันจากนั้นเปิดที่ซ่อนที่สองจากกองซ้อน


5
แต่ผู้ชายคนนี้ต้องการใช้สองขีด!
Elazar Leibovich

@Elazar คุณกำลังอ่านคำถาม OP เพียงต้องการใช้ที่ซ่อนก่อนหน้านี้ หากคุณถูกต้องที่จะเก็บการเปลี่ยนแปลงในปัจจุบันวิธีแก้ปัญหาสามารถทำซ้ำได้: ป๊อปคอมมิตทำซ้ำ
William Pursell

ฉันคิดว่าเขาต้องการให้ทั้งสองคนไม่ธรรมดา แต่แล้วอีกครั้งเขาสามารถกระทำได้สองครั้งและรวมกันเป็นหนึ่งการกระทำ
Elazar Leibovich

ฉันได้รับข้อผิดพลาด "... มีอยู่แล้วไม่สามารถชำระเงินได้ ... ไม่สามารถกู้คืนไฟล์ที่ไม่ได้ติดตามจากที่ซ่อน"
Aleksandr Dubinsky

6

โซลูชันของ Mathias นั้นใกล้เคียงที่สุดกับ git stash pop --force (และจริงๆแล้ว c'mon Git devs มารับตัวเลือกนี้กันเถอะ!)

อย่างไรก็ตามหากคุณต้องการทำสิ่งเดียวกันโดยใช้คำสั่ง git เท่านั้นคุณสามารถ:

  1. คอมมิต -a -m "Fixme"
  2. git ซ่อนป๊อป
  3. คอมมิต -a --amend
  4. git รีเซ็ต HEAD ~

กล่าวอีกนัยหนึ่งคือทำการคอมมิต (ซึ่งเราจะไม่ผลักดัน) ของการเปลี่ยนแปลงปัจจุบันของคุณ เมื่อพื้นที่ทำงานของคุณสะอาดแล้วให้เปิดที่เก็บของคุณ ตอนนี้ยอมรับการเปลี่ยนแปลงที่ซ่อนเป็นการแก้ไขการกระทำก่อนหน้าของคุณ เมื่อทำเสร็จแล้วตอนนี้คุณมีการเปลี่ยนแปลงทั้งสองชุดรวมกันในคอมมิตเดียว ("Fixme"); เพียงแค่ตั้งค่าใหม่ (- ไม่ต้องใช้ - เพื่อให้ไม่มีอะไรสูญหายจริง ๆ ) การชำระเงินของคุณเป็น "หนึ่งก่อนที่จะกระทำ" และตอนนี้คุณมีการเปลี่ยนแปลงทั้งสองชุดโดยไม่มีข้อผูกมัดใด ๆ

** แก้ไข * *

ฉันเพิ่งรู้ว่ามันง่ายกว่านั้นจริงๆ คุณสามารถข้ามขั้นตอนที่ 3 ได้ทั้งหมดดังนั้น ...

  1. คอมมิต -a -m "Fixme"
  2. git ซ่อนป๊อป
  3. git รีเซ็ต HEAD ~

(ยอมรับการเปลี่ยนแปลงปัจจุบันปิดการเปลี่ยนแปลงที่เก็บไว้รีเซ็ตการกระทำนั้นก่อนเพื่อรับการเปลี่ยนแปลงทั้งสองชุดรวมกันในสถานะที่ไม่ได้กำหนดไว้)


4

คำตอบเหล่านี้ไม่ได้ผลจริงหากคุณพบว่าตัวเองอยู่ในสถานการณ์นี้เหมือนที่ฉันทำในวันนี้ ไม่ว่าgit reset --hardฉันจะทำกี่ครั้งแต่ก็ทำให้ฉันไม่มีที่ไหนเลย คำตอบของฉัน (ไม่เป็นทางการ แต่อย่างใดคือ):

  1. พิจารณาการใช้แฮชของที่ซ่อน git reflog --all
  2. รวมแฮชนั้นกับสาขาที่คุณสนใจ

1
ขอบคุณมากครับ ฉันรู้สึกผิดหวังกับการที่ Git ทำตัวแปลก ๆ ใน repo ในพื้นที่ของฉันในตอนนี้ปัญหาเดียวกับที่คุณอธิบาย
yclian

4

ฉันยังพบว่าโซลูชันของ Mathias Leppichทำงานได้ดีดังนั้นฉันจึงเพิ่มนามแฝงสำหรับมันใน. gitconfig ส่วนกลางของฉัน

[alias]
        apply-stash-to-dirty-working-tree = !git stash show -p | git apply && git stash drop

ตอนนี้ฉันสามารถพิมพ์ได้

git apply-stash-to-dirty-working-tree

ซึ่งใช้งานได้ดีสำหรับฉัน

(ระยะทางของคุณอาจแตกต่างกันไปตามชื่อนามแฝงแบบยาวนี้ แต่ฉันชอบความฟุ่มเฟื่อยเมื่อมันมาพร้อมกับการทุบเสร็จ)


3

คุณสามารถนำที่ซ่อนไปใช้กับต้นไม้ที่ "สกปรก" ได้โดยทำการgit addเปลี่ยนแปลงใด ๆ ที่คุณได้ทำไว้ดังนั้นจึงเป็นการทำความสะอาดต้นไม้ จากนั้นคุณสามารถgit stash popและใช้การเปลี่ยนแปลงที่ซ่อนอยู่ได้ไม่มีปัญหา


2

คุณมีไฟล์ที่ถูกแก้ไข แต่ไม่ได้คอมมิต ทั้ง:

git reset --hard HEAD (to bring everything back to HEAD)

หรือหากคุณต้องการบันทึกการเปลี่ยนแปลงของคุณ:

git checkout -b new_branch
git add ...
git commit
git checkout -b old_branch
git stash pop

1
@MikeCooper - ฉันคิดว่าเขาแค่ตั้งใจเพิ่มสิ่งที่คุณต้องการเพิ่มก่อนที่จะกระทำ
sscirrus

0

ฉันมีปัญหาเดียวกัน แต่คอมไพล์ไม่มีไฟล์ที่เปลี่ยนแปลง ปรากฎว่าฉันมีไฟล์ index.lock ที่วางอยู่รอบ ๆ การลบจะช่วยแก้ปัญหาได้


0

ฉันไม่สามารถทำงานส่วนใหญ่ได้ ด้วยเหตุผลบางอย่างมันมักจะคิดว่าฉันมีการเปลี่ยนแปลงในไฟล์ ฉันใช้ที่ซ่อนไม่ได้แพตช์ใช้ไม่ได้checkoutและreset --hardล้มเหลว อะไรในที่สุดได้รับการทำงานประหยัดซ่อนเป็นสาขาที่มีgit stash branch tempbranchnameแล้วทำผสานสาขาปกติและgit checkout master git merge tempbranchnameจากhttp://git-scm.com/book/en/Git-Tools-Stashing :

หากคุณต้องการวิธีที่ง่ายกว่าในการทดสอบการเปลี่ยนแปลงที่ซ่อนไว้อีกครั้งคุณสามารถเรียกใช้ git stash branch ซึ่งจะสร้างสาขาใหม่ให้คุณตรวจสอบการคอมมิตที่คุณทำเมื่อคุณเก็บงานของคุณนำงานของคุณไปใช้ใหม่ที่นั่นจากนั้นจึงปล่อย ซ่อนหากใช้สำเร็จ

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