วิธีใช้ git merge --squash


1209

ฉันมีเซิร์ฟเวอร์ Git ระยะไกลนี่คือสถานการณ์ที่ฉันต้องการดำเนินการ:

  • สำหรับแต่ละข้อบกพร่อง / คุณสมบัติฉันสร้างสาขา Git ที่แตกต่างกัน

  • ฉันยืนยันรหัสของฉันในสาขา Git นั้นด้วยข้อความ Git ที่ไม่เป็นทางการ

  • ในพื้นที่เก็บข้อมูลด้านบนเราต้องทำอย่างใดอย่างหนึ่งกระทำสำหรับหนึ่งข้อผิดพลาดที่มีข้อความ Git อย่างเป็นทางการ

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


1
ฉันไม่แน่ใจว่าฉันเข้าใจคุณทั้งหมดหรือไม่ แต่คุณอาจต้องการ "octopus merge"
MatrixFrog

27
โดยทั่วไปฉันใช้git rebase -iเพื่อยุบคอมมิททั้งหมดของฉันเป็นคอมมิทเดียวและเขียนข้อความคอมมิทใหม่อีกครั้ง จากนั้นฉันก็ส่งทวนน้ำ
Edward Falk

17
git merge --squashทำทุกอย่างในบรรทัดคำสั่งในนัดเดียวและคุณแค่หวังว่ามันจะได้ผล git rebase -iเปิดตัวโปรแกรมแก้ไขและช่วยให้คุณปรับการรีบูต ช้ากว่า แต่คุณสามารถเห็นสิ่งที่คุณทำ นอกจากนี้ยังมีความแตกต่างระหว่างการลดระดับและการรวมซึ่งมีส่วนเกี่ยวข้องเพียงเล็กน้อยในการแสดงความคิดเห็น
Edward Falk

4
ปัญหาเกี่ยวกับคำตอบทั้งหมดนี้คือคุณต้องอยู่ในสาขาหลักในเครื่องและเรียกใช้คำสั่ง merge --squash ... ฉันต้องการเรียกใช้ merge --squash จากสาขาคุณสมบัติไม่ใช่สาขาหลัก .. เพื่อที่ เมื่อฉันทำเสร็จแล้วฉันสามารถผลักสาขาฟีเจอร์ไปที่รีโมตและส่ง PR เป็นไปได้ไหม
Alexander Mills

2
@AlexanderMills ฉันคิดว่าคุณต้องการสาขาฟีเจอร์ที่สอง (โคลนจากสาขาหลัก) ทำmerge --squashตั้งแต่เก่าถึงใหม่แล้วรวมสาขาใหม่เข้ากับต้นแบบ สาขาเก่าล้าสมัย
Gyromite

คำตอบ:


1999

สมมติว่ามีการเรียกสาขาแก้ไขข้อบกพร่องของคุณbugfixและคุณต้องการรวมเข้าไปในmaster:

git checkout master
git merge --squash bugfix
git commit

สิ่งนี้จะนำการกระทำทั้งหมดจากbugfixสาขาสควอชพวกเขาเป็น 1 กระทำและรวมกับmasterสาขาของคุณ


คำอธิบาย :

git checkout master

สลับไปที่masterสาขาของคุณ

git merge --squash bugfix

รับคอมมิชชันทั้งหมดจากbugfixสาขาและรวมเข้ากับสาขาปัจจุบันของคุณ

git commit

สร้างการคอมมิทเดียวจากการเปลี่ยนแปลงที่ถูกผสาน

การข้าม-mพารามิเตอร์ช่วยให้คุณสามารถแก้ไขข้อความคอมมิชชันที่มีทุกข้อความจากการคอมมิตของคุณก่อนที่จะทำการคอมมิท


222
หากคุณต้องการเก็บการอ้างอิงไปยังข้อความการส่งข้อความเก่าคุณสามารถเขียนgit commit(โดยไม่มี-mพารามิเตอร์) และคุณจะได้รับการแก้ไขข้อความยืนยันแบบร่างที่มีข้อความการส่งข้อความทั้งหมดที่คุณส่ง
อเล็กซ์

12
คุณสามารถบรรลุเป้าหมายเดียวกันได้โดยทำในgit commit --amend -m '...'ภายหลัง
Janusz Lenar

19
ในกรณีที่มีข้อขัดแย้งการผสานเกิดขึ้นและคุณแก้ไขข้อขัดแย้งเหล่านี้git commitจะไม่แสดงข้อความการส่งข้อความที่มีประโยชน์ซึ่งมีข้อความการส่งข้อความทั้งหมดที่คุณถูกบีบอัดอีกต่อไป ในกรณีนี้ลองgit commit --file .git/SQUASH_MSG(ผ่านstackoverflow.com/a/11230783/923560 )
Abdull

23
โปรดทราบว่าฉับจะได้โดยเริ่มต้นแอตทริบิวต์กระทำเพื่อ Squasher เพื่อให้ผู้เขียนต้นฉบับคุณต้องระบุอย่างชัดเจนเช่น:git commit -a --author="Author" --message="Issue title #id"
gaborous

5
git merge --squashอนุญาตให้คุณสร้างการคอมมิชชันเดียวที่ด้านบนของสาขาปัจจุบันที่มีผลเหมือนกับการรวมสาขาอื่น แต่จะไม่สร้างบันทึกการผสานซึ่งหมายความว่าคำขอการดึงของคุณเนื่องจากผลลัพธ์จะไม่มีการเปลี่ยนแปลง แต่จะไม่ถูกทำเครื่องหมายว่าถูกผสาน! ดังนั้นคุณจะต้องลบสาขานั้นให้เสร็จ
am0wa

129

ในที่สุดสิ่งที่หักล้างสิ่งนี้สำหรับฉันคือความคิดเห็นที่แสดงว่า:

git checkout main
git merge --squash feature

เทียบเท่ากับการทำ:

git checkout feature
git diff main > feature.patch
git checkout main
patch -p1 < feature.patch
git add .

เมื่อฉันต้องการรวมสาขาฟีเจอร์ด้วย 105 (!!) คอมมิตและให้พวกเขาทั้งหมดถูกบีบอัดเป็นหนึ่งฉันไม่ต้องการgit rebase -i origin/masterเพราะฉันต้องแยกข้อขัดแย้งการรวมสำหรับแต่ละคอมมิทขั้นกลาง (หรืออย่างน้อยก็อันที่ git ไม่สามารถเข้าใจตัวเอง) การใช้git merge --squashทำให้ฉันได้รับผลลัพธ์ที่ฉันต้องการจากการกระทำเดียวเพื่อรวมสาขาคุณลักษณะทั้งหมด และฉันต้องแก้ไขข้อขัดแย้งด้วยตนเองได้เพียงหนึ่งครั้งเท่านั้น


75
ฉันขอแนะนำอย่างยิ่งให้ทำการผสานในสาขาคุณลักษณะก่อนgit merge masterและจากนั้นgit merge --squash featureในสาขาหลักเท่านั้น
dotancohen

8
@dotancohen ขออภัยที่จะขุดความคิดเห็นเก่า :) สิ่งที่ได้รับจากการรวมในสาขาคุณสมบัติก่อนที่จะดำเนินการgit merge --squash featureจากสาขาหลัก?
bitsmack

57
คุณต้องการผสานต้นแบบเข้ากับสาขาคุณลักษณะก่อนและจัดการกับการแก้ไขด้วยตนเองในสาขาคุณลักษณะของคุณ นอกจากนี้ยังช่วยให้คุณเรียกใช้การทดสอบและตรวจสอบให้แน่ใจว่าฟีเจอร์สาขาของคุณทำงานอย่างถูกต้อง จากนั้นคุณรับประกันได้ว่าคุณสามารถผสานคุณสมบัติสาขาของคุณเข้ากับต้นแบบโดยอัตโนมัติ
Dan Kohn

4
@dankohn ฉันขอแนะนำให้คุณเพิ่มคำอธิบายในความคิดเห็นข้างต้นลงในคำตอบของคุณ
guntbert

3
@bitsmack: คุณจะรวมต้นแบบเข้ากับคุณลักษณะก่อน สิ่งนี้ให้โอกาสคุณในการแก้ไขข้อขัดแย้งของคุณลักษณะก่อนที่จะรวมคุณสมบัติเข้ากับต้นแบบ
Mike

97

คุณต้องการรวมเข้ากับตัวเลือกสควอช นั่นคือถ้าคุณต้องการที่จะทำมันทีละสาขา

git merge --squash feature1

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

git checkout feature1
git rebase -i master

สควอชเป็นหนึ่งกระทำแล้วทำซ้ำสำหรับคุณสมบัติอื่น ๆ

git checkout master
git merge feature1 feature2 feature3 ...

การผสานครั้งสุดท้ายนั้นเป็น "การผสานปลาหมึกยักษ์" เพราะมันรวมสาขาจำนวนมากในครั้งเดียว

หวังว่านี่จะช่วยได้


3
ทำไมคุณกำลังลดระดับ
Umair A.

12
@UmairAshraf เป็น rebase เชิงโต้ตอบที่ให้ตัวเลือกในการทำสควอชในสาขาของคุณ
andho

1
การรีบูตเป็นความคิดที่ไม่ดี อย่า
รีบูตการ

1
@ Sebi2020 git merge - สควอชจะรีบูตคอมมิชชันที่เผยแพร่ไปแล้วของคุณในแบบที่แย่กว่ารีบูตแบบโต้ตอบ การปฏิเสธแบบโต้ตอบ (ในสาขาคุณลักษณะ) มีผลกระทบเล็กน้อยถึงไม่มีเลย
xiix

1
@xiix สิ่งนี้ถือเป็นจริงถ้าคุณเพียงคนเดียวที่ทำงานกับสาขาคุณลักษณะ นี่ไม่ใช่ข้อสมมุติที่คุณสามารถทำได้ ผมขอแนะนำให้อ่านหน้าเว็บที่เกี่ยวข้องกับ rebasing ในGit-SCM มันระบุว่า " อย่ารีบูตเครื่องที่มีอยู่นอกพื้นที่เก็บข้อมูลของคุณและผู้คนอาจทำงานตามพวกเขา " และถ้าคุณไม่รู้ว่าคนใช้งานคอมมิชชันที่เผยแพร่แล้วหรือไม่ ธรรมชาติของ git) คุณไม่ควรทำอย่างนั้น
Sebi2020

23

หากคุณมีอยู่แล้วgit merge bugfixบนmainคุณสามารถผสานสควอชกระทำของคุณเป็นหนึ่งด้วย:

git reset --soft HEAD^1
git commit

git reset --soft HEAD^1ดูเหมือนว่าจะยกเลิกการคอมมิชชันล่าสุดที่ดำเนินการก่อนการรวมอย่างน้อยในกรณีที่การผสานเป็นการส่งต่อที่รวดเร็ว
Jesper Matthiesen

@JesperMatthiesen git reset --soft HEAD^<number-of-commits-to-squash>ในกรณีที่มีการส่งต่ออย่างรวดเร็วคุณไม่ได้รับการผสานกระทำดังนั้นแล้วคุณจะทำอย่างไร
qwertzguy

สิ่งนี้ช่วยให้ฉันสควอชทุกอย่างให้เป็นหนึ่งเดียวหลังจากการรวมดาวน์สตรีม
killjoy

18

ผสานnewFeatureสาขาเข้าmasterกับการกระทำที่กำหนดเอง:

git merge --squash newFeature && git commit -m 'Your custom commit message';

ถ้าคุณทำเช่นนั้น

git merge --squash newFeature && git commit

คุณจะได้รับข้อความคอมมิชชันที่จะรวมการคอมมิชชันnewFeatureสาขาทั้งหมดซึ่งคุณสามารถกำหนดเองได้

ฉันอธิบายอย่างละเอียดที่นี่: https://youtu.be/FQNAIacelT4


10

ฉันรู้ว่าคำถามนี้ไม่ได้เกี่ยวกับ Github โดยเฉพาะ แต่เนื่องจาก Github นั้นถูกใช้อย่างกว้างขวางและนี่คือคำตอบที่ฉันต้องการฉันจะแบ่งปันที่นี่

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

หากมีการเปิดใช้งานการรวมสควอชตัวเลือก "สควอชและผสาน" ควรปรากฏขึ้นในเมนูดร็อปดาวน์ภายใต้ปุ่ม "ผสาน"

สกรีนช็อตของฟีเจอร์ "สควอชและผสาน" Github


GitHub ใช้อีเมลเริ่มต้นที่เชื่อมโยงกับบัญชีของคุณ หากคุณมีที่อยู่อีเมลหลายแห่งและจำเป็นต้องใช้ที่อยู่สำรองคุณไม่สามารถใช้ GH UI ได้
Luca Guidi

4

สมมติว่าคุณทำงานในคุณสมบัติ / task1 ที่มีหลายคอมมิท

  1. ไปที่สาขาโครงการของคุณ (โครงการ / my_project)

    git checkout project/my_project
    
  2. สร้างสาขาใหม่ (คุณสมบัติ / task1_bugfix)

    git checkout -b feature/task1_bugfix
    
  3. มาร์จกับ--squashตัวเลือก

    git merge --squash feature/task1
    
  4. สร้างความมุ่งมั่นเดียว

    git commit -am "add single comments"
    
  5. ดันสาขาของคุณ

    git push --set-upstream origin feature/task1_bugfix
    

1

สำหรับ Git

สร้างคุณสมบัติใหม่

ผ่าน Terminal / Shell:

git checkout origin/feature/<featurename>
git merge --squash origin/feature/<featurename>

วิธีนี้ไม่ได้อนุญาตให้คุณตรวจสอบก่อน

จากนั้นส่งมอบและเสร็จสิ้นคุณสมบัติจากสาขาใหม่นี้และลบ / เพิกเฉยสาขาเก่า (สาขาที่คุณทำบน dev)


@Melebius การอ้างอิงเดียวกับ "SourceTree" อยู่ในประโยคของคุณหากเป็นแท็กหรือคำถามก่อนหน้า: ไม่มีอยู่อีกต่อไป
Jordan Stefanelli

1
@JordanStefanelli SourceTree ถูกใช้ในรุ่นเดิมของคำตอบนี้ ขอขอบคุณที่แจ้งว่าได้รับการแก้ไขแล้ว!
Melebius

1

หากคุณได้รับข้อผิดพลาด: ไม่สามารถทำการยืนยันได้เนื่องจากคุณมีไฟล์ที่ไม่ได้ถูกแยกทิ้ง

git checkout master
git merge --squash bugfix
git add .
git commit -m "Message"

แก้ไขไฟล์ Conflict ทั้งหมด

git add . 

คุณสามารถใช้

git add [filename]

0

วิธีสควอชสาขาท้องถิ่นของคุณก่อนที่จะผลักดัน:

  1. ชำระเงินที่สาขาที่มีปัญหาเพื่อดำเนินการต่อหากยังไม่ได้ชำระเงิน

  2. ค้นหา sha ของความมุ่งมั่นที่เก่าแก่ที่สุดที่คุณต้องการเก็บ

  3. สร้าง / ชำระเงินสาขาใหม่ (tmp1) จากการกระทำที่

    git checkout -b tmp1 <sha1-of-commit>

  4. รวมสาขาเดิมเข้ากับสาขาใหม่

    git merge --squash <original branch>

  5. ยอมรับการเปลี่ยนแปลงที่สร้างขึ้นโดยการผสานด้วยข้อความคอมมิทสรุป

    git commit -m <msg>

  6. ชำระเงินสาขาเดิมที่คุณต้องการสควอช

    git checkout <branch>

  7. รีเซ็ตเป็นแบบเดิมที่คุณต้องการเก็บไว้

    git reset --soft <sha1>

  8. รีบูตสาขานี้ตามสาขา tmp1 ใหม่

    git rebase tmp1

  9. เอาล่ะ - ตอนนี้ลบสาขา tmp1 ชั่วคราวเมื่อคุณแน่ใจว่าทุกอย่างเรียบร้อย


0

คุณสามารถใช้เครื่องมือที่ฉันได้สร้างขึ้นเพื่อให้กระบวนการนี้ง่ายขึ้น: Git-สควอช ตัวอย่างเช่นการสควอชทั้งหมดกระทำในสาขาฟีเจอร์ที่แยกจากสาขาหลักเขียน:

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