วิธีการสควอชกระทำในคอมไพล์หลังจากที่พวกเขาถูกผลัก?


550

นี่เป็นคำอธิบายที่ดีสำหรับการบีบหลายคอมมิต:

http://git-scm.com/book/en/Git-Branching-Rebasing

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

แก้ไข:เมื่อฉันgit rebase -i origin/master~4 masterเก็บไว้เป็นคนแรกpickตั้งอีกสามเป็นsquashแล้วออก (ผ่าน cx cc ใน emacs) ฉันได้รับ:

$ git rebase -i origin/master~4 master
# Not currently on any branch.
nothing to commit (working directory clean)

Could not apply 2f40e2c... Revert "issue 4427: bpf device permission change option added"
$ git rebase -i origin/master~4 master
Interactive rebase already started

โดยที่ 2f40 เป็นการpickกระทำ และตอนนี้ไม่มีการกระทำที่ 4 git logปรากฏใน ฉันคาดว่าโปรแกรมแก้ไขของฉันจะเริ่มต้นใหม่เพื่อให้ฉันสามารถป้อนข้อความยืนยัน ผมทำอะไรผิดหรือเปล่า?

คำตอบ:


779

สควอชกระทำในท้องถิ่นด้วย

git rebase -i origin/master~4 master

แล้วบังคับให้กดด้วย

git push origin +master

ความแตกต่างระหว่าง--forceและ+

จากเอกสารของgit push:

โปรดทราบว่า--forceนำไปใช้กับการอ้างอิงทั้งหมดที่ถูกผลักดังนั้นการใช้มันกับการpush.defaultตั้งค่าไปยังmatchingหรือที่มีหลายสถานที่การผลักดันที่กำหนดด้วยremote.*.pushอาจเขียนทับอ้างอิงอื่นนอกเหนือจากสาขาปัจจุบัน (รวมถึงการอ้างอิงในท้องถิ่น ในการบังคับให้กดไปที่สาขาเดียวให้ใช้+ ด้านหน้าของ refspec เพื่อดัน (เช่นgit push origin +masterเพื่อบังคับให้กดไปที่masterสาขา)


30
คุณสามารถgit push --force origin master
Daenyth

7
Daenyth : ใช่ แต่ฉันชอบไวยากรณ์นี้มากกว่าเพราะสั้นกว่า
Alan Haggai Alavi

86
และแน่นอนว่าถ้าคนอื่นอาจดึงข้อมูลจากพื้นที่เก็บข้อมูลระยะไกลคุณอาจไม่ต้องการทำสิ่งนี้ - คำตอบในกรณีนี้คือ "คุณไม่ทำ"
Cascabel

10
นอกจากนี้ผมคิดว่า OP จะว่าการคัดลอกคำสั่งgit rebase -i origin/masterและที่จริงอยากจะทราบวิธีการ rebase git rebase -i origin/master~20 masterกระทำไกลกลับไปกว่านั้นเช่น
Cascabel

6
gstackoverflow :+บังคับเฉพาะ refspec ที่นำหน้าด้วย --forceจะบังคับ refspecs ทั้งหมดที่ถูกผลัก โปรดดูคำตอบที่อัพเดต
Alan Haggai Alavi

120

ในสาขาฉันสามารถทำสิ่งนี้ได้ (สำหรับ 4 ครั้งล่าสุด)

git checkout my_branch
git reset --soft HEAD~4
git commit
git push --force origin my_branch

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

3
ตัน มันสามารถมากกว่า 4 ได้อย่างไร? คุณสามารถทำอย่างละเอียด?
jakob-r

ที่ฉันไม่แน่ใจ แต่ก็มีบางอย่างที่เกี่ยวข้องกับการพยายามบีบความมุ่งมั่นที่ผลักดันไปแล้ว ดูเหมือนว่าคนอื่น ๆ มีประสบการณ์คล้ายกันที่นี่ - stackoverflow.com/questions/5189560/…
cchamberlain

4
ฉันจะยอมรับสิ่งนี้เป็นคำตอบที่คาดหวัง สะอาดกว่าตอบรับได้ดีกว่า
vikramvi

4
นี่เป็นคำตอบที่ชัดเจนและเป็นที่ยอมรับมากที่สุดใน 4 ขั้นตอน
Ameya Salagre

45

ความแตกต่างเล็กน้อยกับคำตอบที่ยอมรับได้ แต่ฉันประสบความยากลำบากในการบีบอัดและในที่สุดก็รับมัน

$ git rebase -i HEAD~4
  • ที่หน้าจอโต้ตอบที่เปิดขึ้นแทนที่เลือกด้วยสควอช ที่ด้านบนสำหรับการกระทำทั้งหมดที่คุณต้องการสควอช
  • บันทึกและปิดตัวแก้ไขผ่าน esc --> :wq

กดไปที่รีโมทโดยใช้:

$ git push origin branch-name --force

2
สั้นและมีประสิทธิภาพประณีต:
terwxqian

22

ปัญหามากมายสามารถหลีกเลี่ยงได้โดยการสร้างเพียงbranchเพื่อทำงานและไม่ทำงานในmaster:

git checkout -b mybranch

ผลงานต่อไปนี้ของคอมมิทที่ส่งไปremoteแล้ว & การรวมกันของคอมมิทที่ส่งremote/ localกระทำเท่านั้น:

# example merging 4 commits

git checkout mybranch
git rebase -i mybranch~4 mybranch

# at the interactive screen
# choose fixup for commit: 2 / 3 / 4

git push -u origin +mybranch

ฉันยังมีบันทึกคำขอแบบดึงซึ่งอาจเป็นประโยชน์


17

git rebase -i master

คุณจะได้รับการแก้ไข vm เปิดและ msgs บางอย่างเช่นนี้

Pick 2994283490 commit msg1
f 7994283490 commit msg2
f 4654283490 commit msg3
f 5694283490 commit msg4
#Some message 
#
#some more

ที่นี่ฉันได้เปลี่ยนการเลือกสำหรับทั้งหมดอื่น ๆ ยอมรับเป็น "f" (แทนการแก้ไข)

git push -f origin feature/feature-branch-name-xyz

การดำเนินการนี้จะแก้ไขการคอมมิททั้งหมดเป็นคอมมิทเดียวและจะลบคอมมิททั้งหมด ฉันทำสิ่งนี้และมันช่วยฉัน


3

เมื่อคุณทำงานกับ Gitlab หรือ Github คุณสามารถทำงานได้ด้วยวิธีนี้ คุณสควอชกระทำของคุณด้วยวิธีใดวิธีหนึ่งดังกล่าวข้างต้น สิ่งที่ฉันชอบคือ:

git rebase -i HEAD~4
or
git rebase -i origin/master

เลือกสควอชหรือแก้ไขสำหรับการกระทำของคุณ ณ จุดนี้คุณจะตรวจสอบสถานะ git และข้อความอาจเป็น:

    On branch ABC-1916-remote
    Your branch and 'origin/ABC-1916' have diverged,
    and have 1 and 7 different commits each, respectively.
      (use "git pull" to merge the remote branch into yours)

และคุณสามารถล่อลวงให้ดึงมันได้ อย่าทำอย่างนั้นหรือคุณจะอยู่ในสถานการณ์เดียวกับเมื่อก่อน

แทนที่จะไปที่ต้นกำเนิดของคุณด้วย:

git push origin +ABC-1916-remote:ABC-1916

เครื่องหมาย + อนุญาตให้บังคับให้กดไปที่สาขาเดียวเท่านั้น


ไม่มีอะไรผิดปกติในการดึงโดยเฉพาะอย่างยิ่งถ้าคุณมีข้อขัดแย้งพวกเขาสามารถแก้ไขได้ง่ายกว่าถ้าคุณบังคับให้กด
Ray_Poly

2

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

git rebase -i HEAD~2
    [ pick     older-commit  ]
    [ squash   newest-commit ]
git push --force

โดยค่าเริ่มต้นสิ่งนี้จะรวมข้อความการส่งข้อความคอมมิทล่าสุดเป็นคอมเม้นท์คอมมิชชันเก่า


2

1) git rebase -i HEAD~4

เพื่อทำอย่างละเอียด: มันทำงานในสาขาปัจจุบัน; HEAD ~ 4 หมายถึงการบีบการกระทำสี่ครั้งล่าสุด; โหมดโต้ตอบ (-i)

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

เอาท์พุท: rebased เรียบร้อยแล้วและการปรับปรุง refs / หัว / สาขาชื่อ

3) git push origin refs/heads/branch-name --force

เอาท์พุท:

remote:
remote: To create a merge request for branch-name, visit:
remote: http://xxx/sc/server/merge_requests/new?merge_request%5Bsource_branch%5D=sss
remote:To ip:sc/server.git
 + 84b4b60...5045693 branch-name -> branch-name (forced update)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.