สร้างคอมมิต Git เดียวอีกครั้ง


116

มีวิธีในการปรับฐานคอมมิตเดียวจากสาขาไปยังสาขาอื่นหรือไม่?

ฉันมีโครงสร้างสาขานี้:

-- -- -- -- -- (Master)
            \
              -- -- -- -- -- XX (Feature-branch)

สิ่งที่ฉันต้องการทำก็คือการตั้งค่าคอมมิตสุดท้ายของการกระทำครั้งสุดท้ายFeature-branchไปยังมาสเตอร์และการย้อนกลับFeature-branchหนึ่งคอมมิต

-- -- -- -- -- XX (Master)
            \
              -- -- -- -- -- (Feature-branch)

ฉันจะทำอย่างไร?


3
หากคุณสามารถตั้งค่าคอมมิชชั่นใหม่ได้กี่ครั้งแล้วทำไมคุณถึงถามเกี่ยวกับการรีเบตหนึ่งครั้ง? ถ้าฉันสามารถถามคำถามใน SO ได้ฉันจะถามว่าอะไรคือความแตกต่างระหว่างการรีเบต (การคอมมิตครั้งเดียว) และการเลือกเชอร์รี่
วัล

9
เพราะฉันไม่รู้ว่ามีการเก็บเชอร์รี่อยู่และฉันทำ "Faff about on branch", "Get request for fix on different branch", "fix it", "Commit to wrong branch", "D'OH!" เพียงพอที่จะถามคำถามนั้นมีประโยชน์
Kevin Meyer

คำตอบ:


116

คุณสามารถเลือก XX ให้เชี่ยวชาญได้

git checkout master
git cherry-pick <commit ID of XX>

และลบคอมมิตสุดท้ายออกจากฟีเจอร์แบรนช์ด้วยการรีเซ็ตคอมไพล์

git checkout Feature-branch
git reset --hard HEAD^

64
คำถามที่เรียกโดยเฉพาะว่า 'git rebase ... ' จะมีคำตอบที่ยอมรับได้อย่างไรมากกว่าการเลือกเชอร์รี่ซึ่งเป็นแนวคิดที่แตกต่างกันโดยสิ้นเชิงและบางครั้งก็ถือว่าไม่สะอาด
Bondax

1
ไม่แน่ใจว่าสิ่งนี้เกี่ยวข้องหรือไม่ แต่การคอมมิตที่ฉันต้องการจะ rebase มีไฟล์บางไฟล์ที่ถูกย้ายและcherry-pickทำให้ดูเหมือนว่าไฟล์เหล่านี้ถูกลบออกจากตำแหน่งเก่าและสร้างขึ้นที่ตำแหน่งใหม่ ฉันคิดว่า rebase จะดูแลเรื่องนี้ แต่ตอนนี้ฉันผลักดันต้นน้ำดังนั้นฉันจึงไม่สามารถทดสอบได้ ไม่ว่าในกรณีใดโปรดระวังหากคุณมีสถานการณ์ที่คล้ายคลึงกัน
waldyrious

หมายเหตุ: ในการผลักดันการเปลี่ยนแปลงFeature-branchต้นทางคุณจะต้องทำgit push -f origin Feature-branchเนื่องจากFeature-branchตอนนี้ถือว่าคุณเป็น 1 คอมมิตที่อยู่เบื้องหลังไฟล์origin/Feature-branch.
jojo

1
ความแตกต่างในทางปฏิบัติระหว่างโซลูชันนี้กับ CharlesBคืออะไร?
Lii

97
git rebase --onto master branch~1 branch 

ข้อความนี้ระบุว่า "rebase the range of commits ระหว่าง last-before-branch และ branch (นั่นคือ XX คอมมิต) ที่ปลายของสาขาหลัก"

หลังจากbranchย้ายเคล็ดลับการดำเนินการนี้XXแล้วคุณจึงต้องการตั้งค่ากลับด้วย

git checkout branch
git reset --hard branch@{1}^

ซึ่งระบุว่า "รีเซ็ตปลายสาขาเป็นคอมมิตก่อนสถานะก่อนหน้า"

ดังนั้นการเลือกเชอร์รี่จึงเป็นวิธีที่ง่ายกว่า ...


5
สิ่งนี้ดูเหมือนจะไม่ได้ผลสำหรับฉันฉันสูญเสียคอมมิตก่อน XX และสาขาได้รับการปรับฐานให้เชี่ยวชาญด้วยการคอมมิตเดียว แต่ฉันไม่เคยใช้มา--ontoก่อนดังนั้นฉันอาจทำอะไรผิดพลาด BTW OP กล่าวว่า rebase แต่ดูเหมือนว่าเขาต้องการเลือกเชอร์รี่
tewe

1
ข้อผิดพลาดของฉัน rebase จะย้ายสาขาไปที่มาสเตอร์ต้องรีเซ็ต
CharlesB

1
อะไรคือความแตกต่างในทางปฏิบัติระหว่างโซลูชันนี้กับหนึ่งโดย tewe ?
Lii

1
@Lii สิ่งเดียวที่ฉันเห็นคือมันใช้ 3 ขั้นตอนแทนที่จะเป็น 4
CharlesB

52

มันค่อนข้างง่ายที่จะทำจริง วิธีแก้ปัญหาคือทำ rebase แบบโต้ตอบและ "ทิ้ง" คอมมิตทั้งหมดที่คุณไม่ต้องการรวมไว้ใน rebase

git rebase -i <target_branch>target_branchสาขาที่คุณต้องการตั้งฐานใหม่อยู่ที่ไหน

จากนั้นคุณจะแก้ไขไฟล์ที่เปิดและคอมpickมิตที่คุณต้องการและdrop(หรือdสั้น ๆ ) คอมมิตทั้งหมดที่คุณไม่ต้องการนำมาด้วย


6
IMO เป็นทางออกที่ดีกว่ามากและตอบโจทย์ได้จริง
GabrielOshiro

นี่ควรเป็นวิธีการแก้ปัญหาที่ได้รับการยอมรับโดยพิจารณาจากความทั่วไปใช้งานง่ายและสั้น
Pablo Arias

1

@ ชาร์ลส์ตอบถูก อย่างไรก็ตามฉันลงเอยด้วยการใช้สิ่งนี้หลายครั้งที่สำคัญที่สุดคือ rebase config เฉพาะในโครงการ

  * a8f9182 (HEAD -> การผลิต) การกำหนดค่าการผลิต
  | * daa18b7 (ก่อน) การกำหนดค่าก่อนการผลิตจริง
  | /  
  | * d365f5f (โลคัล) คอนฟิกูเรชัน
  | /  
  * 27d2835 (dev) คุณสมบัติใหม่ที่น่าทึ่งที่จะช่วยโลก
* | 56d2467 (หลัก) ทันสมัยน่าเบื่อสำหรับโครงการ
| /

ที่ฉันสร้างคำสั่งใหม่สำหรับมัน:

$ cat ~ / bin / git-rebaseshot 
COMMIT = $ 1
DEST = $ {2: -Head}
git rebase $ {COMMIT} ^ $ {COMMIT} - จาก $ DEST

โดยปกติคุณต้องการเติมชื่อสาขาโดยอัตโนมัติสำหรับคำสั่งนั้นดังนั้นให้เพิ่มการจัดหาฟังก์ชันนี้ (เพิ่มเป็น. bashrc หรือ. profile):

_git_rebaseshot () 
{ 
    __gitcomp_nl "$ (__ git_refs)"
}

การเติมข้อความอัตโนมัติ git จะค้นหา

คุณสามารถใช้คำสั่งนี้ดังนี้:

# rebase config on prepro on actual HEAD
$ git rebaseshot prepro 
# rebase config on local onto dev
$ git rebaseshot local dev
# rebase production config on master
$ git rebaseshot pro master

เมื่อคุณแบ่งคุณสมบัติอย่างถูกต้องความเป็นไปได้จะไม่มีที่สิ้นสุด

* a8f9182 (HEAD -> postgres) การกำหนดค่า BBDD
* a8f9182 (ในเครื่อง) การกำหนดค่าภายในเครื่อง
* a8f9182 (debug) การกำหนดค่าระดับบันทึก
* a8f9182 (dev) คุณลักษณะใหม่
|

ฉันเดาว่านี่คือสิ่งที่คนชอบทำผ้าห่ม

คำสั่งนี้จะใช้ได้กับทุกสิ่งที่คุณระบุ:

$ git rebaseshot <Feature branch> master
$ git rebaseshot <commit of XX> master

// คุณสามารถเชื่อมโยงไปยังโครงการใด ๆ ที่เราสามารถเห็นการทำงานนี้ได้หรือไม่?
Nathan Basanese

ตามธรรมชาติแล้วสาขาที่มีให้สำหรับ rebaseshot จะไม่ถูกผูกมัดนอก repo ในพื้นที่ เพียงสร้างหลายสาขาที่ด้านบนของต้นแบบ (ระดับบันทึกการเชื่อมต่อฐานข้อมูลการกำหนดค่า) และใช้คำสั่งระหว่างกัน เป็นธรรมดาที่จะเห็นผล
albfan

// ฉันพบปัญหาบางอย่าง ฉันจะลองอีกครั้ง
Nathan Basanese

0

นี่เป็นอีกทางเลือกหนึ่ง:

  1. ตรวจสอบให้แน่ใจว่าคุณมีรีโมตพร้อมสำเนาของสาขาคุณลักษณะ
  2. ลบสาขาคุณลักษณะเฉพาะที่
  3. สร้างและชำระเงินสาขาใหม่ด้วยชื่อเดียวกับสาขาฟีเจอร์เก่าที่คุณเพิ่งลบออกจากสาขาหลัก
  4. เชอร์รี่เลือกหนึ่งคอมมิตจากสำเนาระยะไกลของสาขาคุณลักษณะที่คุณต้องการ

คำสั่งมีลักษณะดังนี้:

git checkout Feature-branch
git push -u origin HEAD
git checkout master
git branch -D Feature-branch
git checkout -b Feature-branch
git cherry-pick HASH-OF-XX

ไม่ใช่คำสั่ง rebase แต่เป็น rebase ด้วยจิตวิญญาณ

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