ชำระเงินที่สาขาอื่นเมื่อมีการเปลี่ยนแปลงที่ไม่มีข้อผูกมัดในสาขาปัจจุบัน


353

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

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

กฎนี่คืออะไร มันมีความสำคัญไม่ว่าการเปลี่ยนแปลงจะถูกจัดฉากหรือไม่เป็นฉาก? การแบกรับการเปลี่ยนแปลงไปสู่สาขาอื่นไม่สมเหตุสมผลกับฉันทำไมบางครั้งคอมไพล์จึงอนุญาต นั่นคือมีประโยชน์ในบางสถานการณ์หรือไม่

คำตอบ:


355

บันทึกเบื้องต้น

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

git checkout branch2

บางครั้ง Git พูดว่า "โอเคคุณอยู่ใน branch2 แล้ว!" บางครั้ง Git พูดว่า "ฉันทำไม่ได้ฉันจะสูญเสียการเปลี่ยนแปลงบางส่วน"

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

Sidebar: git stash saveเป็นไวยากรณ์เก่า git stash pushถูกนำมาใช้ใน Git เวอร์ชัน 2.13 เพื่อแก้ไขปัญหาบางอย่างกับข้อโต้แย้งgit stashและอนุญาตตัวเลือกใหม่ ทั้งสองทำสิ่งเดียวกันเมื่อใช้ในวิธีพื้นฐาน

คุณสามารถหยุดอ่านที่นี่ถ้าคุณชอบ!

หาก Git ไม่ยอมให้คุณเปลี่ยนคุณมีวิธีแก้ไข: ใช้git stashหรือgit commit; หรือหากการเปลี่ยนแปลงของคุณไม่สำคัญที่จะสร้างใหม่ให้ใช้git checkout -fเพื่อบังคับ คำตอบนี้เกี่ยวกับเมื่อ Git จะให้คุณgit checkout branch2แม้ว่าคุณจะเริ่มทำการเปลี่ยนแปลงบางอย่าง ทำไมบางครั้งมันทำงานและไม่ใช่เวลาอื่น

กฎที่นี่เรียบง่ายในทางเดียวและซับซ้อน / ยากที่จะอธิบายในอีก:

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

นั่นคือ - และโปรดทราบว่านี่ยังง่าย มีบางอย่างที่พิเศษที่ยากกรณีมุมกับฉากgit adds, s-และเช่นสมมติว่าคุณอยู่ในgit rm จะต้องทำเช่นนี้:branch1git checkout branch2

  • สำหรับทุกไฟล์ที่เป็นในbranch1และไม่ได้อยู่ในbranch2, 1ลบไฟล์ที่
  • สำหรับไฟล์ที่ทุกคนเป็นในbranch2และไม่ได้ในการbranch1สร้างแฟ้มที่ (ที่มีเนื้อหาเหมาะสม)
  • สำหรับทุกไฟล์ที่อยู่ในทั้งสองสาขาหากเวอร์ชันbranch2ต่างกันให้อัพเดตเวอร์ชันแผนผังการทำงาน

แต่ละขั้นตอนเหล่านี้อาจขัดขวางบางสิ่งในต้นไม้ทำงานของคุณ:

  • การลบไฟล์นั้น "ปลอดภัย" หากรุ่นในแผนผังต้นไม้เหมือนกันกับเวอร์ชันที่branch1กำหนด เป็น "ไม่ปลอดภัย" หากคุณทำการเปลี่ยนแปลง
  • การสร้างไฟล์ในแบบที่ปรากฏbranch2คือ "ปลอดภัย" หากไม่มีอยู่ในตอนนี้ 2 เป็น "ไม่ปลอดภัย" ถ้ามีอยู่ตอนนี้ แต่มีเนื้อหา "ผิด"
  • และแน่นอนการเปลี่ยนรุ่นการทำงานต้นไม้ของไฟล์ที่มีรุ่นที่แตกต่างกันคือ "ปลอดภัย" branch1หากรุ่นทำงานต้นไม้มีความมุ่งมั่นแล้ว

การสร้างสาขาใหม่ ( git checkout -b newbranch) ถือเป็น "ปลอดภัย" เสมอ : ไม่มีไฟล์ใดที่จะถูกเพิ่มลบหรือแก้ไขในแผนผังงานซึ่งเป็นส่วนหนึ่งของกระบวนการนี้และดัชนี / พื้นที่จัดเตรียมก็ไม่ถูกแตะต้อง (Caveat: ปลอดภัยเมื่อสร้างสาขาใหม่โดยไม่เปลี่ยนจุดเริ่มต้นของสาขาใหม่ แต่ถ้าคุณเพิ่มอาร์กิวเมนต์อื่นเช่นgit checkout -b newbranch different-start-pointอาจต้องเปลี่ยนสิ่งต่าง ๆ เพื่อย้ายไปdifferent-start-pointGit จะใช้กฎความปลอดภัยการชำระเงินตามปกติ .)


1สิ่งนี้ต้องการให้เรากำหนดความหมายของไฟล์ที่จะอยู่ในสาขาซึ่งจะต้องกำหนดคำว่าสาขาอย่างถูกต้อง (ดูเพิ่มเติมเราหมายถึงอะไรโดย "branch"? ) ที่นี่สิ่งที่ฉันหมายถึงจริงๆคือความมุ่งมั่นที่จะแก้ไขชื่อสาขา:ไฟล์ที่มีเส้นทางอยู่ในถ้าผลิตแฮช ไฟล์นั้นไม่อยู่ในหากคุณได้รับข้อความแสดงข้อผิดพลาดแทน การมีอยู่ของพา ธในดัชนีหรือแผนผังต้นไม้ของคุณนั้นไม่เกี่ยวข้องเมื่อตอบคำถามนี้โดยเฉพาะ ดังนั้นความลับที่นี่คือการตรวจสอบผลลัพธ์ของในแต่ละP branch1git rev-parse branch1:Pbranch1Pgit rev-parsebranch-name:path. สิ่งนี้อาจล้มเหลวเนื่องจากไฟล์ "ใน" ไม่เกินหนึ่งสาขาหรือให้รหัสแฮชสองรายการแก่เรา หากแฮช ID ทั้งสองเหมือนกันไฟล์จะเหมือนกันในทั้งสองสาขา ไม่จำเป็นต้องมีการเปลี่ยนแปลง หากรหัสแฮชต่างกันไฟล์จะแตกต่างกันในสองสาขาและจะต้องเปลี่ยนเป็นสลับสาขา

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

2มันอาจถูกพิจารณาว่า "เรียงลำดับจากที่ปลอดภัย" ถ้ามันมีอยู่แล้วใน "เนื้อหาที่ถูกต้อง" ดังนั้น Git จึงไม่จำเป็นต้องสร้างมันขึ้นมาเลย ฉันจำได้ว่า Git บางรุ่นอนุญาตอย่างน้อย แต่การทดสอบในตอนนี้แสดงว่าถือว่าไม่ปลอดภัยใน Git 1.8.5.4 อาร์กิวเมนต์เดียวกันนี้จะนำไปใช้กับไฟล์ที่ถูกแก้ไขซึ่งมีการปรับให้ตรงกับสาขาที่ต้องเปลี่ยนไป อีกครั้ง 1.8.5.4 เพิ่งพูดว่า "จะถูกเขียนทับ" ดูจุดสิ้นสุดของบันทึกทางเทคนิคเช่นกัน: หน่วยความจำของฉันอาจมีข้อผิดพลาดเนื่องจากฉันไม่คิดว่ากฎแบบอ่านทรีมีการเปลี่ยนแปลงตั้งแต่ฉันเริ่มใช้ Git ในรุ่น 1.5.something


มันมีความสำคัญไม่ว่าการเปลี่ยนแปลงจะถูกจัดฉากหรือไม่เป็นฉาก?

ใช่ในบางวิธี โดยเฉพาะอย่างยิ่งคุณสามารถจัดลำดับการเปลี่ยนแปลงจากนั้น "ยกเลิกการแก้ไข" ไฟล์แผนผังต้นไม้ นี่คือไฟล์ในสองสาขาซึ่งแตกต่างกันในbranch1และbranch2:

$ git show branch1:inboth
this file is in both branches
$ git show branch2:inboth
this file is in both branches
but it has more stuff in branch2 now
$ git checkout branch1
Switched to branch 'branch1'
$ echo 'but it has more stuff in branch2 now' >> inboth

ณ จุดนี้แฟ้มต้นไม้ทำงานinbothตรงกับหนึ่งในแม้ว่าเราจะอยู่บนbranch2 branch1การเปลี่ยนแปลงนี้ไม่ได้จัดเตรียมไว้สำหรับคอมมิชชันซึ่งเป็นสิ่งที่git status --shortแสดงให้เห็นที่นี่:

$ git status --short
 M inboth

space-then-M หมายถึง "แก้ไข แต่ไม่จัดเตรียม" (หรือมากกว่านั้นอย่างแม่นยำสำเนาแผนผังการทำงานแตกต่างจากสำเนาตามขั้นตอน / ดัชนี)

$ git checkout branch2
error: Your local changes ...

branch2ตกลงตอนนี้ขอเวทีสำเนาการทำงานต้นไม้ซึ่งเรารู้อยู่แล้วว่ายังตรงกับสำเนาใน

$ git add inboth
$ git status --short
M  inboth
$ git checkout branch2
Switched to branch 'branch2'

ที่นี่ทั้งแบบฉากและการทำงานที่ตรงกับสิ่งที่อยู่ในbranch2ดังนั้นการชำระเงินได้รับอนุญาต

ลองอีกขั้นตอน:

$ git checkout branch1
Switched to branch 'branch1'
$ cat inboth
this file is in both branches

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

มาขั้นที่สามของไฟล์ที่แตกต่างจากการคัดลอกสาขาจากนั้นตั้งค่าสำเนาการทำงานให้ตรงกับรุ่นสาขาปัจจุบัน:

$ echo 'staged version different from all' > inboth
$ git add inboth
$ git show branch1:inboth > inboth
$ git status --short
MM inboth

ทั้งสองMที่นี่หมายถึง: ไฟล์ฉากแตกต่างจากHEADไฟล์และไฟล์ต้นไม้ทำงานแตกต่างจากไฟล์ฉาก เวอร์ชันต้นไม้ทำงานไม่ตรงกับรุ่นbranch1(aka HEAD):

$ git diff HEAD
$

แต่git checkoutจะไม่อนุญาตให้ชำระเงิน:

$ git checkout branch2
error: Your local changes ...

มาตั้งbranch2เวอร์ชั่นกันดีกว่า:

$ git show branch2:inboth > inboth
$ git status --short
MM inboth
$ git diff HEAD
diff --git a/inboth b/inboth
index ecb07f7..aee20fb 100644
--- a/inboth
+++ b/inboth
@@ -1 +1,2 @@
 this file is in both branches
+but it has more stuff in branch2 now
$ git diff branch2 -- inboth
$ git checkout branch2
error: Your local changes ...

แม้ว่าสำเนาการทำงานปัจจุบันจะตรงกับที่อยู่ในbranch2ไฟล์ staged จะไม่ทำเช่นนั้นการgit checkoutคัดลอกนั้นจะสูญหายและการคัดลอกgit checkoutจะถูกปฏิเสธ

หมายเหตุด้านเทคนิค - เฉพาะสำหรับ :-) ที่อยากรู้อยากเห็นอย่างบ้าคลั่ง

กลไกการดำเนินงานพื้นฐานสำหรับทั้งหมดนี้คือ Git ของดัชนี ดัชนีเรียกว่า "พื้นที่การแสดงละคร" คือที่ที่คุณสร้างต่อไปกระทำมันเริ่มออกมาตรงกับปัจจุบันกระทำคือสิ่งที่คุณได้ตรวจสอบออกในขณะนี้และจากนั้นทุกครั้งที่คุณgit addไฟล์คุณแทนที่รุ่นดัชนี กับสิ่งที่คุณมีในต้นไม้ทำงานของคุณ

จำไว้ว่าต้นไม้ทำงานเป็นที่ที่คุณทำงานกับไฟล์ของคุณ ที่นี่พวกเขามีรูปแบบปกติของพวกเขามากกว่ารูปแบบพิเศษที่มีประโยชน์เฉพาะกับ Git บางอย่างเช่นที่พวกเขาทำในการกระทำและในดัชนี ดังนั้นคุณแยกไฟล์จากการคอมมิชชันผ่านดัชนีและจากนั้นไปยังแผนผังต้นไม้ หลังจากเปลี่ยนคุณgit addไปยังดัชนี ในความเป็นจริงแล้วมีสามที่สำหรับแต่ละไฟล์: การกระทำปัจจุบัน, ดัชนี, และแผนผังต้นไม้

เมื่อคุณใช้git checkout branch2งานสิ่งที่ Git ทำภายใต้ฝาปิดคือการเปรียบเทียบทิปการกระทำของbranch2สิ่งที่อยู่ในการกระทำปัจจุบันและดัชนีตอนนี้ ไฟล์ใด ๆ ที่ตรงกับที่มีอยู่ตอนนี้ Git สามารถทิ้งไว้คนเดียว มันไม่ถูกแตะต้องเลย ไฟล์ใด ๆ ที่เหมือนกันทั้งสองกระทำ , Git สามารถยังปล่อยให้อยู่คนเดียวและเหล่านี้เป็นคนที่ช่วยให้คุณสามารถสลับสาขา

Git ส่วนใหญ่รวมถึงการคอมมิชชัน - สับเปลี่ยนนั้นค่อนข้างเร็วเนื่องจากดัชนีนี้ สิ่งที่เป็นจริงในดัชนีไม่ได้แต่ละไฟล์ตัวเอง แต่แต่ละไฟล์ของกัญชา สำเนาของไฟล์นั้นจะถูกเก็บไว้เป็นสิ่งที่ Git เรียกว่าวัตถุหยดในพื้นที่เก็บข้อมูล วิธีนี้คล้ายกับวิธีการจัดเก็บไฟล์ในคอมมิทเช่นกัน: คอมมิทไม่ได้มีไฟล์จริง ๆพวกมันแค่นำ Git ไปที่ ID แฮชของแต่ละไฟล์ ดังนั้น Git จึงสามารถเปรียบเทียบ hash IDs ซึ่งปัจจุบันเป็นสตริงที่มีความยาว 160 บิตเพื่อตัดสินใจว่า commits XและYมีไฟล์เดียวกันหรือไม่ จากนั้นสามารถเปรียบเทียบรหัสแฮชเหล่านั้นกับรหัสแฮชในดัชนีได้เช่นกัน

นี่คือสิ่งที่นำไปสู่กรณีมุมคี่บอลทั้งหมดข้างบน เรามีกระทำXและYที่ทั้งสองมีไฟล์และเรามีรายการดัชนีสำหรับpath/to/name.txt path/to/name.txtบางทีทั้งสามแฮชตรงกัน บางทีพวกเขาสองคนจับคู่และหนึ่งไม่ตรง บางทีทั้งสามอาจแตกต่างกัน และเราอาจมีanother/file.txtเฉพาะในXหรือเฉพาะในYและอยู่หรือไม่อยู่ในดัชนีตอนนี้ แต่ละกรณีต่าง ๆ เหล่านี้จำเป็นต้องมีการพิจารณาแยกต่างหาก: Git จำเป็นต้องคัดลอกไฟล์ออกจากกระทำไปยังดัชนีหรือลบออกจากดัชนีเพื่อเปลี่ยนจากXเป็นYหรือไม่ ถ้าเป็นเช่นนั้นก็ยังต้องคัดลอกไฟล์ไปยังแผนผังต้นไม้หรือลบออกจากแผนผังต้นไม้ และถ้าว่าเป็นกรณีที่ดัชนีและการทำงานต้นไม้รุ่นที่มีการแข่งขันที่ดีกว่าอย่างน้อยหนึ่งในรุ่นที่มุ่งมั่น; มิฉะนั้น Git จะปิดบังข้อมูลบางอย่าง

(กฎที่สมบูรณ์สำหรับการทั้งหมดนี้ได้อธิบายไว้ในไม่ใช่git checkoutเอกสารที่คุณอาจคาดหวัง แต่เอกสารภายใต้หัวข้อ "สองต้นไม้ผสาน" .)git read-tree


3
... นอกจากนี้ยังมีการgit checkout -mรวม worktree ของคุณและการเปลี่ยนแปลงดัชนีในการชำระเงินใหม่
jthill

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

1
(1) คุณทำไม่ได้และ (2) ซอร์สโค้ด ปัญหาหลักคือ Git พัฒนาอย่างต่อเนื่อง ตัวอย่างเช่นตอนนี้มีแรงผลักดันอย่างมากในการเพิ่มหรือทิ้ง SHA-1 ด้วยหรือสนับสนุน SHA-256 ส่วนหนึ่งของ Git นี้ค่อนข้างเสถียรมาเป็นเวลานานแล้วและกลไกพื้นฐานนั้นตรงไปตรงมา: Git เปรียบเทียบดัชนีปัจจุบันกับปัจจุบันและเป้าหมายกระทำและตัดสินใจว่าจะเปลี่ยนแปลงไฟล์ใด (ถ้ามี) ตามเป้าหมายที่กระทำ จากนั้นทดสอบ "ความสะอาด" ของไฟล์แผนผังต้นไม้หากรายการดัชนีจะต้องแทนที่
2560

6
คำตอบสั้น ๆ : มีกฎกติกา แต่ผู้ใช้โดยเฉลี่ยมีความหวังในการทำความเข้าใจให้จดจำเพียงอย่างเดียวดังนั้นแทนที่จะอาศัยเครื่องมือที่จะทำงานอย่างชาญฉลาดคุณควรวางใจในระเบียบวินัยของการตรวจสอบเมื่อคุณเท่านั้น สาขาปัจจุบันมุ่งมั่นและสะอาด ฉันไม่เห็นว่าสิ่งนี้จะตอบคำถามว่าเมื่อใดจะเป็นประโยชน์ในการดำเนินการเปลี่ยนแปลงที่โดดเด่นในสาขาอื่น แต่ฉันอาจพลาดเพราะฉันพยายามเข้าใจมัน
Neutrino

2
@HawkeyeParker: คำตอบนี้ได้รับการแก้ไขมากมายและฉันไม่แน่ใจว่าจะปรับปรุงอะไรมาก แต่ฉันจะลองเพิ่มบางอย่างเกี่ยวกับความหมายของไฟล์ที่จะเป็น "ในสาขา" ในที่สุดสิ่งนี้จะสั่นคลอนเพราะความคิดของ "สาขา" ที่นี่ไม่ได้กำหนดไว้อย่างถูกต้องตั้งแต่แรก แต่นั่นก็เป็นอีกรายการหนึ่ง
torek

51

คุณมีสองทางเลือก: ซ่อนการเปลี่ยนแปลงของคุณ:

git stash

จากนั้นในภายหลังเพื่อให้พวกเขากลับมา:

git stash apply

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

คุณพูดว่ามันไม่เข้าท่า แต่คุณแค่ทำเพื่อที่คุณจะสามารถรวมพวกเขาได้ตามต้องการหลังจากลงมือทำ เห็นได้ชัดว่าทางเลือกอื่น ๆ ของคุณคือการส่งสำเนาของสาขาแล้วดึง ข้อสันนิษฐานคือคุณไม่ต้องการทำเช่นนั้น (ในกรณีที่ฉันงงว่าคุณไม่ต้องการสาขา) หรือคุณกลัวความขัดแย้ง


1
คำสั่งgit stash applyไม่ถูกต้องใช่ไหม นี่เอกสาร
Thomas8

1
เพียงแค่สิ่งที่ฉันกำลังมองหาเพื่อสลับไปยังสาขาต่าง ๆ เป็นการชั่วคราวเพื่อค้นหาบางสิ่งบางอย่างและกลับไปสู่สถานะเดิมของสาขาที่ฉันกำลังทำงานอยู่ ขอบคุณ Rob!
Naishta

1
ใช่นี่เป็นวิธีที่ถูกต้องในการทำเช่นนี้ ฉันซาบซึ้งรายละเอียดในคำตอบที่ยอมรับได้ แต่นั่นทำให้สิ่งที่ยากกว่าที่พวกเขาต้องการ
Michael Leonard

5
นอกจากนี้หากคุณไม่ต้องการเก็บที่ซ่อนไว้รอบ ๆ คุณสามารถใช้git stash popและจะลบการซ่อนออกจากรายการของคุณหากใช้สำเร็จ
Michael Leonard

1
ใช้งานได้ดีกว่าgit stash popเว้นแต่คุณตั้งใจจะเก็บบันทึกการหยุดทำงานในประวัติการซื้อคืนของคุณ
Damilola Olowookere

14

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

ตัวอย่าง:

$ echo 'hello world' > file.txt
$ git add file.txt
$ git commit -m "adding file.txt"

$ git checkout -b experiment
$ echo 'goodbye world' >> file.txt
$ git add file.txt
$ git commit -m "added text"
     # experiment now contains changes that master doesn't have
     # any future changes to this file will keep you from changing branches
     # until the changes are stashed or committed

$ echo "and we're back" >> file.txt  # making additional changes
$ git checkout master
error: Your local changes to the following files would be overwritten by checkout:
    file.txt
Please, commit your changes or stash them before you can switch branches.
Aborting

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

ตัวอย่าง:

$ git checkout -b experimental  # creates new branch 'experimental'
$ echo 'hello world' > file.txt
$ git add file.txt
$ git commit -m "added file.txt"

$ git checkout master # master does not have file.txt
$ echo 'goodbye world' > file.txt
$ git checkout experimental
error: The following untracked working tree files would be overwritten by checkout:
    file.txt
Please move or remove them before you can switch branches.
Aborting

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

$ echo 'experimental change' >> file.txt # change to existing tracked file
   # I want to save these, but not on master

$ git checkout -b experiment
M       file.txt
Switched to branch 'experiment'
$ git add file.txt
$ git commit -m "possible modification for file.txt"

จริงๆแล้วฉันยังไม่ค่อยเข้าใจเท่าไหร่ ในตัวอย่างแรกของคุณหลังจากที่คุณเพิ่ม "และเรากลับมา" มันบอกว่าการเปลี่ยนแปลงในระบบจะถูกเขียนทับการเปลี่ยนแปลงในท้องถิ่นคืออะไร? "และพวกเรากลับมาแล้ว"? ทำไม git ไม่เพียงแค่ทำการเปลี่ยนแปลงนี้ให้เป็น master ดังนั้นในต้นแบบไฟล์จะมี "hello world" และ "และเรากลับมาแล้ว"
Xufeng

ในตัวอย่างแรกต้นแบบมีความมุ่งมั่น 'สวัสดีโลก' เท่านั้น การทดสอบมีการทำ 'สวัสดีโลก \ n กู๊ดบายโลก เพื่อให้การเปลี่ยนแปลงสาขาเกิดขึ้นต้องมีการแก้ไข file.txt ปัญหาคือมีการเปลี่ยนแปลงที่ไม่มีข้อผูกมัด "hello world \ n Goodbye world \ n และเรากลับมาแล้ว"
Gordolio

1

คำตอบที่ถูกต้องคือ

git checkout -m origin/master

มันรวมการเปลี่ยนแปลงจากสาขาต้นแบบที่มีการเปลี่ยนแปลงในท้องถิ่นของคุณแม้ปราศจากข้อผูกมัด


0

ในกรณีที่คุณไม่ต้องการให้มีการเปลี่ยนแปลงใด git reset --hard

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

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