เครื่องมือง่ายๆที่จะ 'ยอมรับพวกเขา' หรือ 'ยอมรับของฉัน' บนไฟล์ทั้งหมดโดยใช้ git


399

ฉันไม่ต้องการเครื่องมือการผสานภาพและฉันไม่ต้องการให้ vi ไฟล์ที่ขัดแย้งกันและเลือกระหว่าง HEAD (เหมือง) และการเปลี่ยนแปลงที่นำเข้า (ด้วยตนเอง) ด้วยตนเอง ส่วนใหญ่ฉันต้องการการเปลี่ยนแปลงทั้งหมดหรือทั้งหมดของฉัน โดยทั่วไปนี่เป็นเพราะการเปลี่ยนแปลงของฉันทำให้มันดูดีและกลับมาหาฉันผ่านการดึง แต่อาจมีการปรับเปลี่ยนเล็กน้อยในที่ต่างๆ

มีเครื่องมือบรรทัดคำสั่งที่จะกำจัดเครื่องหมายความขัดแย้งและเลือกทุกทางหรือวิธีอื่นตามที่ฉันเลือก? หรือชุดของคำสั่ง git ที่ฉันสามารถนามแฝงตัวเองที่จะทำแต่ละคน

# accept mine
alias am="some_sequence;of;commands"
alias at="some_other_sequence;of;commands"

การทำเช่นนี้ค่อนข้างน่ารำคาญ สำหรับ 'accept mine' ฉันได้ลองแล้ว:

randy@sabotage ~/linus $ git merge test-branch
Auto-merging Makefile
CONFLICT (content): Merge conflict in Makefile
Automatic merge failed; fix conflicts and then commit the result.

randy@sabotage ~/linus $ git checkout Makefile 
error: path 'Makefile' is unmerged

andy@sabotage ~/linus $ git reset --hard HEAD Makefile 
fatal: Cannot do hard reset with paths.

ฉันควรกำจัดเครื่องหมายการเปลี่ยนแปลงเหล่านี้ได้อย่างไร

ที่ฉันสามารถทำได้:

git reset HEAD Makefile; rm Makefile; git checkout Makefile

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

การไปทางอื่นการทำ 'ยอมรับของพวกเขา' นั้นไม่เป็นระเบียบ วิธีเดียวที่ฉันจะเข้าใจได้ก็คือ:

git show test-branch:Makefile > Makefile; git add Makefile;

สิ่งนี้ทำให้ฉันมีข้อความคอมมิทที่ยุ่งเหยิงซึ่งมี Conflicts: Makefile อยู่สองครั้ง

ใครช่วยกรุณาชี้ให้เห็นวิธีการกระทำสองอย่างข้างต้นในวิธีที่ง่ายกว่า? ขอบคุณ


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

คำตอบ:


602

การแก้ปัญหาง่ายมาก git checkout <filename>พยายามที่จะตรวจสอบไฟล์จากดัชนีและดังนั้นจึงล้มเหลวในการผสาน

สิ่งที่คุณต้องทำคือ (ชำระเงินการกระทำ ):

หากต้องการชำระเงินเวอร์ชันของคุณเองคุณสามารถใช้หนึ่งใน:

git checkout HEAD -- <filename>

หรือ

git checkout --ours -- <filename>

หรือ

git show :2:<filename> > <filename> # (stage 2 is ours)

หากต้องการชำระเงินรุ่นอื่นคุณสามารถใช้หนึ่งใน:

git checkout test-branch -- <filename>

หรือ

git checkout --theirs -- <filename>

หรือ

git show :3:<filename> > <filename> # (stage 3 is theirs)

คุณจะต้องเรียกใช้ 'เพิ่ม' เพื่อทำเครื่องหมายว่าแก้ไขแล้ว:

git add <filename>

31
ผมพบว่ามันเป็นบิตแปลกที่--oursและ--theirsวิธีการตรงข้ามของสิ่งที่ฉันสังหรณ์ใจคิดว่าเมื่อพยายามออกคำสั่งนี้ ...
โจชัว Muheim

6
ระวังเมื่อใช้git show- สิ่งนี้จะข้ามการขึ้นบรรทัดใหม่
Chronial

2
นี่เป็นสิ่งที่ดีสำหรับไฟล์บางไฟล์ แต่เมื่อคุณมีไฟล์หลายไฟล์ที่ขัดแย้งกัน (เนื่องจากวันที่ในความคิดเห็นเปลี่ยนไป!) คุณจะทำอย่างไร
JhovaniC

4
@Santos: --ใช้โดย Git เพื่อแยกการแก้ไข (ชื่อสาขา ฯลฯ ) จากชื่อพา ธ (ชื่อไฟล์, ไดเรกทอรี) เป็นสิ่งสำคัญหาก Git ไม่สามารถตัดสินใจได้ว่าชื่อเป็นชื่อของสาขาหรือชื่อของไฟล์ นี่เป็นไปตามระเบียบ POSIX (หรือ GNU) ของการใช้เครื่องหมายขีดกลางคู่เพื่อแยกตัวเลือกจากอาร์กิวเมนต์ (ชื่อไฟล์)
Jakub Narębski

3
@Sammaron @Joshua Muheim; theirs/ oursสามารถปรากฏสลับถ้าคุณจะแก้ปัญหาความขัดแย้งในบริบทของการดำเนินงาน rebase ที่ เนื่องจากการรีบูตใช้งานได้โดยการตรวจสอบสาขาเป้าหมายดังนั้นการเลือกเชอร์รี่จากสาขา "ของคุณ" ไปยังเป้าหมายการเปลี่ยนแปลงที่เข้ามา ("พวกเขา") มาจากสาขา "ของคุณ" และสาขาปัจจุบันคือสาขาเป้าหมาย ("ของเรา" )
RJFalconer

93

ลองสิ่งนี้:

วิธียอมรับการเปลี่ยนแปลง: git merge --strategy-option theirs

วิธียอมรับของคุณ: git merge --strategy-option ours


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

3
และคุณสามารถใช้สิ่งนี้สำหรับคำสั่งผสานอื่น ๆ เช่น cherry-pick และ rebase
idbrii

50

จากคำตอบของจาคุบคุณสามารถกำหนดค่านามแฝงต่อไปนี้เพื่อความสะดวก:

accept-ours = "!f() { git checkout --ours -- \"${@:-.}\"; git add -u \"${@:-.}\"; }; f"
accept-theirs = "!f() { git checkout --theirs -- \"${@:-.}\"; git add -u \"${@:-.}\"; }; f"

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

เพิ่มลงใน[alias]ส่วนของคุณ~/.gitconfigหรือเรียกใช้

git config --global alias.accept-ours '!f() { git checkout --ours -- "${@:-.}"; git add -u "${@:-.}"; }; f'
git config --global alias.accept-theirs '!f() { git checkout --theirs -- "${@:-.}"; git add -u "${@:-.}"; }; f'

1
ไม่ทำงานสำหรับฉัน ... เหล่านี้มีไว้สำหรับทุบตีหรือเปลือกอื่น ๆ ?
456584

เหล่านี้เป็นนามแฝงคอมไพล์เพิ่มใน[alias]ส่วนของคุณในการใช้งานหรือ~.gitconfig git config --global accept-ours "..."แก้ไขคำตอบของฉันแล้ว
kynan

2
คุณไม่มีความคิดว่านามแฝงนี้จะช่วยฉันได้นานแค่ไหน ยกนิ้ว!
Adam Parkin

1
@hakre ตรวจสอบให้แน่ใจว่าคุณอ้างนามแฝงไม่เช่นนั้นเชลล์ของคุณจะพยายามตีความมัน ~/.gitconfigหรือเพียงแค่การแก้ไขด้วยตนเองของคุณ
kynan

1
ไวยากรณ์ของเชลล์สำหรับค่าเริ่มต้น:!f() { git checkout --ours -- "${@:-.}" git add -u "${@:-.}; }; f
jthill

17

ตามคำตอบของ kynan นี่คือนามแฝงเดียวกันซึ่งถูกแก้ไขเพื่อให้สามารถจัดการช่องว่างและเครื่องหมายขีดกลางเริ่มต้นในชื่อไฟล์:

accept-ours = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --ours -- \"$@\"; git add -u -- \"$@\"; }; f"
accept-theirs = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --theirs -- \"$@\"; git add -u -- \"$@\"; }; f"

0

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

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

ในการจัดการกับสถานการณ์ทั้งสามนี้คุณสามารถเพิ่มบรรทัดต่อไปนี้ใน.gitconfigไฟล์ของคุณ(หรือเทียบเท่า):

[merge]
  conflictstyle = diff3
[mergetool.getours]
  cmd = git-checkout --ours ${MERGED}
  trustExitCode = true
[mergetool.mergeours]
  cmd = git-merge-file --ours ${LOCAL} ${BASE} ${REMOTE} -p > ${MERGED}
  trustExitCode = true
[mergetool.keepours]
  cmd = sed -I '' -e '/^<<<<<<</d' -e '/^|||||||/,/^>>>>>>>/d' ${MERGED}
  trustExitCode = true
[mergetool.gettheirs]
  cmd = git-checkout --theirs ${MERGED}
  trustExitCode = true
[mergetool.mergetheirs]
  cmd = git-merge-file --theirs ${LOCAL} ${BASE} ${REMOTE} -p > ${MERGED}
  trustExitCode = true
[mergetool.keeptheirs]
  cmd = sed -I '' -e '/^<<<<<<</,/^=======/d' -e '/^>>>>>>>/d' ${MERGED}
  trustExitCode = true

get(ours|theirs)เครื่องมือเพียงแค่ช่วยให้รุ่นตามลำดับของไฟล์และพ่นออกทั้งหมดของการเปลี่ยนแปลงจากรุ่นอื่น ๆ (จึงไม่มีการควบรวมเกิดขึ้น)

merge(ours|theirs)เครื่องมือใหม่ไม่ผสานวิธีที่สามจากท้องถิ่นฐานและรุ่นระยะไกลของแฟ้มที่เลือกที่จะแก้ปัญหาความขัดแย้งในทิศทางที่กำหนด สิ่งนี้มีข้อแม้บางประการโดยเฉพาะ: ละเว้นตัวเลือก diff ที่ส่งผ่านไปยังคำสั่งผสาน (เช่นอัลกอริทึมและการจัดการช่องว่าง) ทำการผสานอย่างหมดจดจากไฟล์ต้นฉบับ (เพื่อให้การเปลี่ยนแปลงใด ๆ ที่ทำเองกับไฟล์ถูกละทิ้งซึ่งอาจจะดีหรือไม่ดี); และมีข้อได้เปรียบที่ไม่สามารถสับสนโดยเครื่องหมายต่าง ๆ ที่ควรอยู่ในไฟล์

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

สิ่งเหล่านี้ถูกใช้โดยการรันโดยgit mergetool -t (get|merge|keep)(ours|theirs) [<filename>]ที่<filename>ไม่ได้ระบุว่าประมวลผลไฟล์ที่ขัดแย้งทั้งหมด

โดยทั่วไปสมมติว่าคุณรู้ว่าไม่มีเครื่องหมายต่าง ๆ ที่จะทำให้เกิดความสับสนในการแสดงออกปกติkeep*ตัวแปรของคำสั่งนั้นมีประสิทธิภาพมากที่สุด หากคุณปล่อยให้mergetool.keepBackupตัวเลือกไม่มีการตั้งค่าหรือเป็นจริงหลังจากผ่านการผสานคุณสามารถกระจาย*.origไฟล์กับผลลัพธ์ของการผสานเพื่อตรวจสอบว่าเหมาะสมแล้ว เป็นตัวอย่างฉันเรียกใช้สิ่งต่อไปนี้หลังจากmergetoolเพียงเพื่อตรวจสอบการเปลี่ยนแปลงก่อนที่จะกระทำ:

for f in `find . -name '*.orig'`; do vimdiff $f ${f%.orig}; done

หมายเหตุ : ถ้าmerge.conflictstyleไม่ได้diff3แล้ว/^|||||||/รูปแบบในsedการปกครองจะต้อง/^=======/แทน

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