คุณจะผลักดันคอมไพล์ท้องถิ่นบางรายการของคุณได้อย่างไร


160

สมมติว่าฉันมี 5 ข้อผูกพันในท้องถิ่น ฉันต้องการเพียงแค่ 2 ของพวกเขาไปที่ repo ส่วนกลาง (ใช้เวิร์กโฟลว์สไตล์ SVN) ฉันจะทำสิ่งนี้ได้อย่างไร

สิ่งนี้ไม่ทำงาน:

git checkout HEAD~3  #set head to three commits ago
git push #attempt push from that head

ที่จบลงด้วยการผลักดันทั้ง 5 กระทำในท้องถิ่น

ฉันคิดว่าฉันสามารถทำการ git reset เพื่อเลิกทำการคอมมิชชันของฉันตามด้วย git stash แล้ว git push - แต่ฉันได้รับข้อความที่เขียนและการจัดระเบียบไฟล์แล้วและฉันไม่ต้องการทำซ้ำ

ฉันรู้สึกว่าธงบางอันผ่านไปเพื่อผลักหรือรีเซ็ตจะได้ผล

ถ้ามันช่วยได้นี่คือคอมไพล์ของฉัน

[ramanujan:~/myrepo/.git]$cat config 
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = ssh://server/git/myrepo.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master

คำตอบ:


192

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

$ git push origin master~3:master

หากคุณใช้ git-svn:

$ git svn dcommit master~3

ในกรณีของ git-svn คุณสามารถใช้ HEAD ~ 3 ได้เนื่องจากคาดว่าจะส่งมอบ ในกรณีของ git ตรงคุณต้องใช้ชื่อสาขาเนื่องจาก HEAD ไม่ได้รับการประเมินอย่างถูกต้องใน refspec

คุณสามารถใช้แนวทางที่ยาวขึ้นของ:

$ git checkout -b tocommit HEAD~3
$ git push origin tocommit:master

หากคุณมีนิสัยในการทำงานประเภทนี้คุณควรพิจารณาทำงานในสาขาอื่น จากนั้นคุณสามารถทำสิ่งที่ชอบ:

$ git checkout master
$ git merge working~3
$ git push origin master:master

โปรดทราบว่าส่วน "จุดเริ่มต้นหลัก: ต้นแบบ" อาจเป็นทางเลือกสำหรับการตั้งค่าของคุณ


14
หมายเหตุ: master~3คุณไม่จำเป็นต้องใช้ การอ้างอิงถึงการกระทำที่ "ถึง" ที่ต้องการนั้นมีผลบังคับใช้อย่างเท่าเทียมกันเช่นHEAD~3หรือHEAD~~~หรือ SHA ที่เฉพาะเจาะจงหรือแท็กที่กำหนดป้ายกำกับไว้
Kaz

2
สิ่งที่ดี. เตือนว่า: ตัวอย่างเหล่านี้ผลักดันให้ต้นแบบต้นแบบ หากคุณกำลังคัดลอกและวางโซลูชันนี้คุณอาจสิ้นสุดการอัพเดทสาขาหลักโดยไม่ตั้งใจ (แน่นอนคุณควรระวังและตรวจสอบคำสั่งของคุณก่อนออกgit push... )
nofinator

ดูเหมือนว่าสิ่งนี้จะผลักดันการกระทำ แต่ไม่ได้เพิ่มสาขาจากระยะไกล
Nateowami

@Nateowami สำหรับสิ่งที่คุณจะต้องระบุสิ่งอื่นนอกเหนือmasterจากด้านไกลของผู้อ้างอิงเช่นgit push origin tocommit:newbramch
Ryan Graham

ฉันเห็น. ชื่อสาขามีอยู่ในเครื่องแล้ว ฉันคิดว่ามันไม่เป็นเช่นนั้น รีโมตยังไม่มีชื่อสาขา
Nateowami

16

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

หลังจากที่ดึงการเปลี่ยนแปลงตั้งแต่ต้นน้ำลงในสาขาต้นแบบของฉันฉันและgit checkout work git rebase masterที่เขียนการเปลี่ยนแปลงในพื้นที่ทั้งหมดของฉันให้เป็นตอนท้ายของประวัติศาสตร์

ฉันจริงใช้git svnกับเวิร์กโฟลว์นี้เพื่อให้ "ดัน" git svn dcommitของฉันการดำเนินงานที่เกี่ยวข้องกับการ ฉันยังใช้tigซึ่งเป็นโปรแกรมดูที่เก็บข้อความโหมด gui ที่ดีเพื่อให้เชอร์รี่เลือกข้อผูกพันที่เหมาะสมที่จะโท


ด้วย git svn dcommit คุณสามารถระบุการคอมมิทถึง dcommit ได้มากดังนั้นเอฟเฟกต์ที่ต้องการค่อนข้างไม่สำคัญกับ git-svn
Ryan Graham

มีข้อเสียสำหรับวิธีนี้ (สรุปได้ที่นี่stackoverflow.com/a/881014/1116674 ) ทางเลือกที่ดีคือการสร้างสาขาสำหรับทุกฟีเจอร์ที่คุณกำลังทำงานและworkสาขา จากนั้นคุณรวมสาขาที่เฉพาะเจาะจงเข้าด้วยกันmasterเพื่อที่คุณจะได้ไม่เสียประวัติพวกเขาไป เมื่อทำงานด้วยworkคุณรวมสาขาทั้งหมดของคุณเข้าด้วยกัน มันมีค่าใช้จ่ายมากกว่า แต่ก็อาจคุ้มค่าในบางกรณี
Hudon

16

โดยค่าเริ่มต้น git-push จะผลักสาขาทั้งหมด เมื่อคุณทำสิ่งนี้:

 git checkout HEAD~3  #set head to three commits ago
 git push #attempt push from that head

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

วิธีแก้ปัญหาด้วยตนเองคือ:

 git push origin HEAD:master

หากคุณพบว่าพฤติกรรมเริ่มต้นของการผลักสาขาทั้งหมดทำให้เกิดความสับสน (และอันตราย!) ให้เพิ่มสิ่งนี้ใน ~ / .gitconfig ของคุณ:

 [remote.origin]
    push = HEAD

จากนั้นจึงผลักเฉพาะสาขาที่คุณเปิด ในตัวอย่างของคุณ (เฮดเดอร์เดี่ยว) คุณจะได้รับข้อความแสดงข้อผิดพลาดนี้แทนที่จะผลักดันการกระทำผิดโดยไม่ตั้งใจ:

 error: unable to push to unqualified destination: HEAD

10

คำตอบสั้น ๆ :

git push <latest commit SHA1 until you want commits to be pushed>

ตัวอย่าง:

git push fc47b2

git push HEAD~2

คำตอบยาว:

คอมมิทถูกเชื่อมโยงเข้าด้วยกันเป็นเชนด้วยกลไกพาเรนต์ / ลูก ดังนั้นการกดคอมมิชชันก็ผลักให้ผู้ปกครองทุกคนกระทำการนี้ด้วยโดยที่ไม่รู้จักรีโมต นี้จะกระทำโดยปริยายเมื่อคุณgit pushปัจจุบันกระทำ: git push HEADทั้งหมดกระทำก่อนหน้านี้นอกจากนี้ยังมีการผลักดันเพราะคำสั่งนี้จะเทียบเท่ากับ

ดังนั้นคำถามอาจถูกเขียนใหม่ในวิธีการผลักดันการกระทำที่เฉพาะเจาะจงและการกระทำที่เฉพาะเจาะจงนี้อาจเป็น HEAD ~ 2 ตัวอย่างเช่น

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


5

1) ใช้ "git rebase" เพื่อจัดลำดับการคอมมิทใหม่ของคุณหากคุณต้องการ

git rebase -i

คำสั่งนี้จะแสดงบางอย่างเช่นนี้ในโปรแกรมแก้ไขของคุณ (ฉันใช้เป็นกลุ่ม)

pick 4791291 commitA
pick a2bdfbd commitB
pick c3d4961 commitC
pick aa1cefc commitD
pick 9781434 commitE

# Rebase ..............
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out




^G Get Help         ^O WriteOut         ^R Read File        ^Y Prev Page                ^K Cut Text         ^C Cur Pos
^X Exit             ^J Justify          ^W Where Is         ^V Next Page            ^U UnCut Text       ^T To Spell

2) จัดลำดับความมุ่งมั่นของคุณใหม่ตามที่คุณเลือกโดยวางตัดง่าย สมมติว่าคำสั่งซื้อใหม่คือ

เลือก 9781434 การส่งมอบ

เลือก c3d4961 commitC

เลือก 4791291 การส่งมอบ

เลือก aa1cefc commitD

เลือก a2bdfbd commitB

ทำการเปลี่ยนแปลงเหล่านี้ในตัวแก้ไขของคุณและกด ctrl + O (writeOut)

หรือคุณยังสามารถใช้

git rebase -i HEAD~<commitNumber>

คุณสามารถตรวจสอบลำดับใหม่ด้วย

git log

3) ตอนนี้ใช้

git push <remoteName> <commit SHA>:<remoteBranchName>

ถ้ามีเพียงหนึ่งสาขาที่รีโมต (แหล่งกำเนิด) และสาขาที่โลคัล (ต้นแบบ) เพียงใช้

git push <commit SHA>
git push aa1cefc

สิ่งนี้จะผลักดัน commitB และ commitD

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