มีตัวเลือก git-merge --dry-run หรือไม่


725

ฉันกำลังรวมในสาขาระยะไกลที่อาจมีความขัดแย้งมากมาย ฉันจะบอกได้อย่างไรว่ามันจะมีความขัดแย้งหรือไม่?

ฉันไม่เห็นอะไรเหมือนใน --dry-rungit-merge


5
เนื่องจากการแตกแขนงนั้นถูกกับ Git ทำไมไม่ลองเช็กเอาต์จากนั้นคุณไม่จำเป็นต้องทำแบบแห้ง คุณสามารถทิ้งสำเนาได้ในภายหลัง
Alexander Mills

คำตอบ:


812

ตามที่ระบุไว้ก่อนหน้านี้ผ่านในการ--no-commitตั้งค่าสถานะ แต่เพื่อหลีกเลี่ยงการส่งต่อที่รวดเร็วส่งต่อ--no-ffเช่นกันเช่น:

$ git merge --no-commit --no-ff $BRANCH

หากต้องการตรวจสอบการเปลี่ยนแปลงที่มีการจัดฉาก:

$ git diff --cached

และคุณสามารถยกเลิกการผสานได้แม้ว่าจะเป็นการผสานแบบกรอไปข้างหน้า:

$ git merge --abort

51
สิ่งนี้ยอดเยี่ยม แต่จะยังคงแก้ไขสำเนาการทำงานของคุณ หาก repo ของคุณเป็นเว็บเซิร์ฟเวอร์สดคุณสามารถแสดงไฟล์ที่มีข้อขัดแย้งได้
dave1010

21
คุณไม่สามารถทำการผสานโดยไม่ส่งผลกระทบต่อสำเนาการทำงาน
mipadi

55
จริง แต่สิ่งที่ชอบgit merge --only-if-there-wont-be-any-conflictsหรือgit diff --show-conflicts <commit>จะเป็นประโยชน์จริงๆ ความอัปยศมันเป็นไปไม่ได้เลยหรือฉันขาดอะไรไป
dave1010

344
@ dave1010 คุณไม่ควรจัดการกับการรวมตัวกันบนเว็บเซิร์ฟเวอร์สด !!! นั่นคือสิ่งที่กล่องการพัฒนาของคุณมีไว้สำหรับ! แก้ไขสาขา "แยง" จากนั้นดันไปยังเว็บเซิร์ฟเวอร์จริง
jpswain

52
หากคุณทำงานบนเซิร์ฟเวอร์จริง / ที่ใช้งานจริงคุณไม่ต้องการทำอะไรนอกจากgit pull --ff-only!
ThiefMaster

237

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

  1. ดึงรีโมตไปยังที่เก็บของคุณ ตัวอย่างเช่น: git fetch origin master
  2. เรียกใช้คอมไพล์ผสานฐาน: git merge-base FETCH_HEAD master
  3. เรียกใช้ git merge-tree: git merge-tree mergebase master FETCH_HEAD( mergebaseเป็นเลขฐานสิบหกที่ผสานฐานพิมพ์ในขั้นตอนก่อนหน้า)

ตอนนี้สมมติว่าคุณต้องการผสานรวมต้นแบบระยะไกลกับเจ้านายท้องถิ่นของคุณ แต่คุณสามารถใช้สาขาใดก็ได้ git merge-treeจะดำเนินการผสานในหน่วยความจำและพิมพ์ผลลัพธ์ไปยังเอาต์พุตมาตรฐาน grep สำหรับรูปแบบหรือ<< >>หรือคุณสามารถพิมพ์ผลลัพธ์ไปยังไฟล์และตรวจสอบว่า หากคุณพบว่าบรรทัดที่ขึ้นต้นด้วย 'เปลี่ยนแปลงทั้งคู่' ส่วนใหญ่อาจมีข้อขัดแย้ง


41
คำตอบนี้เป็นวิธีที่ต่ำกว่ามาตรฐาน IMHO เนื่องจากเป็นโซลูชันที่สะอาดโดยไม่ต้องสัมผัสสำเนาหรือดัชนี
sschuberth

23
BTW, ขั้นตอนที่ 2 และ 3 สามารถรวมกันเป็นขั้นตอนเดียวโดยใช้ตัวดำเนินการ backtick ของคอนโซล Linux ซึ่งประเมินเนื้อหาในตำแหน่ง:git merge-tree `git merge-base FETCH_HEAD master` FETCH_HEAD master
jakub.g

15
เพิ่มไปที่ [alias] ใน. gitconfig: dry = "! f () {git merge-tree` git merge-base $ 2 $ 1` $ 2 $ 1;}; f "# ตรวจสอบว่าการรวม dev เข้าสู่ master จะเป็นอย่างไร: git dry dev master
Noel

8
บรรทัด FIT GIT ใหม่ของฉัน: ยอดเยี่ยมgit merge-tree `git merge-base clieop master` clieop master | grep -A3 "changed in both"มาก! +100
Rudie

4
ในการทดสอบนี้ฉันพบว่าการ grepping สำหรับ 'เปลี่ยนแปลงใน' ทั้งสองรวมสถานะที่ทั้งสองสาขาแก้ไขไฟล์เดียวกันแม้ว่าพวกเขาจะไม่ส่งผลให้เกิดความขัดแย้งผสาน ในการระบุความขัดแย้งที่เกิดขึ้นจริงฉันพบว่าจำเป็นต้อง grep สำหรับมาร์กอัปความขัดแย้งที่เริ่มต้นเช่นนี้: +<<<<<<< .ourดังนั้นฉันจึงใช้นิพจน์ grep เช่นgrep -q '^+<* \.our$'
Guy

55

วิธีเดรัจฉานบังคับง่าย ๆ ของฉันคือ:

  1. สร้างสาขา "pre-master" (จากหลักสูตรหลัก)

  2. ผสานทุกสิ่งที่คุณต้องการเข้าร่วมปรมาจารย์
    จากนั้นคุณจะเห็นว่าการผสานเกิดขึ้นอย่างไรโดยไม่ต้องแตะต้องต้นแบบ

    • รวม pre-master เข้ากับ master หรือ
    • รวมสาขาที่ปล่อยออกมาทั้งหมดเข้าไว้ด้วยกัน

อย่างไรก็ตามฉันจะปฏิบัติตามคำแนะนำของ @ orange80


5
ฉันชอบ @akostajti solution แต่นี่เป็นอีกตัวเลือกที่ประเมินราคาต่ำกว่า ในความเป็นจริงฉันชอบที่จะป้องกันและสร้างสาขาชั่วคราว (แน่นอนเมื่อฉันคาดหวังว่าจะมีความขัดแย้งไม่เช่นนั้นจะเป็นการ overkill) และหากมีสิ่งผิดปกติให้ลบออก
jakub.g

1
dunno หากนี่เป็นวิธี "สกปรก" หรือไม่ แต่มันทำงานได้จริง ๆ ฉันชอบมัน! (Y)
sara

3
นี่ควรเป็นทางออกที่ยอมรับได้ มันรวดเร็วง่ายปลอดภัยย้อนกลับใช้งานง่ายและตราบใดที่ไม่มีการเปลี่ยนแปลงที่ไม่เป็นธรรมก่อนที่คุณจะเริ่มมันจะไม่มีผลข้างเคียง
Bob Ray

3
วิธีแก้ปัญหานี้บอกให้คุณไม่เข้าใจว่าคอมไพล์ทำงานอย่างไร สาขาเป็นเพียงพอยน์เตอร์และคุณสร้างตัวชี้ซ้ำซ้อนเท่านั้น คุณมีความรู้สึกไม่ดีที่จะทำร้ายสาขาของคุณ แต่คุณทำไม่ได้ คุณก็สามารถทำได้git merge --abortหากมีความขัดแย้งถ้ามีการผสานหรือgit reset --hard HEAD~1 git reset --hard origin/masterการสร้างสาขาอื่นให้ความรู้สึกปลอดภัย แต่ถ้าคุณเรียนรู้วิธีการใช้งานคอมไพล์คุณจะเข้าใจว่ามันคือความกลัวที่ถูกวางผิดที่ เมื่อมีข้อกังวลเกี่ยวกับการไม่เปลี่ยนสำเนาการทำงานสิ่งนี้ไม่ได้แก้ปัญหา
Thibault D.

@ thibault-d ลองคิดดูว่าโซลูชั่นซับซ้อนแค่ไหนเมื่อคุณไม่ได้เริ่มต้นด้วยสาขาที่สะอาด git merge --no-commitจะไม่ยกเลิกการรวมหากสามารถส่งต่อได้อย่างรวดเร็ว git merge --abortไม่ทำงานหากรวมเข้าด้วยกัน หากคุณต้องการเขียนสิ่งนี้เป็นสคริปต์มันน่าอึดอัดใจเนื่องจากgit mergeไม่ตอบกลับด้วยรหัสข้อผิดพลาดที่ดีพอที่จะอธิบายความขัดแย้งประเภทต่างๆ การทำงานกับสาขาใหม่จะทำให้สคริปต์ที่ใช้งานไม่ได้ปล่อยให้ repo ของคุณอยู่ในสถานะที่ต้องการการแทรกแซงด้วยตนเอง แน่นอนว่าคุณจะไม่สูญเสียอะไรเลย แต่มันจะง่ายกว่าที่จะสร้างเป็นอย่างอื่น
Erik Aronesty

47

การยกเลิกการรวมกับคอมไพล์นั้นง่ายมากคุณไม่ควรกังวลเกี่ยวกับการทำแห้ง:

$ git pull $REMOTE $BRANCH
# uh oh, that wasn't right
$ git reset --hard ORIG_HEAD
# all is right with the world

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


7
เพียงแค่ตรวจสอบว่าการผสานจะเป็นกรอไปข้างหน้า (FF) เป็นเรื่องของการตรวจสอบรายชื่อgit branch --contains HEADหรือมากกว่านั้นโดยตรงให้ใช้git merge --ff-only
Brian Phillips

7
git reset - ฮาร์ดเป็นหนึ่งในคำสั่งการลบข้อมูลไม่กี่แบ็คเอาต์ที่ git มีอยู่ดังนั้นควรใช้ด้วยความระมัดระวังอย่างยิ่ง เช่นนี้ -1
Kzqai

8
@Tchalvak ยังคงมีการอ้างอิงอยู่
Kissaki

3
--dry-runจะไม่ "เพียงตรวจสอบว่าการผสานจะส่งต่ออย่างรวดเร็ว" หรือไม่ มันจะส่งกลับผลลัพธ์ที่แน่นอนว่าการผสานจะ: ไฟล์ความขัดแย้งเป็นต้นว่า ff จะไม่น่าสนใจจริง ๆ หรือไม่
Rudie

3
แล้วไงgit stash; git reset --hardล่ะ @BrianPhillips
รหัส Whisperer

41

ฉันทำนามแฝงสำหรับการทำเช่นนี้และทำงานเหมือนมีเสน่ห์ฉันทำสิ่งนี้:

 git config --global alias.mergetest '!f(){ git merge --no-commit --no-ff "$1"; git merge --abort; echo "Merge aborted"; };f '

ตอนนี้ฉันแค่โทร

git mergetest <branchname>

เพื่อตรวจสอบว่ามีข้อขัดแย้งใด ๆ หรือไม่


ยอดเยี่ยม! ฉันเก็บมันไว้
qbert65536

28

เพียงแค่แตกสาขาปัจจุบันของคุณกับสาขาระยะไกลนี่จะบอกคุณว่าจะมีการเปลี่ยนแปลงอะไรเมื่อคุณดึง / รวม

#see diff between current master and remote branch
git diff master origin/master

1
ความคิดที่น่าสนใจ ฉันจะดูผลลัพธ์นั้นและพิจารณาว่าการผสานจะทำงานได้หรือไม่
MatrixFrog

6
สิ่งนี้จะไม่บอกคุณว่ามีข้อขัดแย้งใด ๆ เกิดขึ้นหรือไม่ แต่มันจะให้ความคิดทั่วไปเกี่ยวกับสิ่งที่จะเกิดขึ้นหากคุณดึง / ผสาน
timh

10
นี่จะบอกความแตกต่างระหว่างสองสาขาเท่านั้นมันจะไม่บอกคุณว่าผลลัพธ์ของการรวมจะเป็นอย่างไร นี่คือความแตกต่างที่สำคัญเนื่องจากการรวมในบางกรณีจะทำการเปลี่ยนแปลงจากสาขาที่แตกต่างกันโดยอัตโนมัติขึ้นอยู่กับว่าพวกเขามีความมุ่งมั่นเมื่อใด ดังนั้นโดยพื้นฐานแล้วการทำ diff อาจทำให้คุณคิดว่าการเปลี่ยนแปลงบางอย่างของคุณจะถูกเปลี่ยนกลับเมื่อเป็นจริงกระบวนการผสานจะทำการเปลี่ยนแปลงใหม่กว่าแบบเก่าโดยอัตโนมัติ หวังว่ามันสมเหตุสมผล
markquezada

3
หากต้องการสร้างความคิดเห็นของ @ mirthlab จะมีความแตกต่างอย่างมีนัยสำคัญระหว่าง diff และ merge ถ้าใครบางคนเคยทำการผสานกับกลยุทธ์การผสาน "ours" (หรือบางโปรแกรมแก้ไขการผสานแบบแมนนวล) ส่วนต่างจะแสดงให้คุณเห็นถึงความแตกต่างซึ่งนับเป็น "ผสานแล้ว"
เทาร

21

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

ตัวอย่างเช่นสมมติว่าคุณต้องการรวมสาขาที่ชื่อ "feature-x" เข้ากับสาขาหลักของคุณ

git request-pull master origin feature-x

จะแสดงบทสรุปของสิ่งที่จะเกิดขึ้น (โดยไม่ทำอะไรเลย):

The following changes since commit fc01dde318:
    Layout updates (2015-06-25 11:00:47 +0200)
are available in the git repository at:
    http://fakeurl.com/myrepo.git/ feature-x
for you to fetch changes up to 841d3b41ad:
----------------------------------------------------------------
john (2):
    Adding some layout
    Refactoring
ioserver.js            |   8 +++---
package.json           |   7 +++++-
server.js              |   4 +--
layout/ldkdsd.js       | 277 +++++++++++++++++++++++++++++++++++++
4 files changed, 289 insertions(+), 7 deletions(-)
create mode 100644 layout/ldkdsd.js

หากคุณเพิ่ม-pพารามิเตอร์คุณจะได้รับข้อความแพตช์แบบเต็มเหมือนกับว่าคุณกำลังทำคอมไพล์ในทุกไฟล์ที่เปลี่ยนแปลง


3
คุณสามารถทำให้สิ่งนี้ชัดเจนขึ้นเล็กน้อยโดยการเพิ่มอะไรmasterและoriginทำในตัวเลือกบรรทัดคำสั่งและถ้าฉันเป็นตัวอย่างในท้องถิ่นbranch1และต้องการที่จะทำrequest-pullในสาขาคุณลักษณะท้องถิ่นbranch2? ฉันยังต้องการoriginหรือไม่ แน่นอนหนึ่งสามารถอ่านเอกสารได้เสมอ
Ela782

น่าเศร้าคำสั่งนี้ใช้งานได้เฉพาะถ้า Rev # 2 เป็นชื่อสาขามันไม่ทำงานสำหรับแฮช: /
Jared Grubb

20

ฉันประหลาดใจที่ไม่มีใครแนะนำให้ใช้แพทช์

สมมติว่าคุณต้องการทดสอบการรวมyour_branchเข้าmaster(ฉันสมมติว่าคุณได้masterเช็คเอาต์):

$ git diff master your_branch > your_branch.patch
$ git apply --check your_branch.patch
$ rm your_branch.patch

นั่นควรทำเคล็ดลับ

หากคุณได้รับข้อผิดพลาดเช่น

error: patch failed: test.txt:1
error: test.txt: patch does not apply

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


โปรดทราบว่านี่จะไม่เปลี่ยนแผนผังการทำงานของคุณ (นอกเหนือจากการสร้างไฟล์แพทช์แน่นอน แต่คุณสามารถลบได้อย่างปลอดภัยในภายหลัง) จากเอกสารประกอบการใช้ git:

--check
    Instead of applying the patch, see if the patch is applicable to the
    current working tree and/or the index file and detects errors. Turns
    off "apply".

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


วิธีนี้เป็นคำตอบที่ได้รับการยอมรับสำหรับคำถามนี้และมีข้อสังเกตบางประการในความคิดเห็นเช่น "git ไม่สามารถใช้กลยุทธ์การรวมแบบเรียกซ้ำ" และ "ไฟล์แก้ไขให้ข้อผิดพลาดสำหรับไฟล์ใหม่" มิฉะนั้นก็ดูดี
neno

1
git diff master your_branch | git apply --checkวิธีที่สั้นลงโดยไม่ต้องสร้างไฟล์แพทช์ชั่วคราว:
ks1322

9

สิ่งนี้อาจน่าสนใจ: จากเอกสาร:

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

แต่คุณสามารถทำได้ด้วยวิธีที่ไร้เดียงสา (แต่ช้า):

rm -Rf /tmp/repository
cp -r repository /tmp/
cd /tmp/repository
git merge ...
...if successful, do the real merge. :)

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


2
ถ้าสิ่งที่คุณต้องการคือค้อน ... :) +1
kaiser

สำเนาสะอาดสามารถรับกับcp -r repository/.git /tmp/repository/.git, cd /tmp/repository, git reset --hard, git add --all, git reset --hard(การวัดที่ดี) git status(เพื่อตรวจสอบว่ามันเป็นที่สะอาด)
ADTC

8

ฉันรู้ว่านี่เป็นคำถามเก่า แต่เป็นคำถามแรกที่ปรากฏในการค้นหาของ Google

Git แนะนำตัวเลือก --ff-only เมื่อทำการผสาน

จาก: http://git-scm.com/docs/git-merge


--ff เท่านั้น

ปฏิเสธที่จะรวมและออกด้วยสถานะที่ไม่ใช่ศูนย์เว้นแต่ว่า HEAD ปัจจุบันนั้นทันสมัยอยู่แล้วหรือการผสานนั้นสามารถแก้ไขได้อย่างรวดเร็ว

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

git pull --ff-only origin branchA #See if you can pull down and merge branchA

git merge --ff-only branchA branchB #See if you can merge branchA into branchB

1
นั่นจะทำการผสานหากสามารถทำได้ด้วยการกรอไปข้างหน้าซึ่งไม่ใช่สิ่งที่ฉันต้องการในคำถามดั้งเดิม ฉันคิดว่าคำตอบที่ยอมรับมีอีกครึ่งหนึ่งที่แก้ไขได้
อ็อตโต

แม้ว่าที่จริงแล้วคอมไพล์แฟนซีแจ้งให้ขจัดความต้องการที่ฉันมีให้กับเรื่องแบบนี้
อ็อตโต

2
มันไม่เหมือนกันจริงๆ ออกจากที่มีไม่ใช่ศูนย์สถานะเพราะผสานไม่สามารถแก้ไขได้อย่างรวดเร็วไปข้างหน้าไม่ได้หมายความว่ามีความขัดแย้ง มันหมายถึงประวัติศาสตร์ได้แยกจากกันและความมุ่งมั่นผสานเป็นสิ่งที่จำเป็น
ADTC

7

ฉันใช้บันทึก git เพื่อดูว่ามีการเปลี่ยนแปลงอะไรในสาขาฟีเจอร์จากสาขาหลัก

git log does_this_branch..contain_this_branch_changes

เช่น - เพื่อดูว่าคอมมิชชันใดอยู่ในฟีเจอร์แบรนช์ที่มี / ไม่ถูกรวมเข้ากับมาสเตอร์:

git log master..feature_branch

3

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


2

ทางออกของฉันคือการรวมถอยหลัง

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

git checkout my-branch
git merge origin/target-branch

คุณจะเห็นว่ามีข้อขัดแย้งใด ๆ หรือไม่และสามารถวางแผนเกี่ยวกับวิธีแก้ไขได้

หลังจากนั้นคุณสามารถยกเลิกการผสานผ่านทางคอมไพล์merge --abortหรือ (หากไม่มีข้อขัดแย้งและการผสานเกิดขึ้น) ย้อนกลับไปยังคอมมิชชันก่อนหน้าผ่านgit reset --hard HEAD~1


-2

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

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