ฉันจะดูตัวอย่างการผสานด้วยคอมไพล์ได้อย่างไร


397

ฉันมีสาขาคอมไพล์ (ตัวอย่างการฉีด) และฉันต้องการรวมในสาขาการพัฒนาอื่น หรือฉัน

เพื่อที่จะตัดสินใจว่าฉันต้องการรวมสาขานี้หรือไม่ฉันต้องการดูตัวอย่างของการผสานที่จะทำ ควรมีความสามารถในการดูรายการของการคอมมิทที่ถูกนำไปใช้

เพื่อให้ห่างไกลดีที่สุดที่ฉันสามารถขึ้นมามีแล้วmerge --no-ff --no-commitdiff HEAD


17
ฉันต้องการgit mergeและgit reset --keep HEAD@{1}ถ้าฉันไม่ชอบผลลัพธ์
Jan Hudec

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

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

2
@Jan: ด้วยเหตุผลบางอย่างgit reset --keep HEAD@{1}คืนfatal: Cannot do a keep reset in the middle of a merge.ความช่วยเหลือ?
moey

3
ทำไมไม่มี--previewตัวเลือกในคอมไพล์ผสาน?
Gaui

คำตอบ:


283

ฉันพบว่าการแก้ปัญหาที่ดีที่สุดสำหรับผมคือการเป็นเพียงแค่ดำเนินการผสานและยกเลิกได้หากมีความขัดแย้ง ไวยากรณ์นี้รู้สึกสะอาดและเรียบง่ายสำหรับฉัน นี่คือกลยุทธ์ 2ด้านล่าง

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

กลยุทธ์ที่ 1: วิธีที่ปลอดภัย - รวมสาขาชั่วคราว:

git checkout mybranch
git checkout -b mynew-temporary-branch
git merge some-other-branch

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

นี่เป็นพื้นแห้ง

กลยุทธ์ที่ 2: เมื่อคุณต้องการผสานอย่างแน่นอน แต่หากไม่มีความขัดแย้ง

git checkout mybranch
git merge some-other-branch

หาก git รายงานข้อขัดแย้ง (และเฉพาะในกรณีที่มีข้อขัดแย้ง) คุณสามารถทำได้:

git merge --abort

หากการผสานสำเร็จคุณจะไม่สามารถยกเลิกได้ (รีเซ็ตเท่านั้น)

หากคุณยังไม่พร้อมที่จะรวมใช้วิธีที่ปลอดภัยกว่าด้านบน

[แก้ไข: 2016-พ.ย. - ฉันเปลี่ยนกลยุทธ์ 1 สำหรับ 2 เพราะดูเหมือนว่าคนส่วนใหญ่กำลังมองหา "วิธีที่ปลอดภัย" กลยุทธ์ที่ 2 เป็นบันทึกย่อที่คุณสามารถยกเลิกการผสานได้ถ้าการผสานมีข้อขัดแย้งที่คุณไม่พร้อมที่จะจัดการ โปรดทราบว่าหากอ่านความคิดเห็น!]


2
+1 สำหรับกลยุทธ์ 2. สาขาชั่วคราวที่แสดงสิ่งที่จะเกิดขึ้นเมื่อทำการผสาน กลยุทธ์ที่ 1 คือสิ่งที่ฉันพยายามหลีกเลี่ยงสำหรับกรณีนี้โดยเฉพาะ
Gordolio

2
ฉันขอแนะนำให้เปลี่ยนกลยุทธ์รอบ ๆ เพื่อให้ปลอดภัยกว่าเป็นอันดับแรก (การฝึกอบรมจิตของฉันมาถึง - คนส่วนใหญ่จะถือว่าตัวเลือกที่ดีที่สุดจะเป็นคนแรกแม้ว่าจะใช้คำว่า "ปลอดภัย" อย่างชัดเจน) แต่นอกเหนือจากนั้น งาน.
paxdiablo

6
คุณสามารถทำgit merge --no-ff --no-commitถ้าคุณไม่ต้องการยอมรับการเปลี่ยนแปลงโดยตรง สิ่งนี้ช่วยลด "ความต้องการ" สำหรับสาขาที่แตกต่างกันทำให้ง่ายขึ้นเล็กน้อยในการตรวจสอบการเปลี่ยนแปลง
เจอราร์ดแวนเฮลเดน

และถ้าคุณตัดสินใจว่าคุณไม่ต้องการที่จะผสานที่ทุกคนและในความเป็นจริงค่อนข้างจะเขียนโค้ดเพิ่มเติมบางส่วนและจากนั้นกระทำไปยังสาขาของคุณเพื่อให้คุณสามารถปรับใช้เพียงสาขาของคุณบนเซิร์ฟเวอร์ทดสอบจะไม่คุณยังคงต้องเป็นการเปลี่ยนgit merge --no-ff --no-commit? ฉันเดาว่าคุณยังสามารถทำอะไรได้git merge --abortหลังจากนั้นถ้าคุณไม่ชอบสิ่งที่คุณเห็น? แม้ว่าการผสานจะไม่ก่อให้เกิดความขัดแย้งหรือไม่?
Kasapo

คนส่วนใหญ่ชอบคัดลอกและวางและไม่คิดมาก ดังนั้นสำหรับยุทธศาสตร์ที่ 1 อาจจะยังเพิ่มวิธีการยกเลิกการผสานในสาขาในประเทศชั่วคราวgit reset --hard HEADแล้วชำระเงินเป็นสาขาที่แตกต่างกันและลบสาขาชั่วคราวgit checkout <different branch name> git delete -b <name of temporary branch>
user3613932

401
  • git log ..otherbranch
    • รายการการเปลี่ยนแปลงที่จะถูกรวมเข้ากับสาขาปัจจุบัน
  • git diff ...otherbranch
    • แตกต่างจากบรรพบุรุษทั่วไป (ผสานฐาน) ถึงส่วนหัวของสิ่งที่จะผสาน สังเกตจุดสามจุดที่มีความหมายพิเศษเมื่อเปรียบเทียบกับจุดสองจุด (ดูด้านล่าง)
  • gitk ...otherbranch
    • การแสดงกราฟิกของกิ่งไม้ตั้งแต่รวมเข้าด้วยกันครั้งที่แล้ว

สตริงที่ว่างเปล่าหมายถึงHEADเพื่อที่ว่าทำไมเพียงแทน..otherbranchHEAD..otherbranch

จุดสองจุดสามจุดมีความหมายแตกต่างกันเล็กน้อยสำหรับคำสั่งต่าง ๆ ที่แสดงรายการการแก้ไข (บันทึก gitk ฯลฯ ) สำหรับการเข้าสู่ระบบและอื่น ๆ จุดสองจุด ( a..b) หมายความว่าทุกอย่างที่อยู่ในbแต่ไม่aและจุดสามจุด ( a...b) หมายความว่าทุกอย่างที่อยู่ในเพียงหนึ่งหรือa bแต่ diff ใช้งานได้กับการแก้ไขสองครั้งและมีตัวพิมพ์ที่ง่ายกว่าสองจุด ( a..b) คือความแตกต่างอย่างง่ายจากaถึงbและสามจุด ( a...b) หมายถึงความแตกต่างระหว่างบรรพบุรุษทั่วไปและb( git diff $(git merge-base a b)..b)


7
จุดที่สามคือส่วนที่ฉันหายไปขอบคุณ! วิธีการบันทึกใช้งานได้ดีเช่นกัน log -p - .reverse ..otherbranch ดูเหมือนจะเป็นวิธีที่ดีในการดูว่าจะรวมอะไรเข้าบ้าง
Glenjamin

1
ฉันหายไปgit checkout masterก่อนที่จะลองสิ่งนี้ ฉันสงสัยว่าทำไมมันถึงบอกว่าการเปลี่ยนแปลงทั้งหมดของฉันกำลังจะถูกเขียนทับ ...
Droogans

5
git show ..otherbranchจะแสดงรายการการเปลี่ยนแปลงและความแตกต่างที่จะถูกรวมเข้ากับสาขาปัจจุบัน
Gaui

4
นี่ไม่แม่นยำอย่างสมบูรณ์โดยเฉพาะอย่างยิ่งสำหรับเชอร์รี่
void.pointer

2
@ void.pointer, คอมไพล์ไม่รักษาเชอร์รี่เลือกโดยเฉพาะในการรวมปกติจึงไม่ได้ที่นี่อย่างใดอย่างหนึ่ง สามารถเขียนกลยุทธ์การรวมที่จะ แต่เท่าที่ฉันรู้มันไม่เคยเป็น
Jan Hudec

19

svn update -nหากคุณชอบฉันคุณกำลังมองหาที่จะเทียบเท่า ต่อไปนี้ปรากฏขึ้นเพื่อทำการหลอกลวง โปรดทราบว่าให้ทำgit fetchก่อนเพื่อให้ repo ในพื้นที่ของคุณมีการอัพเดตที่เหมาะสมเพื่อเปรียบเทียบ

$ git fetch origin
$ git diff --name-status origin/master
D       TableAudit/Step0_DeleteOldFiles.sh
D       TableAudit/Step1_PopulateRawTableList.sh
A       manbuild/staff_companies.sql
M       update-all-slave-dbs.sh

หรือถ้าคุณต้องการความแตกต่างจากหัวของคุณถึงระยะไกล:

$ git fetch origin
$ git diff origin/master

IMO โซลูชันนี้ง่ายขึ้นและมีข้อผิดพลาดน้อยลง (และมีความเสี่ยงน้อยกว่า) กว่าโซลูชันระดับสูงที่เสนอ "ผสานแล้วยกเลิก"


1
ควรจะเป็น$ git checkout target-branchแล้ว$ git diff --name-status ...branch-to-be-merged(สามจุดที่มีความจำเป็นเพื่อให้พิมพ์เป็น)
Lu55

สิ่งหนึ่งที่ขาดหายไป: มันไม่แสดงให้คุณเห็นว่าไฟล์ใดที่จะมีความขัดแย้ง - ไฟล์เหล่านั้นมีเครื่องหมาย "M" เหมือนกับไฟล์ที่ถูกแก้ไขในสาขา แต่สามารถผสานได้โดยไม่มีข้อขัดแย้งใด ๆ
peterflynn

บางทีสิ่งต่าง ๆ อาจแตกต่างกันไปในปี 2012 แต่วันนี้การยกเลิกการผสานดูเหมือนจะค่อนข้างน่าเชื่อถือดังนั้นฉันไม่คิดว่ามันยุติธรรมที่จะอธิบายลักษณะนี้ว่า "ง่ายขึ้นและผิดพลาดน้อยกว่า" ในขณะนี้
David Z

8

คำตอบส่วนใหญ่ที่นี่ต้องใช้ไดเรกทอรีการทำงานที่สะอาดและหลายขั้นตอนแบบโต้ตอบ (ไม่ดีสำหรับการเขียนสคริปต์) หรือไม่ได้ผลสำหรับทุกกรณีเช่นการรวมที่ผ่านมาซึ่งนำการเปลี่ยนแปลงที่โดดเด่นบางอย่างมาสู่สาขาเป้าหมายของคุณ เหมือนกัน.

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

git merge-tree $(git merge-base master develop) master develop

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

git merge-tree $(git merge-base master develop) master develop | colordiff | less -R

- https://git.seveas.net/previewing-a-merge-result.html

(ขอบคุณ David Normington สำหรับลิงก์)

PS:

หากคุณจะได้รับความขัดแย้งผสานพวกเขาจะปรากฏขึ้นพร้อมเครื่องหมายความขัดแย้งตามปกติในผลลัพธ์เช่น:

$ git merge-tree $(git merge-base a b ) a b 
added in both
  our    100644 78981922613b2afb6025042ff6bd878ac1994e85 a
  their  100644 61780798228d17af2d34fce4cfbdf35556832472 a
@@ -1 +1,5 @@
+<<<<<<< .our
 a
+=======
+b
+>>>>>>> .their

User @dreftymac สร้างจุดที่ดี: สิ่งนี้ทำให้ไม่เหมาะสำหรับการเขียนสคริปต์เนื่องจากคุณไม่สามารถตรวจจับสิ่งนั้นได้จากรหัสสถานะ เครื่องหมายความขัดแย้งอาจแตกต่างกันมากขึ้นอยู่กับสถานการณ์ (ลบแล้วเทียบกับแก้ไข ฯลฯ ) ซึ่งทำให้ grep ยากเกินไปเช่นกัน ระวัง.


1
@hraban ดูเหมือนว่าคำตอบที่ถูกต้อง แต่ก็ยังมีองค์ประกอบที่ขาดหายไปหนึ่งรายการ วิธีการนี้ต้องการให้ผู้ใช้ "ลูกตา" เอาท์พุทเพื่อดูว่ามีเครื่องหมายข้อขัดแย้งอยู่หรือไม่ คุณมีวิธีการที่จะส่งคืนได้อย่างง่ายดายtrueหากมีข้อขัดแย้งและfalseหากไม่มีข้อขัดแย้ง (เช่นค่าบูลีนที่ไม่ต้องการการทดสอบ "ลูกตา" หรือการแทรกแซงของมนุษย์)
dreftymac

1
@dreftymac ไม่พบสิ่งใดที่มีผลกระทบนั้น คุณสามารถใช้สิ่งที่ชอบgit merge-tree ... | grep -q '^[a-z].*in both$' && echo conflict || echo safe to mergeแต่มันฟินนิคกี้; ฉันอาจจะลืมกรณี บางทีคุณต้องการตรวจสอบเครื่องหมายข้อขัดแย้งแทน เช่นนี้อาจจะไม่จับ "สไตล์ของพวกเขาถูกลบความขัดแย้งของสไตล์ของเราเปลี่ยนไป" (ฉันเพิ่งตรวจสอบและที่ไม่ได้แสดงเครื่องหมายความขัดแย้งดังนั้นคุณต้อง regex อย่างพิถีพิถันเพื่อความปลอดภัยที่นี่)
38945

1
ใช้less -Rเพื่อจัดการเอาต์พุตสีโดยไม่แก้ไขการกำหนดค่าของคุณ
Giacomo Alzetta

ขอบคุณ @GiacomoAlzetta ฉันได้ทำการอัพเดทแล้ว
hraban

6

หากคุณได้ทำการเปลี่ยนแปลงแล้วรายการโปรดของฉันคือ:

git log ...@{u}

ต้องมี git 1.7.x ผมเชื่อว่า @{u}สัญกรณ์คือ "ชวเลข" สำหรับสาขาต้นน้ำดังนั้นจึงเป็นเรื่องเล็ก ๆ น้อย ๆ git log ...origin/masterอีกหลากหลายกว่า

หมายเหตุ: ถ้าคุณใช้ zsh และสิ่งที่ขยายออกไปอย่างต่อเนื่องคุณอาจต้องทำสิ่งต่อไปนี้:

git log ...@\{u\}

6

การเพิ่มคำตอบที่มีอยู่สามารถสร้างนามแฝงเพื่อแสดง diff และ / หรือบันทึกก่อนทำการผสาน คำตอบจำนวนมากละเว้นสิ่งfetchที่ต้องทำก่อนก่อน "ดูตัวอย่าง" การรวม; นี่คือนามแฝงที่รวมสองขั้นตอนนี้ไว้ในที่เดียว (เลียนแบบสิ่งที่คล้ายกับ Mercurial's hg incoming/outgoing )

ดังนั้นการสร้าง " git log ..otherbranch" คุณสามารถเพิ่มสิ่งต่อไปนี้ลงใน~/.gitconfig:

...
[alias]
    # fetch and show what would be merged (use option "-p" to see patch)
    incoming = "!git remote update -p; git log ..@{u}"

สำหรับสมมาตรสามารถใช้นามแฝงต่อไปนี้เพื่อแสดงสิ่งที่ได้ทำไว้และจะถูกผลักก่อนที่จะกด:

    # what would be pushed (currently committed)
    outgoing = log @{u}..

จากนั้นคุณสามารถเรียกใช้ " git incoming" เพื่อแสดงการเปลี่ยนแปลงจำนวนมากหรือ " git incoming -p" เพื่อแสดงแพตช์ (เช่น "ดิฟ"), " git incoming --pretty=oneline", สำหรับการสรุปแบบสั้น ๆ เป็นต้นคุณสามารถรัน (เป็นทางเลือก) "git pull " เพื่อ จริง ๆ แล้วผสาน (แม้ว่าเมื่อคุณได้รับแล้วการรวมสามารถทำได้โดยตรง)

เช่นกัน " git outgoing" แสดงสิ่งที่จะถูกผลักถ้าคุณต้องเรียกใช้ " git push"


3

git log currentbranch..otherbranchจะให้รายการการกระทำที่จะเข้าสู่สาขาปัจจุบันหากคุณทำการรวม ข้อโต้แย้งตามปกติในการเข้าสู่ระบบซึ่งให้รายละเอียดเกี่ยวกับการกระทำจะให้ข้อมูลเพิ่มเติมกับคุณ

git diff currentbranch otherbranchจะให้ความแตกต่างระหว่างการกระทำทั้งสองที่จะกลายเป็นหนึ่ง นี่จะเป็นความแตกต่างที่ให้ทุกสิ่งที่คุณจะได้รับการผสาน

สิ่งเหล่านี้จะช่วยได้ไหม


2
จริงๆแล้วผิด git log otherbranch..currentbranchจะช่วยให้รายการกระทำในcurrentbranch สิ่งที่git diff otherbranch currentbranchให้คุณแตกต่างจากเวอร์ชันที่จะผสานกับเคล็ดลับปัจจุบันซึ่งเป็นเรื่องที่ไร้ประโยชน์เท่าที่จะเป็นไปได้เพราะสิ่งที่คุณต้องการแตกต่างจากฐานผสานถึงส่วนหัวผสาน
Jan Hudec

ขอบคุณ ฉันเปลี่ยนชื่อของต้นไม้
Noufal Ibrahim

3

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


2

ขาดการรวมตัวกันในแบบที่โยนทิ้ง (ดูคำตอบของ Kasapo) ดูเหมือนจะไม่มีวิธีที่เชื่อถือได้ในการเห็นสิ่งนี้

ต้องบอกว่านี่เป็นวิธีที่เข้าใกล้:

git log TARGET_BRANCH...SOURCE_BRANCH --cherry

สิ่งนี้ให้การบ่งชี้ที่เป็นธรรมซึ่งความมุ่งมั่นจะทำให้เป็นการรวมเข้าด้วยกัน หากต้องการดู diffs -pเพิ่ม หากต้องการดูชื่อไฟล์เพิ่มใด ๆ ของ--raw, --stat, --name-only,--name-status ,

ปัญหาเกี่ยวกับgit diff TARGET_BRANCH...SOURCE_BRANCHวิธีการ (ดูคำตอบของ Jan Hudec) คือคุณจะเห็นความแตกต่างสำหรับการเปลี่ยนแปลงในสาขาเป้าหมายของคุณแล้วหากสาขาต้นทางของคุณมีการผสานข้าม


1

บางทีนี่อาจช่วยคุณได้ git-diff-tree - เปรียบเทียบเนื้อหาและโหมดของ blobs ที่พบผ่านวัตถุต้นไม้สองต้น


1

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

นี่คือวิธีแก้ปัญหาของฉันในกรณีที่ช่วยคนอื่นออกไปที่นั่น:

ในสถานการณ์นี้ฉันมีสาขาที่เรียกว่า QA ที่มีการเปลี่ยนแปลงมากมายตั้งแต่การผลิตครั้งล่าสุด การผลิตครั้งล่าสุดของเราถูกติดแท็กด้วย "15.20.1" ฉันมีสาขาการพัฒนาอื่นที่เรียกว่า new_stuff ที่ฉันต้องการรวมเข้ากับสาขา QA ทั้ง QA และ new_stuff ชี้ให้ยอมรับว่า "ติดตาม" (ตามที่รายงานโดย gitk) แท็ก 15.20.1

git checkout QA
git pull
git diff 15.20.1 --name-only > QA_files
git checkout new_stuff
git pull
git diff 15.20.1 --name-only > new_stuff_files
comm -12 QA_files new_stuff_files

นี่คือการสนทนาบางอย่างที่ทำให้ฉันสนใจในการกำหนดเป้าหมายไฟล์เฉพาะเหล่านี้:

ฉันจะเชื่อถือการผสาน Git ได้อย่างไร

/software/199780/how-far-do-you-trust-automerge

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