ฉันจะส่งการคอมมิตเฉพาะไปยังรีโมตได้อย่างไรและไม่คอมมิทก่อนหน้า?


827

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

เป็นไปได้ไหม


6
สำเนาซ้ำซ้อนของgit ที่
user151019

ดูเทคนิคที่ดีได้ที่นี่: stackoverflow.com/a/1789142/1579667
Benj

คำตอบ:


1087

ในการเพิ่มความมุ่งมั่นที่กำหนดคุณสามารถเขียน:

git push <remotename> <commit SHA>:<remotebranchname>

มี<remotebranchname>อยู่แล้วในรีโมท (หากไม่เป็นเช่นนั้นคุณสามารถใช้git push <remotename> <commit SHA>:refs/heads/<remotebranchname>สร้างอัตโนมัติได้)

หากคุณต้องการที่จะผลักดันการกระทำโดยไม่ต้องมุ่งมั่นก่อนหน้านี้คุณควรใช้git rebase -iเพื่อสั่งซื้อการกระทำ


66
git push <remotename> <commit SHA>:<remotebranchname>โรงงาน เคล็ดลับคือการรวมเข้าด้วยกันgit rebase -iเพื่อย้ายการคอมมิทที่คุณต้องการเป็นคอมมิชชันแรกและระบุว่า commit-sha
dminer

29
อีกเคล็ดลับที่ดีคือการทำให้แน่ใจว่าคุณคัดลอก SHA ของการกระทำที่คุณต้องการที่จะผลักดันหลังจากทำที่ rebase -i และไม่ก่อนที่จะเหมือนผมก็ไม่ได้ :)
estan

33
โปรดทราบว่าสิ่งนี้จะล้มเหลวหากสาขาระยะไกลยังไม่มีอยู่ git push <remotename> <commit SHA>:refs/heads/<new remote branch name>การสร้างสาขาที่สามารถทำได้ด้วย หลังจากนี้ให้กดตามคำตอบที่อธิบายไว้
Wes Oldenbeuving

32
ยกตัวอย่างเช่นการที่จะผลักดันทุกอย่าง git push origin HEAD~1:masterแต่การกระทำสุดท้ายที่มีชื่อมาตรฐานบางอย่าง
เสียงอึกทึกไร้สาระ

3
โปรดทราบด้วยว่าหากคุณได้ผลัก SHA ที่ใหม่กว่าไปยังสาขาระยะไกลนั้นแล้วคุณจะต้องบังคับให้กด SHA นี้ ใช้-fธง
Ian Vaughan

79

คำตอบอื่น ๆ กำลังขาดคำอธิบายการเรียงลำดับใหม่

git push <remotename> <commit SHA>:<remotebranchname>

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

git rebase -i HEAD~xxx

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

เพื่อสรุปฉันใช้

git rebase -i HEAD~<number of commits to SHA>
git push origin <post-rebase SHA>:master

เพื่อผลักดันการกระทำเดียวกับสาขาต้นแบบระยะไกลของฉัน

อ้างอิง:

  1. http://blog.dennisrobinson.name/push-only-one-commit-with-git/
  2. http://blog.dennisrobinson.name/reorder-commits-with-git/

ดูสิ่งนี้ด้วย:

  1. git: การทำซ้ำหลังการรีบูตท้องถิ่นตามด้วยการดึง
  2. git: การกด Single Commits, เรียงลำดับใหม่ด้วย rebase, Commits ที่ซ้ำกัน

3
ต้นกำเนิดบางอย่างอาจไม่อนุญาตสิ่งนี้ดูเหมือนว่า ตัวอย่างเช่นกับ GitLab ฉันเห็นว่า 'คุณไม่ได้รับอนุญาตให้บังคับใช้รหัสผลักดันไปยังสาขาที่ได้รับการป้องกันในโครงการนี้' ซึ่งแปลกนิดหน่อยตั้งแต่ฉันไม่คิดว่าฉันจะบังคับอะไรเลยแค่ทำตามปกติ ความคิดวิธีการทำโดยไม่ต้องบังคับใด ๆ ?
Ed Avis

1
@Ed Shoudl ไม่จำเป็นต้องมีการผลักดัน ดูเหมือนว่าคุณมีปัญหากับการตั้งค่าคอมไพล์โดยเฉพาะของคุณ บางทีคุณ rebased ผ่านหัวหน้าระยะไกลกระทำ? ฉันไม่รู้ว่าสาขาใดที่ได้รับความคุ้มครองดูเหมือนจะเป็นปัญหาสิทธิ์
ซามูเอล

1
ซามูเอล - นั่นน่าจะสมเหตุสมผล แต่การปฏิเสธ - คอมไพล์แสดงให้คุณเห็นเฉพาะการกระทำในท้องถิ่นซึ่งช้ากว่าหัวหน้าระยะไกลดังนั้นฉันไม่รู้ว่าฉันจะทำสิ่งนั้นได้อย่างไร
Ed Avis

1
ซามูเอล - แน่นอนตอนนี้ฉันสามารถผลักดันบางส่วนได้ดังนั้นฉันไม่รู้ว่าเกิดอะไรผิด แต่ต้องพยายามผลักดันการกระทำที่ไม่ได้มาจากหัวหน้าระยะไกลไม่ทางใดทางหนึ่ง
Ed Avis

1
@Ed คุณพูดว่า "git rebase -i แสดงให้คุณเห็นเฉพาะการกระทำในท้องถิ่นซึ่งช้ากว่าหัวหน้าระยะไกล" ฉันไม่คิดว่านี่เป็นเรื่องจริง ฉันทดสอบและสามารถรีบูตผ่าน HEAD ระยะไกลได้
ซามูเอล

25

ฉันขอแนะนำให้ใช้git rebase -i; ย้ายการคอมมิทที่คุณต้องการผลักไปด้านบนสุดของคอมมิทที่คุณทำ จากนั้นใช้git logเพื่อรับค่า SHA ของค่าคอมมิชชัน rebased ตรวจสอบและผลักดัน การรีบูตจะทำให้มั่นใจได้ว่าการกระทำอื่น ๆ ของคุณตอนนี้เป็นลูกของคุณที่ผลักดันดังนั้นการผลักอนาคตก็จะใช้ได้เช่นกัน


3
บางทีคุณอาจยกตัวอย่างการเคลื่อนไหวที่สมบูรณ์ git logขั้นตอนอีกหรือไม่
Drux

4
สมมติว่าคุณมีข้อผูกพันที่ค่อนข้างอิสระ 3 ข้อที่มีข้อความ "A", "B", "C" ที่ทำตามคำสั่งนั้นและคุณต้องการกด "B" 'git rebase -i' คุณควรจะได้รับและแก้ไขรายการทั้งสาม ย้าย B ขึ้นและบันทึก / ออก 'git log --pretty = oneline -n3' จะแสดงรายการ B, A, C พร้อมกับแฮชก่อนข้อความแต่ละข้อความด้วย B ในตอนนี้ 'git checkout -b temp $ hash_of_B; git push 'ควรกด B ที่จุดนั้น จากนั้นคุณอาจต้องการที่จะ 'git checkout -b master; git branch -d temp 'เพื่อกลับไปยังสถานะก่อนหน้าของคุณโดยสันนิษฐานว่าคุณอยู่ในสาขาหลักของท้องถิ่น แทนที่ตามความเหมาะสม
วอลเตอร์ Mundt

1
+1 คุณเคยพบกับ"ความโกรธเกรี้ยวของเทพเจ้า git"หลังจาก rebase-push-rebase หรือไม่? (อาจเกิดขึ้นโดยบังเอิญด้วยใช่มั้ย)
Drux

2
หากคุณอ่านคำตอบของฉันอย่างถี่ถ้วนคุณจะเห็นว่าการกดเกิดขึ้นหลังจากการรีบูตเท่านั้นและการคอมมิชชันที่ถูกปฏิเสธจะถูกย้ายไปเหนือคอมมิชชันอื่นที่ยังไม่ได้ผลัก เมื่อความมุ่งมั่นถูกผลักก็ควรได้รับการพิจารณาโดยทั่วไปตั้งอยู่ในหิน ปล่อยไว้ตามลำพังในการสร้างใหม่ในอนาคต เทคนิคนี้เป็นเพียงเพื่อให้คุณสามารถเรียงลำดับการเปลี่ยนแปลงในท้องถิ่นหลายรายการเป็นการสั่งซื้อที่ดีก่อนที่จะผลักดันพวกเขา หากคุณมีการตั้งค่าการติดตามอย่างถูกต้อง 'git rebase -i' ที่ไม่มี args อื่น ๆ จะไม่แสดงว่าคุณได้ทำสัญญาไว้ดังนั้นจึงปลอดภัยจากอุบัติเหตุมากกว่าวิธีอื่น ๆ
วอลเตอร์ Mundt

21

Cherry-pick ใช้งานได้ดีที่สุดเมื่อเทียบกับวิธีอื่น ๆ ทั้งหมดในขณะที่กดการกระทำที่เฉพาะเจาะจง

วิธีที่จะทำคือ:

สร้างสาขาใหม่ -

git branch <new-branch>

อัปเดตสาขาใหม่ด้วยสาขาต้นทางของคุณ -

git fetch

git rebase

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

เชอร์รี่เลือกสิ่งsha idที่คุณต้องการทำ -

git cherry-pick <sha id of the commit>

คุณสามารถรับsha idโดยการเรียกใช้

git log

ผลักไปที่จุดเริ่มต้นของคุณ -

git push

เรียกใช้gitkเพื่อดูว่าทุกอย่างมีลักษณะเหมือนที่คุณต้องการ


2
การใช้git rebase -iจะเป็นโซลูชันที่สมบูรณ์แบบตามที่แนะนำในโซลูชันด้านบน ต้องใช้ Cherry pick เท่านั้นเมื่อคุณต้องการทำซ้ำการกระทำ
Vinay Bhargav

13

ฉันเชื่อว่าคุณจะต้อง "ย้อนกลับคอมไพล์" กลับไปที่การคอมมิทแล้วกดมัน หรือคุณสามารถคอมมิชชันcherry-pickเป็นสาขาใหม่และผลักไปที่สาขาบนที่เก็บระยะไกล สิ่งที่ต้องการ:

git branch onecommit
git checkout onecommit
git cherry-pick 7300a6130d9447e18a931e898b64eefedea19544 # From the other branch
git push origin {branch}

9
การย้อนกลับของ git เป็นความคิดที่ไม่ดีที่นี่ - มันสร้างความมุ่งมั่นใหม่
hased

1
@hasen: คุณสามารถcherry-pickทำตามที่คุณต้องการ
Josh K

4
ทั้งการเปลี่ยนกลับและการเลือกเชอร์รี่เป็นความคิดที่ไม่ดี git rebase -i เป็นเพื่อนของคุณที่นี่ดูคำตอบจาก Walter Mundt ด้านล่าง
Nicolas C

3
@ Nicolas ทำไมเชอร์รี่เลือกความคิดที่ไม่ดี?
แอนทอน

3
@Antoine โดยทั่วไปคุณต้องการให้สาขาของคุณซิงค์กับสาขาที่ติดตามอยู่ หากคุณเลือกเชอร์รี่คุณกำลังทำสำเนา / วางและคุณจะต้องจัดการกับสำเนาที่ไม่พุชในบางครั้ง หากคุณรีบูต -i คุณจะ "ตัดและวาง" และทำให้สาขาของคุณซิงค์กับรีโมตจนถึงตำแหน่งที่คุณต้องการ
Nicolas C

0

คุณสามารถทำได้ในไดเรกทอรีอื่น:

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