Git: สร้างสาขาจากการเปลี่ยนแปลงแบบไม่มีสเตจ / ไม่มีข้อผูกมัดบนมาสเตอร์


991

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

สิ่งนี้เกิดขึ้นกับฉันเสมอและฉันไม่รู้ว่าจะเปลี่ยนไปใช้สาขาอื่นได้อย่างไรและรับการเปลี่ยนแปลงที่ไม่ได้รับการแจ้งเตือนเหล่านี้ทั้งหมดจากฉันโดยปล่อยให้สาขาหลักสะอาด ฉันควรgit stash && git stash branch new_branchจะทำอย่างนั้น แต่นี่คือสิ่งที่ฉันได้รับ:

~/test $ git status
# On branch master
nothing to commit (working directory clean)

~/test $ echo "hello!" > testing 

~/test $ git status
# On branch master
# 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:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git stash
Saved working directory and index state WIP on master: 4402b8c testing
HEAD is now at 4402b8c testing

~/test $ git status
# On branch master
nothing to commit (working directory clean)

~/test $ git stash branch new_branch
Switched to a new branch 'new_branch'
# On branch new_branch
# 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:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (db1b9a3391a82d86c9fdd26dab095ba9b820e35b)

~/test $ git s
# On branch new_branch
# 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:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git checkout master
M   testing
Switched to branch 'master'

~/test $ git status
# On branch master
# 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:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

คุณรู้หรือไม่ว่ามีวิธีใดในการบรรลุเป้าหมายนี้?


1
แม้ว่าจะมีวิธีแก้ไขปัญหาของคุณที่ง่ายกว่า แต่คุณสามารถระบุในสิ่งที่ผลลัพธ์ที่คุณได้รับแตกต่างจากสิ่งที่คุณต้องการได้หรือไม่?
Gauthier

2
ด้วยการทำด้านบนหรือคำตอบที่ด้านล่างการเปลี่ยนแปลงที่ไม่ได้รับการแก้ไขจะเกิดขึ้นกับทั้งต้นแบบและสาขาใหม่ ฉันต้องการพวกเขาเฉพาะในสาขาใหม่ดังนั้นฉันสามารถชำระเงินหลักและทำงานในสิ่งอื่นโดยไม่ต้องมีการเปลี่ยนแปลงเหล่านี้ลอยไปรอบ ๆ
knoopx

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

คำตอบ:


1207

ไม่จำเป็นต้องซ่อน

git checkout -b new_branch_name

ไม่ได้สัมผัสการเปลี่ยนแปลงในท้องถิ่นของคุณ มันเพิ่งสร้างสาขาจาก HEAD ปัจจุบันและตั้ง HEAD ที่นั่น ดังนั้นฉันเดาว่านั่นคือสิ่งที่คุณต้องการ

--- แก้ไขเพื่ออธิบายผลการชำระเงินหลัก ---

คุณสับสนเพราะcheckout masterไม่ทิ้งการเปลี่ยนแปลงหรือไม่?

เนื่องจากการเปลี่ยนแปลงเป็นแบบโลคอลเท่านั้นจึงไม่ต้องการให้คุณสูญเสียมันไปง่ายเกินไป เมื่อเปลี่ยนสาขา git จะไม่เขียนทับการเปลี่ยนแปลงในท้องถิ่นของคุณ ผลลัพธ์ของคุณcheckout masterคือ:

M   testing

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

-fถ้าคุณอยากที่จะยกเลิกการเปลี่ยนแปลงท้องถิ่นคุณมีการบังคับให้ชำระเงินด้วย

git checkout master -f

เนื่องจากการเปลี่ยนแปลงของคุณไม่เคยเกิดขึ้นคุณจะสูญเสียมันไป

ลองกลับไปที่สาขาของคุณส่งการเปลี่ยนแปลงจากนั้นเช็คเอาต์หลักอีกครั้ง

git checkout new_branch
git commit -a -m"edited"
git checkout master
git status

คุณควรได้รับMข้อความหลังจากเช็คเอาต์ครั้งแรก แต่ไม่หลังจากนั้นอีกต่อไปcheckout masterและgit statusไม่ควรแสดงไฟล์ที่แก้ไข

--- แก้ไขเพื่อล้างความสับสนเกี่ยวกับไดเรกทอรีทำงาน (ไฟล์ในเครื่อง) ---

ในการตอบความคิดเห็นแรกของคุณการเปลี่ยนแปลงในท้องถิ่นเป็นเพียง ... ดีท้องถิ่น Git ไม่ได้บันทึกไว้โดยอัตโนมัติคุณต้องบอกให้บันทึกในภายหลัง หากคุณทำการเปลี่ยนแปลงและไม่กระทำหรือซ่อนไว้อย่างชัดเจน git จะไม่ทำการเปลี่ยนแปลง หากคุณเปลี่ยน HEAD ( checkout master) การเปลี่ยนแปลงในระบบจะไม่ถูกเขียนทับตั้งแต่ยังไม่ได้บันทึก


32
สิ่งที่สับสนที่นี่คือ man page ของ git นั้นระบุว่าgit checkout“ อัพเดตไฟล์ในแผนผังการทำงานเพื่อให้ตรงกับเวอร์ชันในดัชนีหรือแผนผังที่ระบุ” ซึ่งถือว่าการเปลี่ยนแปลงของคุณในระบบไฟล์ของคุณจะหายไปในภายหลัง โดยไม่มีโอกาสกลับคืนมา แม้ว่าคุณจะบอกว่าพวกเขาจะไม่ทำ แต่ก็ยังทำให้เกิดความรู้สึกที่ไม่ดี ฉันไม่ไว้วางใจนี้ที่ทุกคน เอกสารไม่ดีจริง ๆ หรือพฤติกรรมเริ่มต้นของคอมไพล์เป็นอันตรายจริงๆ เราไม่ควรเชื่อใจฮิวริสติก“ อัตโนมัติ” บางอย่างเพื่อตรวจสอบว่าในกรณีนี้คุณไม่ต้องการสูญเสียการเปลี่ยนแปลง
Evi1M4chine

16
หากคุณกำลังตรวจสอบการกระทำที่จะเขียนทับการเปลี่ยนแปลงในท้องถิ่นของคุณ (หากประวัติระหว่างการกระทำในปัจจุบันและการกระทำที่เป็นเป้าหมายสัมผัสกับไฟล์ที่แก้ไขในพื้นที่ของคุณ) git ปฏิเสธ เพียงแค่checkoutไม่ขัดแย้งกับการเปลี่ยนแปลงในท้องถิ่นของคุณการชำระเงินจะใช้งานได้และทำให้การเปลี่ยนแปลงในระบบอยู่คนเดียว ฉันเข้าใจความรู้สึกไม่ดี แต่แมนเพจควรจะพูดว่า "อัปเดตไฟล์ที่ไม่มีการแก้ไขในแผนผังการทำงาน" Git ไม่ได้ทำให้ง่ายต่อการสูญเสียการเปลี่ยนแปลงในท้องถิ่น git checkoutอนุญาตให้เปลี่ยนแปลงในท้องถิ่นของคุณเพียงอย่างเดียวหรือปฏิเสธหากมีข้อขัดแย้ง
Gauthier

1
ดีฉันจะเช็คเอ้าท์ไปยังสาขาอื่นโดยไม่นำการเปลี่ยนแปลงในพื้นที่มาได้อย่างไร
アレックス

5
git checkout <other_branch> -f@ Alex คุณจะสูญเสียการเปลี่ยนแปลงในพื้นที่โดยไม่มีการเตือน
Gauthier

2
@ Evi1M4chine อันแรก เอกสารเป็นที่เลวร้ายจริงๆ
Qwertie

62

ลอง:

git stash
git checkout -b new-branch
git stash apply

6
สิ่งนี้แตกต่างหรือไม่กับการทำ 'git checkout -b new-branch' ด้วยตัวเอง?
Adrian Mouat

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

6
หรือแทนสองขั้นตอนสุดท้าย: git stash branch สาขาใหม่
rethab

1
ไม่จำเป็นต้องใช้ git stash อีกต่อไป
kory

เมื่อคุณมีสาขาที่มีอยู่แล้วที่คุณต้องการที่จะใส่ทุกสิ่งของคุณสะสมทำให้รู้สึกสำหรับฉัน: (ในที่สุดก็เรียก git - ทั้งหมด; เพื่อให้ได้สาขาระยะไกลในแหล่งกำเนิด) git สะสม; git checkout <existing-branch>; git stash นำไปใช้;
Paolof76

24

สองสิ่งที่คุณสามารถทำได้:

git checkout -b sillyname
git commit -am "silly message"
git checkout - 

หรือ

git stash -u
git branch sillyname stash@{0}

( git checkout -<- เส้นประเป็นทางลัดสำหรับสาขาก่อนหน้านี้ที่คุณเปิดอยู่)

( git stash -u<- -uหมายถึงว่าใช้การเปลี่ยนแปลงแบบไม่จัดเตรียม)


7

หากคุณกำลังใช้งานไคลเอนต์ GitHub Windows (อย่างที่ฉันเป็น) และคุณอยู่ในสถานการณ์ที่มีการเปลี่ยนแปลงที่ไม่มีข้อผูกมัดที่คุณต้องการย้ายไปยังสาขาใหม่คุณสามารถเพียง "สร้างสาขาใหม่" ผ่านไคลเอนต์ GitHub มันจะเปลี่ยนเป็นสาขาที่สร้างขึ้นใหม่และรักษาการเปลี่ยนแปลงของคุณ

ป้อนคำอธิบายรูปภาพที่นี่


ที่หยุดการเปลี่ยนแปลงก่อนที่จะสร้างสาขาใหม่ดังนั้นจึงไม่เก็บไว้ (เวอร์ชัน 223 บน Mac OS)
Fernando Gallego

2

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

git checkout -b branch_name

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

ส่งการเปลี่ยนแปลงของคุณไปยังสาขาใหม่

git commit -m "First commit"

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

git push --set-upstream origin feature/feature/NEWBRANCH

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

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

git checkout master -f

การทำเช่นนี้จะเป็นการยกเลิกการเปลี่ยนแปลงในท้องถิ่นที่ไม่ได้รับการยอมรับในการชำระเงิน


คำตอบนี้แตกต่างจากคำตอบที่ยอมรับได้อย่างไร
Kometen

แม้ว่าจะมีการทับซ้อนกับคำตอบที่ยอมรับ แต่ก็มีคำแนะนำทีละขั้นตอนอย่างง่ายและยังรวมถึงการดำเนินการที่จำเป็นในการผลักดันสาขาใหม่จากระยะไกล ง่ายชัดเจนและมีประโยชน์
Kjartan

คำตอบนี้ชัดเจนและช่วยฉันมาก
Vadim

0

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

ป้อนคำอธิบายรูปภาพที่นี่

เช่นเดียวกับถ้าคุณเพียงสลับสาขาด้วย

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