ย้ายมุ่งมั่น (แต่ไม่ผลัก) การเปลี่ยนแปลงไปยังสาขาใหม่หลังจากดึง


460

ฉันได้ทำงานนิดหน่อย ("สาขาของคุณอยู่ก่อนหน้า 'ต้นกำเนิด / ปรมาจารย์' โดยมีความมุ่งมั่น 37 อย่าง") ซึ่งจริง ๆ แล้วควรเข้าไปในสาขาของตัวเองมากกว่าเข้าmasterมา การกระทำเหล่านี้มีอยู่ในเครื่องของฉันเท่านั้นและไม่ได้ถูกผลักไปoriginแต่สถานการณ์นั้นค่อนข้างซับซ้อนใน devs อื่น ๆ ที่ได้รับการผลักดันorigin/masterและฉันได้ทำการเปลี่ยนแปลงเหล่านั้นแล้ว

ฉันจะย้ายการตอบรับในพื้นที่ 37 แห่งไปยังสาขาใหม่ได้อย่างไร จากเอกสารพบว่าgit rebase --onto my-new-branch masterหรือ...origin/masterควรทำเช่นนี้ แต่ทั้งคู่ก็ให้ข้อผิดพลาด "ร้ายแรง: จำเป็นต้องมีการแก้ไขครั้งเดียว" man git-rebaseไม่ได้พูดอะไรเกี่ยวกับการให้การแก้ไขrebaseและตัวอย่างของมันไม่ทำดังนั้นฉันจึงไม่รู้ว่าจะแก้ไขข้อผิดพลาดนี้ได้อย่างไร

(โปรดทราบว่านี่ไม่ใช่งานซ้ำของMove ที่มีอยู่ไม่ได้ผูกมัดกับสาขาใหม่ใน Gitหรือจะรวมการเปลี่ยนแปลงในพื้นที่ของฉันเข้ากับ Git สาขาอื่นได้อย่างไรเนื่องจากคำถามเหล่านั้นจัดการกับการเปลี่ยนแปลงที่ไม่มีข้อผูกมัดในแผนผังการทำงานท้องถิ่น มุ่งมั่นในท้องถิ่น)


ลองดูโซลูชันนี้ ดูเหมือนจะง่ายและสะอาด
โทนี่

ลองดูโซลูชันนี้ ดูเหมือนจะง่ายและสะอาด
โทนี่

คำตอบ:


518

สิ่งนี้น่าจะดีเพราะคุณยังไม่ได้ส่งคำมั่นสัญญาไปที่อื่นและคุณมีอิสระที่จะเขียนประวัติสาขาของคุณorigin/masterอีกครั้ง ก่อนอื่นฉันจะเรียกใช้ a git fetch originเพื่อให้แน่ใจว่าorigin/masterเป็นรุ่นล่าสุด สมมติว่าคุณอยู่ในขณะนี้masterคุณควรจะทำ:

git rebase origin/master

... ซึ่งจะเล่นใหม่ทั้งหมดกระทำของคุณที่ไม่ได้อยู่ในบนorigin/master origin/masterการดำเนินการเริ่มต้นของการรีบูตคือการละเว้นการรวมคอมมิชชัน (เช่นgit pullการแนะนำของคุณorigin/master) (คุณอาจต้องแก้ไขข้อขัดแย้งระหว่างทาง) จากนั้นคุณสามารถสร้างสาขาใหม่ของคุณตามผลลัพธ์:

git branch new-work

... จากนั้นรีเซ็ตmasterกลับเป็นorigin/master:

# Use with care - make sure "git status" is clean and you're still on master:
git reset --hard origin/master

เมื่อทำชนิดของการจัดการกับสาขานี้git branch, git resetฯลฯ ฉันพบว่ามันมีประโยชน์ที่จะบ่อยดูที่กระทำกราฟที่มีgitk --allหรือเครื่องมือที่คล้ายกันเพียงเพื่อตรวจสอบว่าฉันเข้าใจที่ทุก refs ที่แตกต่างกันจะชี้

หรือคุณอาจสร้างหัวข้อสาขาตามตำแหน่งที่มาสเตอร์ของคุณอยู่ในตำแหน่งแรก ( git branch new-work-including-merges) จากนั้นรีเซ็ตmasterตามข้างต้น อย่างไรก็ตามเนื่องจากสาขาหัวข้อของคุณจะรวมการผสานจากorigin/masterและคุณยังไม่ได้ผลักดันการเปลี่ยนแปลงของคุณฉันขอแนะนำให้ทำการรีบูตเพื่อให้ประวัติศาสตร์มีความเป็นระเบียบมากขึ้น (นอกจากนี้เมื่อคุณรวมสาขาหัวข้อของคุณกลับมาเป็นหลักในที่สุดการเปลี่ยนแปลงจะชัดเจนยิ่งขึ้น)


8
@Olie: ไม่คำตอบนั้นถูกต้องภายใต้สมมติฐานในคำถามและคำตอบที่ฉันตั้งไว้ที่ด้านบนของคำตอบ ความมุ่งมั่นที่ควรจะอยู่ในสาขาใหม่แยกต่างหากมีอยู่แล้วในmaster; rebase เขียนใหม่masterสาขาเพื่อให้การกระทำใหม่จะเป็นเส้นตรงด้านบนของorigin/masterแล้วgit branch new-workสร้างnew-workชี้สาขาที่ปลายของmaster(สาขาในปัจจุบัน) โดยไม่ต้องnew-workเปลี่ยนสาขาปัจจุบัน ดังนั้นตอนนี้new-workมีความมุ่งมั่นใหม่ทั้งหมด แล้วรีเซ็ตย้ายสาขาในปัจจุบัน (ยังคงmaster) origin/masterกลับไป
Mark Longair

1
@Quintesse: ฉันเสียใจมากถ้าคุณสูญเสียงาน แต่ฉันแน่ใจว่าคำตอบนี้ถูกต้องสำหรับสถานการณ์ที่ผู้ถามดั้งเดิมอธิบายไว้ (ฉันเพิ่งตอบไปด้วยคำพูดของ Olie หวังว่าจะชี้แจง) อย่างไรก็ตามในกรณีที่ช่วยให้คุณกลับมาทำงานได้ฉันควรจะบอกว่าถ้างานของคุณเกิดขึ้นภายในไม่กี่วันที่ผ่านมา (หนึ่งในข้อสมมติในคำถามและคำตอบนี้ ) คุณควรจะสามารถเรียกดูได้ง่ายผ่าน reflog คอมไพล์
Mark Longair

5
@Olie: อาจเป็นวิธีที่ดีกว่าในการอธิบาย: กิ่งใน git ก็เหมือนป้ายที่ชี้ไปที่การกระทำเฉพาะ พวกเขาจะถูกย้ายไปที่พันธสัญญาใหม่โดยอัตโนมัติหากคุณสร้างพวกเขาในขณะที่อยู่ในสาขานั้นหรือสามารถย้ายด้วยgit resetและวิธีอื่น ๆ git branch new-workเป็นเพียงการพูดว่า "สร้างสาขาชี้ไปที่นี้กระทำในขณะที่ผมยังคงอยู่ในสาขาปัจจุบันของฉัน (ซึ่งเป็นหลักในกรณีนี้)" ดังนั้นไม่จำเป็นต้องมีคำสั่งที่ย้ายคอมมิชชันจากต้นแบบไปยังสาขาใหม่ - คุณเพิ่งสร้างสาขาใหม่ที่นั่นและเมื่อคุณรีเซ็ตต้นแบบสาขาใหม่จะถูกทิ้งไว้ที่ตำแหน่งเดิม
Mark Longair

1
สายไปงานเลี้ยง แต่ @Olie เพียงเพราะสถานะคอมไพล์เมื่อในสาขาใหม่ไม่ได้แสดงความมุ่งมั่นข้างหน้าของเจ้านายไม่ได้หมายความว่าพวกเขาไม่ได้อยู่ที่นั่นจริงๆ (สมมติว่าเป็นเพราะคุณเป็นห่วง) ลองผลักดันสาขาใหม่สู่แหล่งกำเนิด: คุณจะเห็นความมุ่งมั่นอยู่ที่นั่น
Félix Gagnon-Grenier

2
@ FélixGagnon-Grenier ไม่ต้องกังวลกับ "สาย" - มีคนค้นหาคำถามเก่า ๆ อยู่เสมอและการชี้แจงทุกครั้งจะช่วยได้ ขอบคุณ! :)
Olie

148

หากคุณมีภาระผูกพันต่ำและคุณไม่สนใจว่าสิ่งเหล่านี้จะรวมกันเป็นหนึ่งเมกะกระทำนี้ทำงานได้ดีและไม่น่ากลัวเหมือนทำgit rebase:

เลิกทำไฟล์ (แทนที่ 1 ด้วย # ของข้อผูกมัด)

git reset --soft HEAD~1

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

git checkout -b NewBranchName

เพิ่มการเปลี่ยนแปลง

git add -A

ทำให้การกระทำ

git commit -m "Whatever"

5
git log --all --decorate --oneline --graphในการแสดงที่ง่ายต่อการเข้าใจกราฟกรุณาใช้
EliuX

เฮ้ @EliuX - ฉันไม่มีความเกี่ยวข้องที่นี่ คุณสามารถขยายหรือไม่
Stachu

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

4
ขอบคุณ!! นี่เป็นทางออกที่ง่ายมากและทำงานได้อย่างสมบูรณ์ !!
Chris Sim

90

ฉันติดอยู่กับปัญหาเดียวกัน ฉันพบโซลูชันที่ง่ายที่สุดที่ฉันต้องการแบ่งปัน

1) สร้างสาขาใหม่พร้อมการเปลี่ยนแปลงของคุณ

git checkout -b mybranch

2) (ไม่บังคับ) กดรหัสสาขาใหม่บนเซิร์ฟเวอร์ระยะไกล

git push origin mybranch

3) ชำระเงินกลับไปที่สาขาหลัก

git checkout master

4) รีเซ็ตรหัสสาขาหลักด้วยรีโมตเซิร์ฟเวอร์และนำการคอมมิตออก

git reset --hard origin/master

10
นั่นเป็นวิธีที่ง่ายที่สุด
dhilt

4
คุณสามารถออกจากขั้นตอนที่ 2 ฉันคิดว่าในเวลาตั้งแต่คำตอบด้านบนคอมไพล์มีการเปลี่ยนแปลงและการอนุญาตนี้ไม่ได้รับอนุญาตมาก่อน
เซบาสเตียน

นี่คือคำตอบที่ดีที่สุดในความคิดของฉัน
Macindows

1
คำตอบนี้ต้องย้ายไปด้านบน ขอบคุณ.
amit

27

อีกวิธีหนึ่งที่จะถือว่า branch1 - คือ Branch ที่มีการเปลี่ยนแปลงที่มุ่งมั่น branch2 - เป็น Branch ที่ต้องการ

git fetch && git checkout branch1
git log

เลือกกระทำรหัสที่คุณต้องการย้าย

git fetch && git checkout branch2
git cherry-pick commit_id_first..commit_id_last
git push

ตอนนี้ย้อนกลับการกระทำที่ไม่ได้รับการชำระจากสาขาเริ่มต้น

git fetch && git checkout branch1
git reset --soft HEAD~1

5
Cherry-pick เป็นคำสั่ง "คัดลอก / ย้ายคำสั่ง commit" ที่ดีที่สุด เมื่อประวัติสัมภาระสำหรับวัตถุประสงค์ของคุณ
John Neuhaus

นี่คือคำตอบที่สะดวกที่สุดสำหรับคำถามนี้ ขอบคุณสำหรับคำสั่ง!
Farah

คุณสามารถอัปเดตความคิดเห็นล่าสุดของคุณโดยที่ 1 หรือ n คือจำนวนการคอมมิชชันที่ยังไม่ได้กด? นี่ยังเป็นทางออกที่ดีสำหรับคำถามนี้
chAlexey

9

หรือมิฉะนั้นหลังจากที่คุณส่งมอบสาขาผิดให้ทำตามขั้นตอนเหล่านี้:

  1. git log
  2. git diff {previous to last commit} {latest commit} > your_changes.patch
  3. git reset --hard origin/{your current branch}
  4. git checkout -b {new branch}
  5. git apply your_changes.patch

ฉันสามารถจินตนาการได้ว่ามีวิธีที่ง่ายกว่าสำหรับขั้นตอนที่หนึ่งและสอง


6

เกี่ยวกับ:

  1. สาขาจาก HEAD ปัจจุบัน
  2. ตรวจสอบให้แน่ใจว่าคุณเป็นผู้เชี่ยวชาญไม่ใช่สาขาใหม่ของคุณ
  3. git reset กลับไปที่การคอมมิทล่าสุดก่อนที่จะเริ่มทำการเปลี่ยนแปลง
  4. git pull เพื่อดึงเฉพาะการเปลี่ยนแปลงระยะไกลที่คุณโยนทิ้งไปด้วยการรีเซ็ต

หรือจะระเบิดเมื่อคุณพยายามรวมสาขาอีกครั้ง?


2
อ่านี่เป็นตัวเลือก B ที่อธิบายโดย @ Mark-Longair ด้านบน
Tim Keating

2

นี่เป็นวิธีที่ง่ายกว่ามาก:

  1. สร้างสาขาใหม่

  2. ในสาขาใหม่ของคุณทำgit merge master- สิ่งนี้จะรวมการเปลี่ยนแปลงที่คุณมุ่งมั่น (ไม่ได้ผลัก) กับสาขาใหม่ของคุณ

  3. ลบสาขาหลักในเครื่องของคุณgit branch -D masterใช้-Dแทน-dเพราะคุณต้องการบังคับให้ลบสาขา

  4. เพียงทำgit fetchในสาขาหลักของคุณและทำgit pullในสาขาหลักของคุณเพื่อให้แน่ใจว่าคุณมีรหัสล่าสุดของทีม


1

วิธีที่ง่ายกว่าซึ่งฉันใช้อยู่ (สมมติว่าคุณต้องการย้าย 4 คอมมิชชัน):

git format-patch HEAD~4

(ดูในไดเรกทอรีที่คุณใช้คำสั่งสุดท้ายสำหรับ 4 .patchไฟล์)

git reset HEAD~4 --hard

git checkout -b tmp/my-new-branch

แล้ว:

git apply /path/to/patch.patch

ในสิ่งที่คุณต้องการ


0
  1. ชำระเงินสำเนาต้นฉบับของคุณใหม่

    git clone ........

  2. ทำให้สาขาจากตำแหน่งที่ต้องการ

    git checkout {position} git checkout -b {branch-name}

  3. เพิ่มที่เก็บระยะไกล

    git remote add shared ../{original sources location}.git

  4. รับแหล่งที่มาจากระยะไกล

    git fetch shared

  5. ชำระเงินสาขาที่ต้องการ

    git checkout {branch-name}

  6. รวมแหล่งที่มา

    git merge shared/{original branch from shared repository}


0

สำหรับฉันนี่เป็นวิธีที่ดีที่สุด:

  1. ตรวจสอบการเปลี่ยนแปลงและรวมความขัดแย้ง git fetch
  2. สร้างสาขาใหม่git branch my-changesและกดไปที่รีโมต
  3. เปลี่ยนอัปสตรีมเป็นสาขาที่สร้างขึ้นใหม่ git master -u upstream-branch remotes/origin/my-changes
  4. ผลักดันความมุ่งมั่นของคุณไปยังสาขาต้นน้ำใหม่
  5. สลับกลับไปเป็นอัปสตรีมก่อนหน้า git branch master --set-upstream-to remotes/origin/master
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.