วิธีการกู้คืนการเปลี่ยนแปลงที่ไม่มีข้อผูกมัดที่เก็บไว้


694

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

นอกจากนี้ฉันได้ทำการเปลี่ยนแปลงบางอย่างที่ด้านบนของไฟล์รหัสที่ถูกจัดเก็บตั้งแต่

มีโอกาสใดบ้างที่ฉันสามารถเรียกการเปลี่ยนแปลงที่เก็บไว้ในสาขาใหม่ได้ถ้าเป็นไปได้?


7
คุณลองใช้ 'stash pop' แล้วหรือยัง
เบิร์ต

ไม่จริงฉันใหม่กับคอมไพล์ เนื่องจากฉันไม่ได้ตระหนักถึงคำสั่งทั้งหมดอย่างเต็มที่ฉันจึงไม่ได้ลองทำอะไรอีก! ฉันไม่ต้องการสูญเสียการเปลี่ยนแปลงเหล่านั้น
Aswathy P Krishnan

33
หากคุณไม่ต้องการสูญเสียการเปลี่ยนแปลงที่ทำไว้ให้ลองใช้ 'git stash Apply' วิธีนี้จะใช้การเปลี่ยนแปลงที่เก็บไว้กับสาขาปัจจุบันของคุณในขณะที่ยังคงเก็บสะสม หากทุกอย่างเรียบร้อยหลังจากใช้ที่ซ่อนคุณสามารถวางที่ซ่อนโดยใช้ 'git stash drop'
robert

2
@robert ขอบคุณสำหรับคำตอบง่ายๆเมื่อเทียบกับคำตอบที่ยอมรับยาก (สำหรับมือใหม่)
Saheel Godhane

คำตอบ:


1186

คำตอบที่ง่ายสำหรับคำถามง่าย ๆ คือ git stash apply

git stash applyเพียงตรวจสอบสาขาที่คุณต้องการการเปลี่ยนแปลงของคุณบนแล้ว จากนั้นใช้git diffเพื่อดูผลลัพธ์

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

ฉันมักจะแนะนำให้ใช้มากกว่าgit stash apply git stash popความแตกต่างคือapplyออกจากที่ซ่อนรอบเพื่อให้ง่ายต่อการลองapplyใหม่หรือเพื่อดู ฯลฯ หากpopสามารถดึงที่ซ่อนได้ออกมามันจะทันทีด้วยdropและถ้าคุณรู้ทันทีว่าคุณต้องการแยกมัน อื่น (ในสาขาที่แตกต่าง) หรือกับ--indexหรือบางอย่างนั่นไม่ใช่เรื่องง่าย หากคุณapply, คุณdropจะได้รับเลือกเมื่อมีการ

มันคือทั้งหมดเล็กน้อยทางเดียวหรืออื่น ๆ แม้ว่าและสำหรับมือใหม่ที่จะคอมไพล์ก็ควรจะเกี่ยวกับที่เหมือนกัน (และคุณสามารถข้ามส่วนที่เหลือทั้งหมดนี้ได้!)


ถ้าคุณทำสิ่งที่ก้าวหน้ากว่าหรือซับซ้อนกว่าล่ะ?

มี "วิธีการใช้ git stash" อย่างน้อยสามหรือสี่วิธีเหมือนเดิม ข้างต้นสำหรับ "วิธีที่ 1", "วิธีที่ง่าย":

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

    นี่เป็นกรณีง่ายที่อธิบายไว้ข้างต้น เรียกใช้git stash save(หรือธรรมดาgit stashสิ่งเดียวกัน) ตรวจสอบสาขาอื่น ๆ git stash applyและการใช้งาน นี่เป็นการรวมคอมไพล์ในการเปลี่ยนแปลงก่อนหน้าของคุณโดยใช้กลไกการผสานที่มีประสิทธิภาพมากกว่าของคอมไพล์ ตรวจสอบผลลัพธ์อย่างระมัดระวัง (พร้อมgit diff) เพื่อดูว่าคุณชอบหรือไม่และใช้วิธีนี้git stash dropเพื่อลดการสะสม คุณทำเสร็จแล้ว!

  2. คุณเริ่มการเปลี่ยนแปลงบางอย่างและซ่อนไว้ จากนั้นคุณเปลี่ยนเป็นสาขาอื่นและเริ่มการเปลี่ยนแปลงมากขึ้นโดยลืมว่าคุณมีสาขาที่ถูกซ่อนอยู่

    ตอนนี้คุณต้องการที่จะเก็บหรือย้ายการเปลี่ยนแปลงเหล่านี้และเก็บสะสมของคุณด้วย

    ในความเป็นจริงคุณสามารถgit stash saveอีกครั้งในขณะที่git stashทำให้ "กอง" ของการเปลี่ยนแปลง ถ้าคุณว่าคุณมีสอง stashes หนึ่งเรียกว่าเพียงแค่stash-but คุณยังสามารถเขียนและอื่นหนึ่งสะกดstash@{0} stash@{1}ใช้git stash list(ตลอดเวลา) เพื่อดูพวกเขาทั้งหมด ใหม่ล่าสุดจะเป็นตัวเลขต่ำสุดเสมอ เมื่อคุณgit stash dropมันลดลงล่าสุดและหนึ่งที่ถูกstash@{1}ย้ายไปด้านบนของสแต็ค หากคุณมีมากขึ้นคนที่stash@{2}กลายเป็นstash@{1}และอื่น ๆ

    คุณสามารถapplyแล้วdropซ่อนที่เฉพาะเจาะจงเกินไป: git stash apply stash@{2}และอื่น ๆ วางที่ซ่อนเฉพาะจัดลำดับใหม่เฉพาะหมายเลขที่สูงกว่าเท่านั้น อีกครั้งหนึ่งที่ไม่มีตัวเลขก็เช่นstash@{0}กัน

    หากคุณสะสมจำนวนมากของการหยุดชะงักมันจะยุ่งเหยิงพอสมควร (เป็นที่ซ่อนที่ฉันต้องการstash@{7}หรือstash@{4}ใช่หรือไม่รอฉันเพิ่งผลักไปอีกอันตอนนี้พวกเขาอายุ 8 และ 5?) ผมเองชอบที่จะถ่ายโอนการเปลี่ยนแปลงเหล่านี้เป็นสาขาใหม่เพราะสาขามีชื่อและความหมายอย่างมากสำหรับผมยิ่งไปกว่าcleanup-attempt-in-December stash@{12}( git stashคำสั่งใช้ข้อความบันทึกทางเลือกและสิ่งเหล่านั้นสามารถช่วยได้ แต่อย่างใดปัญหาทั้งหมดของฉันหยุดเพียงตั้งชื่อWIP on branch)

  3. (พิเศษขั้นสูง) คุณเคยใช้git stash save -pหรืออย่างระมัดระวังgit add-ed และ / หรือgit rmบิตเฉพาะ -ed git stash saveของรหัสของคุณก่อนที่จะใช้ คุณมีหนึ่งเวอร์ชันในดัชนี / พื้นที่จัดเตรียมและอีกหนึ่งเวอร์ชัน (ต่างกัน) ในแผนผังการทำงาน คุณต้องการที่จะรักษาทั้งหมดนี้ ดังนั้นตอนนี้คุณใช้git stash apply --indexและบางครั้งก็ล้มเหลวด้วย:

    Conflicts in index.  Try without --index.
    
  4. คุณกำลังใช้git stash save --keep-indexเพื่อทดสอบ "สิ่งที่จะเกิดขึ้น" อันนี้อยู่นอกเหนือขอบเขตของคำตอบนี้ ดูStackOverflow คำตอบอื่นแทน

สำหรับกรณีที่ซับซ้อนฉันขอแนะนำให้เริ่มต้นในไดเรกทอรีทำงาน "สะอาด" ก่อนโดยยอมรับการเปลี่ยนแปลงใด ๆ ที่คุณมีตอนนี้ (ในสาขาใหม่หากคุณต้องการ) ด้วยวิธีการที่ "ที่ไหนสักแห่ง" ที่คุณใช้พวกเขาไม่มีอะไรในนั้นและคุณเพียงแค่จะพยายามเปลี่ยนแปลงการ stashed:

git status               # see if there's anything you need to commit
                         # uh oh, there is - let's put it on a new temp branch
git checkout -b temp     # create new temp branch to save stuff
git add ...              # add (and/or remove) stuff as needed
git commit               # save first set of changes

ตอนนี้คุณอยู่ในจุดเริ่มต้น "สะอาด" หรืออาจจะเป็นเช่นนี้มากขึ้น:

git status               # see if there's anything you need to commit
                         # status says "nothing to commit"
git checkout -b temp     # optional: create new branch for "apply"
git stash apply          # apply stashed changes; see below about --index

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


เมื่อใดก็ตามที่คุณมีที่ซ่อนคุณสามารถใช้git stash show -pเพื่อดูรุ่นที่เรียบง่ายของสิ่งที่อยู่ในที่เก็บของ (อันนี้ง่ายรุ่นลักษณะเฉพาะที่มีการเปลี่ยนแปลง "ต้นงานสุดท้าย" ไม่ดัชนีบันทึกการเปลี่ยนแปลงที่--indexเรียกคืนแยกต่างหาก.) คำสั่งgit stash applyโดยไม่--indexเพียงแค่พยายามที่จะทำให้ผู้ที่เดียวกันการเปลี่ยนแปลงในการทำงานไดเรกทอรีของคุณตอนนี้

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

git stash apply stash      # apply top of stash stack
git stash apply stash@{1}  # and mix in next stash stack entry too

คุณสามารถเลือกคำสั่ง "นำไปใช้" ที่นี่โดยเลือกการซ่อนเฉพาะเพื่อนำไปใช้ในลำดับเฉพาะ อย่างไรก็ตามโปรดทราบว่าแต่ละครั้งที่คุณทำ "git merge" โดยทั่วไปและตามที่เอกสารการรวมเตือนว่า:

การใช้งานคอมไพล์ผสานกับการเปลี่ยนแปลงที่ไม่มีข้อผูกมัดนั้นไม่ได้รับการสนับสนุน: ในขณะที่เป็นไปได้มันอาจทำให้คุณอยู่ในสถานะที่ยากที่จะถอยออกมาในกรณีที่เกิดข้อขัดแย้ง

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


สิ่งที่เกี่ยวกับกรณีที่เป็นไปได้ที่เลวร้ายที่สุด?

สมมติว่าคุณกำลังทำ Git Stuff ขั้นสูงมากมายและคุณได้ทำที่ซ่อนและต้องการgit stash apply --indexแต่ไม่สามารถใช้ที่เก็บที่บันทึกไว้ได้อีกต่อไป--indexเพราะสาขาแยกจากกันมากเกินไปนับตั้งแต่เวลาที่คุณบันทึกไว้

นี่คือสิ่งที่git stash branchมีไว้เพื่อ

ถ้าคุณ:

  1. ตรวจสอบความมุ่งมั่นที่แน่นอนที่คุณอยู่เมื่อคุณทำต้นฉบับstashแล้ว
  2. สร้างสาขาใหม่และในที่สุด
  3. git stash apply --index

ความพยายามในการสร้างการเปลี่ยนแปลงใหม่จะทำงานได้อย่างแน่นอน นี่คือสิ่งที่ไม่ (และจากนั้นจะลดการสะสมเนื่องจากมันถูกนำไปใช้อย่างประสบความสำเร็จ)git stash branch newbranch


บางคำสุดท้ายเกี่ยวกับ--index(มันคืออะไรห่า?)

สิ่งที่--indexอธิบายได้ง่าย แต่มีความซับซ้อนอยู่ภายใน:

  • เมื่อคุณมีการเปลี่ยนแปลงคุณต้องgit add(หรือ "เวที") ก่อนที่จะเข้าcommitร่วม
  • ดังนั้นเมื่อคุณรันgit stashคุณอาจแก้ไขทั้งไฟล์fooและzorgแต่แสดงเพียงไฟล์เดียว
  • ดังนั้นเมื่อคุณขอให้ซ่อนตัวมันอาจจะดีถ้ามันgit addเป็นaddสิ่งต่าง ๆ และไม่ใช่ สิ่งที่ไม่ได้git addเพิ่มเข้ามา นั่นคือถ้าคุณaddแก้ไขfooแต่ไม่zorgกลับมาก่อนที่คุณจะทำstashเช่นนั้นอาจเป็นเรื่องดีถ้ามีการตั้งค่าเดียวกัน ควรจัดฉากอะไรอีก สิ่งที่ถูกแก้ไข แต่ไม่จัดฉากควรแก้ไขอีกครั้ง แต่ไม่จัดฉาก

การ--indexตั้งค่าสถานะเพื่อapplyพยายามตั้งค่าสิ่งนี้ ถ้าต้นไม้ทำงานของคุณสะอาดนี่ก็แค่ใช้งานได้ ถ้าต้นไม้ของคุณมีสิ่งที่added แล้วคุณสามารถดูว่าอาจมีปัญหาบางอย่างที่นี่ หากคุณออกไป--indexการapplyดำเนินการจะไม่พยายามรักษาการตั้งค่าทั้งหมด / ไม่จัดฉาก แต่มันก็จะเรียกคอมไพล์ของเครื่องจักรที่ผสานการใช้งานต้นไม้กระทำใน"ถุงซ่อน" หากคุณไม่สนใจเกี่ยวกับการรักษาฉาก / unstaged ทิ้งออก--indexทำให้มันง่ายมากสำหรับgit stash applyการทำสิ่งที่ตน


2
ฉันไม่เข้าใจความคิดเห็นของคุณ คุณหมายถึง: คุณวิ่งgit stash pop? หรือคุณหมายถึง: คุณแก้ไขไฟล์บางไฟล์ แต่ยังไม่ได้ทำงานgit stashอีกเลย? หรือคุณหมายถึงอย่างอื่นอย่างสิ้นเชิง?
torek

1
ใช่. หมายเหตุในการแก้ไข (ยาว) ของฉันฉันขอแนะนำให้ยอมรับสิ่งที่คุณมีตอนนี้ก่อนapplyทำการสะสม คุณไม่ต้องทำสิ่งนี้ แต่มันทำให้ง่ายขึ้นมากสำหรับคุณที่จะดู คุณสามารถใช้rebase -iสควอชหลายคอมมิชชันหรือเชอร์รี่เลือกการเปลี่ยนแปลงเฉพาะหรืออะไรก็ได้ในภายหลัง
torek

1
ใช่: git stash apply --index(จำทั้งสองขีดกลาง) หากคุณออกไป--indexไม่มีเรื่องใหญ่ จุดเดียวของ--indexคือการทำให้การตั้งค่าฉาก / unstaged (คุณอาจไม่มีการตั้งค่าพิเศษในตอนแรก) จากนั้นgit statusฯลฯ และเพิ่ม / กระทำตามที่ต้องการเป็นต้นเมื่อ (และเมื่อใด) คุณเสร็จสิ้นการซ่อนใช้git stash dropเพื่อทิ้งมัน
torek

1
ตราบใดที่คุณเก็บ (อย่าทำdropหรือpopเก็บสะสม) คุณจะต้องมีรหัสที่ถูกจัดเก็บดั้งเดิมไว้อย่างปลอดภัยบนคอมมิชชันเนื่องจากการสะสมเป็นคอมมิชชัน ! หากคุณต้องการที่จะได้รับมันกลับว่า แต่ในสาขาการใช้งานgit stash branch(ดูส่วนที่ดังกล่าวข้างต้นหรือหนังสือ Pro Gitในคำตอบของ Shunya ) จากนั้นคุณสามารถgit checkoutที่สาขาหรือgit cherry-pickได้กระทำการปิดสาขาที่ ฯลฯ
torek

2
@ChuckWolber: การตั้งชื่อของ Git มีความต้องการมากมาย (เราสามารถกำหนดความหมายต่าง ๆ ให้กับคำว่า "remote", "tracking" และ "branch" ได้อย่างไร? เป็นที่น่าสังเกตว่าคุณสามารถใช้ที่เก็บของกับสิ่งที่ไม่เกี่ยวข้องกับที่เก็บของจริงได้
torek

57
git stash pop

จะได้รับทุกอย่างกลับเข้าที่

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

git checkout -b newbranch
git stash pop

ขอบคุณสำหรับความช่วยเหลือ ฉันจะรับการเปลี่ยนแปลงเหล่านั้นเป็นสาขาใหม่ได้หรือไม่? ตอนนี้ฉันอยู่ในการพัฒนาสาขา
Aswathy P Krishnan

3
git stash newbranch branch จะสร้างสาขาใหม่ที่มีการเปลี่ยนแปลงที่ stashed
เบิร์ต

3
@robert: git stash branch newbranchจะทำอย่างนั้นจริง ๆ ; แต่โปรดระวังว่าจะสร้างสาขาใหม่โดยที่ผู้ปกครองตั้งค่าเป็นการส่งมอบHEADในเวลาที่stashทำ กล่าวอีกนัยหนึ่งก็คือเมื่อคุณกลับมาหลังจากเซสชันแฮ็คที่ยาวนานหรืออะไรก็ตามจ้องมองระเบียบและตัดสินใจว่า "ฉันควรใส่มันไว้ในสาขาแทนที่จะ
หยุดนิ่ง

ฉันได้แก้ไขคำถามของฉัน ฉันต้องการรับการเปลี่ยนแปลงเหล่านั้นในสาขาใหม่ถ้าเป็นไปได้
Aswathy P Krishnan

1
บางครั้งคุณก็ต้องการคำตอบที่ TLDR :)
sachinruk

24

ในการทำให้ง่ายนี้คุณมีสองตัวเลือกในการสะสมที่เก็บของคุณใหม่:

  1. git stash pop - กู้คืนกลับสู่สถานะที่บันทึกไว้ แต่จะลบที่เก็บออกจากที่เก็บข้อมูลชั่วคราว
  2. git stash apply - กู้คืนกลับสู่สถานะที่บันทึกไว้และออกจากรายการที่เก็บไว้เพื่อนำมาใช้ซ้ำในภายหลัง

คุณสามารถอ่านรายละเอียดเพิ่มเติมเกี่ยวกับstit gitในบทความนี้


19

ในการตรวจสอบเนื้อหาที่ซ่อนของคุณ: -

gash stash list

ใช้หมายเลขที่เก็บเฉพาะจากรายการที่เก็บ: -

git stash ใช้ stash @ {2}

หรือสำหรับการใช้ที่ซ่อนแรก: -

คอมไพล์สะสมป๊อป

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


2

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

git stash list (ดูที่ซ่อนของคุณทั้งหมด)

git stash list

ใช้ git stash (เฉพาะหมายเลขที่คุณต้องการจากรายการที่ซ่อนของคุณ)

แบบนี้:

git stash apply 1

0

คุณสามารถซ่อนการเปลี่ยนแปลงที่ไม่มีข้อผูกมัดได้โดยใช้ "git stash" จากนั้นเช็คเอาต์ไปยังสาขาใหม่โดยใช้ "git checkout -b" จากนั้นใช้คอมมิชชันที่เก็บไว้ "git stash Apply"

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