เป รียบเทียบ สองไฟล์
ส่วนตัวและปลอดภัย
ทุกอย่างเกิดขึ้นในเบราว์เซอร์ของคุณ ไฟล์ของคุณไม่เคยสัมผัสเซิร์ฟเวอร์ของเรา
เร็วสุดขีด
ไม่มีการอัปโหลด ไม่ต้องรอ แปลงทันทีที่คุณวางไฟล์
ฟรีจริงๆ
ไม่ต้องใช้บัญชี ไม่มีค่าใช้จ่ายแอบแฝง ไม่มีลูกเล่นขนาดไฟล์
“Diffs” เป็นภาษากลางของการเปลี่ยนแปลง เป็นเรื่องเล่าที่กระชับซึ่งบอกคุณว่า อะไร เคลื่อนไหวระหว่างสองเวอร์ชันของสิ่งหนึ่ง — ซอร์สโค้ด ร้อยแก้ว ชุดข้อมูล — โดยไม่ต้อง บังคับให้คุณอ่านทุกอย่างอีกครั้ง เบื้องหลังสัญลักษณ์ไม่กี่ตัวนั้น (+, -, @@) มีสแต็กของอัลกอริทึม ฮิวริสติก และรูปแบบที่ลึกซึ้ง ที่สร้างสมดุลระหว่างความเหมาะสมที่สุด ความเร็ว และความเข้าใจของมนุษย์ บทความนี้เป็นการเดินทางเชิงปฏิบัติ จากอัลกอริทึมสู่เวิร์กโฟลว์ของ diffs: วิธีการคำนวณ วิธีการจัดรูปแบบ วิธีที่ เครื่องมือผสานใช้ และวิธีปรับแต่งเพื่อการตรวจสอบที่ดีขึ้น ตลอดทาง เราจะอ้างอิง การกล่าวอ้างในแหล่งข้อมูลหลักและเอกสารทางการ — เพราะรายละเอียดเล็กๆ น้อยๆ (เช่น การนับช่องว่าง หรือไม่) มีความสำคัญจริงๆ
“diff” คืออะไรกันแน่
อย่างเป็นทางการ diff อธิบาย สคริปต์แก้ไขที่สั้นที่สุด (SES) เพื่อแปลง ลำดับ “เก่า” เป็น “ใหม่” โดยใช้การแทรกและการลบ (และบางครั้งการแทนที่ ซึ่งสามารถจำลองเป็นการลบ+แทรก) ในทางปฏิบัติ diff ที่โปรแกรมเมอร์ส่วนใหญ่เผชิญคือแบบบรรทัด แล้วจึงปรับแต่งเป็นคำหรืออักขระเพื่อให้อ่านง่ายขึ้น ผลลัพธ์ที่เป็นที่ยอมรับคือรูปแบบ บริบท และ รวม ; แบบหลัง — สิ่งที่คุณมักจะเห็นในการตรวจสอบโค้ด — บีบอัดผลลัพธ์ด้วยส่วนหัวที่กระชับ และ “hunks” ซึ่งแต่ละส่วนจะแสดงพื้นที่ใกล้เคียงของบริบทรอบๆ การเปลี่ยนแปลง รูปแบบรวม ถูกเลือกผ่าน -u/--unified และเป็นมาตรฐานโดยพฤตินัย สำหรับการแพตช์; patch โดยทั่วไปจะได้รับประโยชน์จากบรรทัดบริบท เพื่อใช้การเปลี่ยนแปลงอย่างมีประสิทธิภาพ
คู่มือ GNU diff จัดทำรายการสวิตช์ที่คุณใช้เมื่อต้องการ สัญญาณรบกวนน้อยลงและสัญญาณมากขึ้น — การละเว้นช่องว่าง การขยายแท็บเพื่อการจัดตำแหน่ง หรือการขอ สคริปต์แก้ไข “น้อยที่สุด” แม้ว่าจะช้ากว่าก็ตาม (การอ้างอิงตัวเลือก) ตัวเลือกเหล่านี้ไม่ได้เปลี่ยนความหมายของความแตกต่างของไฟล์สองไฟล์ แต่เปลี่ยน ว่าอัลกอริทึมค้นหาสคริปต์ที่เล็กกว่ าอย่างจริงจังเพียงใดและผลลัพธ์นำเสนอต่อมนุษย์อย่างไร
จาก LCS ถึง Myers: diffs คำนวณอย่างไร
diffs ข้อความส่วนใหญ่สร้างขึ้นจากนามธรรม ลำดับย่อยร่วมที่ยาวที่สุด (LCS) การเขียนโปรแกรมไดนามิกแบบคลาสสิกแก้ปัญหา LCS ในเวลาและพื้นที่ O(mn) แต่ นั่นช้าเกินไปและใช้หน่วยความจำมากเกินไปสำหรับไฟล์ขนาดใหญ่ อัลกอริทึมของ Hirschberg แสดงวิธีคำนวณการจัดตำแหน่งที่เหมาะสมที่สุดใน พื้นที่เชิงเส้น (ยังคง เวลา O(mn)) โดยใช้การแบ่งและพิชิต ซึ่งเป็นเทคนิคการประหยัดพื้นที่พื้นฐานที่ มีอิทธิพลต่อการใช้งาน diff ในทางปฏิบัติ
สำหรับความเร็วและคุณภาพ ความก้าวหน้าคือ อัลกอริทึมของ Eugene W. Myers ปี 1986ซึ่งค้นหา SES ในเวลา O(ND) (N ≈ จำนวนบรรทัดท ั้งหมด, D ≈ ระยะห่างการแก้ไข) และพื้นที่เกือบเชิงเส้น Myers จำลองการแก้ไขใน “กราฟการแก้ไข” และก้าวไปตาม ขอบเขตที่ไปได้ไกลที่สุด ให้ผลลัพธ์ที่ทั้งเร็วและใกล้เคียง กับค่าต่ำสุดในการตั้งค่า diff แบบบรรทัด นั่นคือเหตุผลที่ “Myers” ยังคงเป็นค่าเริ่มต้นในเครื่องมือมากมาย
นอกจากนี้ยังมีตระกูล Hunt–Szymanski ซึ่งเร่งความเร็ว LCS เมื่อมีตำแหน่งที่ตรงกันน้อย (โดยการจัดทำดัชนีการจับคู่ล่วงหน้าและไล่ตาม ลำดับย่อยที่เพิ่มขึ้น) และในอดีตเชื่อมโยงกับตัวแปร diff ในยุคแรก อัลกอริทึมเหล่านี้ให้ความกระจ่างเกี่ยวกับข้อดีข้อเสีย: ในอินพุตที่มีการจับคู่แบบกระจัดกระจาย พวกมันสามารถทำงานได้ เร็วกว่ากำลังสอง สำหรับภาพรวมของผู้ปฏิบัติงานที่เชื่อมโยงทฤษฎีและการใช้งาน โปรดดู บันทึกของ Neil Fraser.
เมื่อ “เหมาะสมที่สุด” ไม่สามารถอ่านได้: กลยุทธ์ความอดทนและฮิสโตแกรม
Myers มุ่งเป้าไปที่สคริปต์แก้ไขที่น้อยที่สุด แต่ “น้อยที่สุด” ≠ “อ่านง่ายที่สุด” บล็อกขนาดใหญ่ ที่จัดลำดับใหม่หรือซ้ำซ้อนสามารถหลอกอัลกอริทึม SES บริสุทธิ์ให้จัดตำแหน่งที่ไม่เหมาะสมได้ เข้าสู่ patience diffซึ่งให้เครดิตกับ Bram Cohen: มันยึดตาม บรรทัดที่ไม่ซ้ำกันและมีความถี่ต่ำ เพื่อ ทำให้การจัดตำแหน่งมีเสถียรภาพ ซึ่งมักจะสร้าง diffs ที่มนุษย์พบว่าสะอาดกว่า — โดยเฉพาะในโค้ดที่มี ฟังก์ชันที่ย้ายหรือบล็อกที่จัดระเบียบใหม่ เครื่องมือมากมายเปิดเผยสิ่งนี้ผ่านตัวเลือก “ความอดทน” (เช่นdiff.algorithm).