จะใช้ Git patch กับไฟล์ที่มีชื่อและเส้นทางอื่นได้อย่างไร?


107

ฉันมีที่เก็บสองแห่ง ./hello.testในหนึ่งฉันจะทำให้การเปลี่ยนแปลงไปยังแฟ้ม git format-patch -1 HEADฉันกระทำการเปลี่ยนแปลงและสร้างแพทช์จากที่กระทำกับ ตอนนี้ฉันมีที่เก็บที่สองที่มีไฟล์ที่มีเนื้อหาเหมือนกับ hello.test แต่ถูกวางไว้ในไดเร็กทอรีอื่นภายใต้ชื่ออื่น: ./blue/red/hi.test. ฉันจะนำโปรแกรมแก้ไขดังกล่าวไปใช้กับhi.testไฟล์ได้อย่างไร ฉันพยายามgit am --directory='blue/red' < patch_fileแต่แน่นอนว่าบ่นว่าไฟล์ไม่ได้ตั้งชื่อเหมือนกัน (ซึ่งฉันคิดว่า Git ไม่สนใจ?) ฉันรู้ว่าฉันสามารถแก้ไขความแตกต่างเพื่อใช้กับไฟล์เฉพาะนั้นได้ แต่ฉันกำลังมองหาวิธีแก้ปัญหาคำสั่ง


เกี่ยวข้องกับ: stackoverflow.com/q/3367254/1959808
Ioannis Filippidis

คำตอบ:


105

คุณสามารถสร้างแพตช์โดยใช้git diffแล้วนำไปใช้โดยใช้patchยูทิลิตี้ซึ่งช่วยให้คุณระบุไฟล์ที่คุณต้องการใช้ความแตกต่าง

ตัวอย่างเช่น:

cd first-repo
git diff HEAD^ -- hello.test > ~/patch_file

cd ../second-repo
patch -p1 blue/red/hi.test ~/patch_file

7
อาดีไม่คิดอย่างนั้น อย่างไรก็ตามมีวิธีใดบ้างที่จะทำสิ่งนี้ด้วยคำสั่ง Git เพื่อให้การคอมมิตข้อมูล (วันที่และเวลาผู้เขียนคอมมิตข้อความคอมมิต) ยังคงเหมือนเดิม
mart1n

2
เป็นไปได้ว่ามีบางอย่างที่คุณสามารถทำได้amหรือapplyแต่ฉันหาไม่เจอ หากคุณพบว่าตัวเองกำลังทำซ้ำการเปลี่ยนแปลงหลายอย่างอาจมีวิธีแก้ปัญหาที่ดีกว่าโดยใช้โมดูลย่อยหรือภาษาที่คุณเลือกให้เพื่อแชร์โค้ด (เช่นใน Ruby คุณสามารถแยกรหัสที่ซ้ำกันเป็นอัญมณีได้)
georgebrock

1
นี่เป็นเอกสารที่เกี่ยวข้อง (ไฟล์ต้นฉบับคือ XML) โมดูลย่อยไม่ใช่ตัวเลือกจริงๆเพราะฉันต้องสร้างกรณีที่แข็งแกร่งสำหรับพวกเขาในโครงสร้างพื้นฐานที่มีอยู่ของเรา
mart1n

57

มีวิธีง่ายๆที่ไม่เกี่ยวข้องกับการแก้ไขโปรแกรมแก้ไขด้วยตนเองหรือสคริปต์ภายนอก

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

git format-patch --relative <committish> --stdout > ~/patch

ในที่เก็บที่สอง:

git am --directory blue/red/ ~/patch

แทนการใช้--relativeในgit format-patchการแก้ปัญหาหนึ่งคือการใช้-p<n>ตัวเลือกในgit amแถบnไดเรกทอรีจากเส้นทางของแพทช์ที่เป็นที่กล่าวถึงในคำตอบของคำถามที่คล้ายกัน

นอกจากนี้ยังสามารถเรียกใช้git format-patch --relative <committish>โดยไม่มี--stdoutและจะสร้างชุด.patchไฟล์ จากนั้นไฟล์เหล่านี้สามารถป้อนโดยตรงgit amกับgit am --directory blue/red/ path/to/*.patchไฟล์.


9
นี่ยังคงอาศัยข้อเท็จจริงที่ว่าชื่อไฟล์เหมือนกันใช่ไหม?
mart1n

3
ควรสังเกตว่า--directoryดูเหมือนว่าอ็อพชันต้องการให้คุณระบุพา ธ แบบเต็มของไดเร็กทอรีที่สัมพันธ์กับ repo root บางอย่างเช่น--directory=./ในขณะที่ chdir ไปยังไดเร็กทอรีย่อยใน repo จะไม่ทำงาน
Reid

1
ใช้ความ--3wayช่วยเหลือกับdoes not exist in index:git am --3way --directory (relative-path) (patch)
Brent Bradburn

ใช้-kคีย์ในทั้งสองคำสั่งเพื่อไม่ตัดบรรทัดแรกของข้อความคอมมิต
ruvim

การใช้--3wayไม่เพียงช่วยให้เกิดข้อผิดพลาด "ไม่มีอยู่ในดัชนี" (ตามที่ @nobar ชี้ให้เห็น) แต่ยังช่วยให้คุณจัดการข้อขัดแย้งในการผสานได้อย่างหมดจด แทนที่จะปล่อยไฟล์ที่ขัดแย้งไว้โดยไม่ถูกแตะต้องจะมีการเพิ่มบล็อกความขัดแย้งที่สามารถแก้ไขได้
Daniel Wolf

12

ตอบคำถามของตัวเองด้วยสคริปต์ที่ทำสิ่งนี้: https://github.com/mprpic/apply-patch-to-file

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


5

จากคำตอบโดย @georgebrock นี่คือวิธีแก้ปัญหาที่ฉันใช้:

ขั้นแรกให้สร้างไฟล์แพตช์ตามปกติ (เช่น. git format-patch commitA..commitB )

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

cd second-repo
git am ~/00*.patch

สำหรับไฟล์แพตช์ทุกไฟล์คุณจะได้รับข้อผิดพลาดเช่น "error: XYZ ไม่มีอยู่ในดัชนี" ตอนนี้คุณสามารถใช้ไฟล์แพตช์นี้ได้ด้วยตนเอง:

patch --directory blue/red < ~/0001-*.patch
git add -a
git am --continue

คุณต้องทำสามขั้นตอนนี้สำหรับไฟล์แพตช์แต่ละไฟล์

การดำเนินการนี้จะเก็บรักษาข้อความคอมมิตดั้งเดิมเป็นต้นโดยไม่ต้องใช้git format-patchคำสั่งพิเศษหรือแก้ไขไฟล์แพตช์


1
คำตอบที่ดีฉันคิดว่านี่เป็นพื้นฐานที่ดีที่สุดสำหรับการจัดการแพตช์ที่ "ไม่ได้มาตรฐาน" ทุกประเภท ฉันทำใน 3 ขั้นตอน (1) ยอมรับข้อความ - git format-patch -1 commitA --stdout > thing.diff; (2) แก้ไขไฟล์แพทช์จนกว่าจะทำตามที่ฉันต้องการ (3) ข้อความที่จะยอมรับ git am --3way thing.diffซึ่งมีข้อดีตรงที่คุณสามารถยอมรับส่วนต่างๆของโปรแกรมแก้ไขที่ใช้งานได้อย่างหมดจดและใช้gitกระบวนการแก้ไขความขัดแย้งมาตรฐานสำหรับส่วนที่ไม่ได้
We Are All Monica

2

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

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

สมมติว่าคุณมีการปรับเปลี่ยนไฟล์Aให้แสดงของA~1รุ่นก่อนหน้านี้และคุณต้องการใช้ต่างระหว่างA~1ไปยังแฟ้มAB

เปิดเครื่องมือที่ผสานวิธีที่สามเช่น Beyond เปรียบเทียบเส้นทางของแผงด้านซ้ายเป็นAแผงกลางเป็นบรรพบุรุษร่วมกันเพื่อให้เส้นทางเป็นเส้นทางของแผงที่เหมาะสมเป็นA~1 Bจากนั้นแผงล่างแสดงให้เห็นถึงผลของการใช้แตกต่างระหว่างA~1การไปยังไฟล์AB

รูปต่อไปนี้แสดงให้เห็นถึงความคิด

ป้อนคำอธิบายภาพที่นี่


0

FYI: เมื่อเร็ว ๆ นี้ฉันมีปัญหาในการพยายามดาวน์โหลดโปรแกรมแก้ไขจาก Github และนำไปใช้กับไฟล์ในเครื่อง (ซึ่งเป็นการ "แทนที่" ในตำแหน่งใหม่)

git amจะไม่ใช้โปรแกรมแก้ไขเนื่องจากไฟล์ "ไม่อยู่ในดัชนี" หรือ "สกปรก" แต่ฉันพบว่าpatchคำสั่งง่ายๆสามารถใช้โปรแกรมแก้ไขได้ มันแจ้งให้ฉันทราบชื่อของไฟล์ที่จะแก้ไข

ได้งานทำต่อไป ...

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