3 คะแนน โดย GN⁺ 2023-10-25 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • การเปลี่ยนแปลงขนาดเล็กสามารถดูได้ดีพอทั้งด้วย unified diff และ split diff แต่เมื่อเป็นการเปลี่ยนแปลงขนาดใหญ่และซับซ้อน การรีวิวด้วยการอ่าน diff อย่างเดียวจะเริ่มชนข้อจำกัด
  • สำหรับการเปลี่ยนแปลงขนาดใหญ่ ควรสำรวจและตรวจสอบโดยอิงจาก สถานะทั้งหมดของโค้ดเบส ณ ช่วงเวลาหนึ่ง ราวกับกำลังแก้โค้ดจริง มากกว่าจะอิงเพียงประวัติการเปลี่ยนแปลง
  • หน้าจอรีวิวที่เหมาะสมควรแสดงโค้ดปัจจุบันบนดิสก์ควบคู่กับ unified diff ของบริเวณนั้น เพื่อให้ติดตามทั้งบริบทของโค้ดและรายละเอียดการเปลี่ยนแปลงได้พร้อมกัน
  • เนื่องจากเครื่องมือที่มีอยู่รองรับรูปแบบนี้ไม่ดีนัก จึงใช้ เวิร์กโฟลว์แบบเทคโนโลยีพื้นฐาน โดย checkout PR ลงมาในเครื่อง แล้วลบ commit ออกให้เหลือเฉพาะการเปลี่ยนแปลง
  • วิธีนี้ช่วยให้สำรวจไฟล์ที่เปลี่ยนและทำเครื่องหมาย hunk ที่รีวิวแล้วได้ แต่ยังต้องจัดการเองอยู่ เพราะตำแหน่งปัจจุบันในเอดิเตอร์กับ diff ไม่ได้ซิงก์กันอัตโนมัติ

รีวิวจากสถานะโค้ดปัจจุบันมากกว่า diff

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

หน้าจอรีวิวที่ต้องการและวิธีเลี่ยงปัญหาแบบโลคัล

  • มุมมอง diff ที่เหมาะสมควรแสดงสถานะโค้ดปัจจุบันทางซ้าย และ unified diff ของบริเวณโค้ดที่กำลังเห็นอยู่ทางขวา
    • โค้ดทางซ้ายควรตรงกับสถานะปัจจุบันที่อยู่บนดิสก์
    • การเปลี่ยนแปลงควรถูกแสดงอย่างนุ่มนวลในขอบพื้นที่
    • diff ทางขวาควรสอดคล้องกับบริเวณโค้ดที่กำลังมองเห็นอยู่ทางซ้าย
  • ปัจจุบันเครื่องมือยังรองรับรูปแบบรีวิวนี้ไม่ดีนัก
  • เวิร์กโฟลว์จริงคือใช้ gpr script เพื่อ checkout PR ลงมาในเครื่อง
    • ในขั้นตอนสุดท้าย จะลบ commit ของ PR ออกให้เหลือเพียงการเปลี่ยนแปลง
    • จากนั้นจึงนำเวิร์กโฟลว์สำหรับ staging และ commit มาใช้กับการรีวิวโค้ด
  • ใช้ edamagit เพื่อดูรายการไฟล์ที่เปลี่ยน และย้ายไปยังการเปลี่ยนแปลงถัดไป/ก่อนหน้าในเอดิเตอร์
    • ยังสามารถใช้ staging area เพื่อทำเครื่องหมาย hunk ที่รีวิวแล้วได้ด้วย
  • ความไม่สะดวกที่ยังเหลืออยู่คือไม่มีการซิงก์อัตโนมัติระหว่าง magit status buffer กับไฟล์ที่เปิดอยู่ในเอดิเตอร์
    • ถ้าต้องการดูไฟล์ปัจจุบันกับ diff ควบคู่กัน ต้องเปิด diff เองและเลื่อนเองไปยังตำแหน่งที่กำลังดูอยู่
  • หากต้องการรีวิวแบบที่เข้าใกล้โค้ดในระดับนี้ ตอนนี้ยังต้องสร้างเครื่องมือชั่วคราวขึ้นมาใช้เอง
  • เป้าหมายหลักของการรีวิวโค้ดไม่ได้จำกัดอยู่แค่การตรวจโค้ดเสมอไป และสามารถอ่านบทความที่เกี่ยวข้อง Two Kinds of Code Review เพิ่มเติมได้

1 ความคิดเห็น

 
GN⁺ 2023-10-25
ความคิดเห็นจาก Hacker News
  • การบอกว่าในการเปลี่ยนแปลงขนาดใหญ่ไม่ได้อยากทำ diff review แต่อยากรีวิว codebase ณ จุดเวลาหนึ่งให้ถูกต้อง และให้ความสนใจกับบริเวณที่เพิ่งเปลี่ยนไปนั้น โดยส่วนตัวดูไม่ค่อยเข้ากับ code review ทั่วไปเท่าไร
    คงต่างกันไปตามทีมและ ticket แต่ถ้า reviewer ไม่ได้มีบทบาทอย่าง principal engineer ที่รับผิดชอบโค้ดทั้งหมดเป็นหลัก ปกติ code review มักใกล้เคียงกับการ ตรวจสอบความถูกต้องสอดคล้อง แบบเร็ว ๆ ด้วยสายตาอีกคู่หนึ่ง
    ถ้า commit ใน PR ถูกจัดระเบียบไว้อย่างดีหรือถูก squash แล้ว การตรวจสอบการเปลี่ยนแปลงแบบเพิ่มทีละส่วนแยกต่างหากก็ทำได้ค่อนข้างง่าย
    สุดท้ายความไม่พอใจนี้ดูเหมือนเป็นเรื่องความต่างของประเภทการรีวิวมากกว่า มีรีวิวแบบตรวจสอบความถูกต้องสอดคล้องที่พบได้ทั่วไป กับรีวิวเชิงสถาปัตยกรรม/ฟีเจอร์แบบลึกก่อน merge ซึ่ง code review ในเครื่องมือบนเว็บส่วนใหญ่ดูจะใกล้กับแบบแรก

    • การมอง code review เป็นแค่การตรวจสอบความถูกต้องสอดคล้องนั้นเป็นมุมมองที่ตื้นเกินไป Code review เป็นกลไกหลักในการลดความเป็นเจ้าของโค้ดแบบรายบุคคล เผยแพร่แนวปฏิบัติ และทำ การถ่ายทอดเทคโนโลยี
      Code review ที่ดีเริ่มจาก PR ที่ดี PR ควรอธิบายเป้าหมายและอธิบายว่าบรรลุเป้าหมายนั้นอย่างไร
      ข้อแรกของการรีวิวที่ดีคือดูว่าโค้ดบรรลุเป้าหมายที่อธิบายไว้หรือไม่ ข้อสองคือมี test ที่ยืนยันฟังก์ชันที่อ้างไว้หรือไม่ ข้อสามคือทำตาม แนวปฏิบัติด้านสถาปัตยกรรม ของระบบเดิมหรือไม่ ข้อสี่คือ style ตรงกับที่คาดหวังหรือไม่ และสุดท้ายคือมีข้อเสนอแนะที่จะทำให้การใช้ API ดีขึ้นหรือไม่
      Code review ที่ทำได้แค่ตรวจสอบความถูกต้องสอดคล้องนั้นมีประโยชน์น้อย เพราะ CI ก็ทำได้ Code review เป็นกระบวนการของมนุษย์ จึงควรใช้ประโยชน์จากสิ่งที่มนุษย์เท่านั้นทำได้ให้เต็มที่ และปล่อยที่เหลือให้เครื่องจักรทำ
      ในรายการข้างต้นมีคำถามแฝงอยู่ด้วยว่า “การเปลี่ยนแปลงนี้จะเป็นตัวอย่างที่ดีสำหรับ contribution ในอนาคตหรือไม่?”
    • คิดว่า code review แบบผิวเผินก็ให้ผลลัพธ์แบบผิวเผินเท่านั้น นี่คือเหตุผลที่แม้ code review จะแพร่หลาย แต่ก็ยังมี bug จำนวนมากถูกปล่อยขึ้น production
      ผมทำ code review ด้วย มุมมองของ tester เสมอ build และรันโค้ดเพื่อดูว่าทำงานตามที่ตั้งใจหรือไม่ มองหาจุดอ่อน และพยายามทำให้มันพัง
      diff ไม่ใช่จุดจบ แต่เป็นจุดเริ่มต้น เป็นแค่เบาะแสว่าควรไปลองเจาะตรงไหนของโค้ด และสุดท้ายหลักฐานก็มาจากพฤติกรรมที่เกิดขึ้นจริง
      บางคนอาจบอกว่า “นั่นเป็นงานของ tester ไม่ใช่งานของ engineer” แต่ผมก็สงสัยว่าใครจะทดสอบได้ดีกว่าคนที่เข้าใจโค้ดและรู้ว่าควรมองตรงไหน
      ผมรู้ว่าทัศนคติแบบนี้เป็นเสียงส่วนน้อย engineer จำนวนมากดูเหมือนมีแรงต้านแปลก ๆ ต่อการรันโค้ดเอง หรือแม้แต่การใช้ debugger พวกเขาสร้าง infrastructure มหึมาเพื่อพยายาม automate ทุกอย่าง แต่ automation สุดท้ายก็เป็นแค่โค้ดที่อาจมี bug ได้เหมือนกัน แล้วใครจะทดสอบ test, Quis custodiet ipsos custodes?
    • เห็นด้วยกับสิ่งที่คาดหวังจาก code review แต่ถ้าจะให้ทำงานได้ดี วิธีการทำงานบางอย่างต้องถูกวางให้เข้าที่ก่อน
      Code review เป็น ด่านป้องกันสุดท้าย ถ้าไม่นับ CI แต่ในทีมที่ผมเคยทำงานด้วย ทิศทางใหญ่ ๆ ที่ PR นำเข้ามามักถูกหารือกับหลายคนมาก่อนถึงจุดนั้นแล้ว จะเป็น pairing, การอธิบายเชิงลึก, coffee chat หรือวิธีใดก็ได้ที่เหมาะกับระดับความซับซ้อน
      เมื่อเป็นแบบนั้น PR ก็กลายเป็นพื้นที่รีวิว tactic ที่ใช้ทำตาม strategy นั้น ไม่ใช่รีวิวตัว strategy เอง เช่น การแยก module ใหม่ การนำ dependency ใหญ่เข้ามา หรือการปรับ API surface ใหม่
      หากตรวจสอบความถูกต้องสอดคล้องของโค้ดเพียงบางส่วนโดยไม่มีการสื่อสารล่วงหน้า ก็มีความเสี่ยงที่ความเป็นเจ้าของโค้ดจะถูกแบ่งแยกเป็นส่วน ๆ กลายเป็นสถานะแบบ “module นั้นทำอะไรนะ?” “ไม่รู้สิ ไปถาม Bob”
      นอกเหนือจากนั้น ไม่ว่าโหมดรีวิวจะเป็นแบบไหน ผมก็ชอบไอเดีย diff view ที่ผู้เขียนเสนอ
    • มีบางส่วนที่พูดได้ดี แต่เมื่อเจอซ้ำ ๆ diff review มักมีหลายกรณีที่เข้าใจไม่ได้จริง ๆ จนค่อนข้างไร้ความหมาย
      การรีวิวอะไรก็ตามจากก้อนที่มีบรรทัดสีแดงกับสีเขียวปนกันทำได้ยาก มันไม่ใช่มุมมองของโค้ดที่มีประโยชน์ และอย่างน้อยก็ไม่เหมาะเป็นมุมมองเริ่มต้น
      ถึงอย่างไรก็เป็นงานจึงต้องฝืนทำไป แต่ผมเห็นด้วย 100% กับที่ผู้เขียนบอกว่ามันไม่ใช่มุมมองที่มีประโยชน์นัก
    • วัฒนธรรมของบริษัทเทคโนโลยียุคใหม่ถอยห่างจากกระบวนการที่เป็นทางการมากขึ้นสำหรับการจัดการงานพัฒนาไปไกลเกินไปแล้ว
      เมื่อไม่มีกระบวนการพื้นฐานสำหรับจัดการ defect, feature ฯลฯ engineer แต่ละคนจึงต้องคิดค้นเองทุกครั้งว่าจะปล่อยฟีเจอร์ผ่านความร่วมมือกันอย่างไร
      ส่วนใหญ่แทบไม่ได้ทำอะไรเลย และ code review กลายเป็นความร่วมมือเพียงอย่างเดียวที่เกิดขึ้นในระดับรายละเอียดที่มีความหมายเกี่ยวกับหัวข้อนั้น จึงเกิดสภาพที่พยายามยัดการแทรกแซงทุกอย่างที่เป็นไปได้เข้าไปในช่วงเวลาเดียว
  • ในฐานะตัวเลือกที่สาม หรืออาจเป็นตัวเลือกที่สี่ difftastic ก็น่าพูดถึง ใช้ diff แบบ “เชิงโครงสร้าง” แทน diff ระดับบรรทัด ทำให้เน้นการเปลี่ยนแปลงได้ละเอียดกว่า
    https://github.com/Wilfred/difftastic

    • ในฐานะตัวเลือกที่สี่ หรืออาจเป็นตัวเลือกที่ห้า ก็มี patdiff: https://opensource.janestreet.com/patdiff/
      เท่าที่จำได้ บางครั้งทำให้ diff อ่านง่ายขึ้นราว 35%, โดยปกติ 60% ไม่ต่างกัน และนาน ๆ ครั้ง 5% กลับทำให้อ่านยากขึ้น
      ใช้มาหลายปีก่อนเลยจำปัญหาเฉพาะเจาะจงไม่ค่อยได้ เหตุผลเดียวที่เลิกใช้คือเริ่มใช้ magit สำหรับ Git diff
    • เป็นแนวทางที่ดีจริง ๆ แต่น่าเสียดายที่ยังไม่ได้ integrate อย่างแพร่หลาย เท่าที่รู้ structured JSON output ที่เหมาะให้เครื่องมืออื่นนำไปใช้ได้ก็เพิ่งมีไม่นานนี้เอง
    • ediff ของ Emacs ก็ทำสิ่งนี้ได้ ฟีเจอร์ที่ highlight คำที่ต่างกันคือ Refine
    • git diff --word-diff ก็มีฟีเจอร์คล้าย ๆ กันและค่อนข้างดี
  • ตอนรีวิวด้วย Vim ก็รู้สึกคล้ายกัน
    มีสคริปต์เล็ก ๆ สำหรับเปิด PR และกับไฟล์ที่เปลี่ยนแปลงก็ทำงานประมาณ vimdiff <(git show baseref:file) file แท็บของ Vim โดยพื้นฐานแล้วเป็นเหมือน view จึงดีตรงที่เปิดบัฟเฟอร์แต่ละอันในสถานะต่างกันพร้อมกันได้
    ใน view พื้นฐาน scroll lock ทำงานได้ตามที่คาด และถ้าจำเป็นก็หลีกเลี่ยงได้ในแท็บแยก
    [c และ ]c จะย้ายระหว่าง hunk โดยอิงชุดการเปลี่ยนแปลงที่มีอยู่ใน PR ไม่ใช่ working directory
    ใช้ dp และ dg เพื่อ push/pull hunk ไปยังบัฟเฟอร์ diff แบบอ่านอย่างเดียวแล้วทำเครื่องหมายว่า “เสร็จแล้ว” ได้ จากนั้นมันจะถูกซ่อนจากการเปลี่ยนแปลงที่ไฮไลต์ในบัฟเฟอร์ live
    การเปลี่ยนแปลงที่ทำในบัฟเฟอร์ live สามารถ commit ได้ทันที หรือ push เป็นคอมเมนต์ได้
    ฟีเจอร์แก้ไขทั่วไปอย่าง go to definition, การผสานกับ build, เอกสารแบบ popup ก็ยังทำงานตามปกติในสถานะ tree ปัจจุบัน
    วิธีนี้ช่วยให้ดูการเปลี่ยนแปลงเทียบกับ branch ฐานของ PR ได้ ขณะเดียวกันก็รักษา working directory ให้สะอาดไว้ ดูดีกว่าวิธีแก้ของ matklad ที่ดูการเปลี่ยนแปลงโดยทำให้ working directory สกปรกอยู่มาก
    ในสภาพแวดล้อมที่ผมทำงานอยู่ การเปลี่ยนแปลงมักถูกเพิ่มเป็น commit แบบ --fixup และเครื่องมือจะรวมกลับตอน merge โดยเรียก git-interpret-trailers เพื่อผูกผู้เขียน commit fixup ให้เป็นของ commit เดิม จึงดีเป็นพิเศษ บางทีก็ดึงคอมเมนต์ข้อความของ PR ออกมา แล้วถ้าเหมาะสมก็ใส่ trailer Reviewed-by หรือถ้าเทียบเท่ากับ +1 ก็ใส่ trailer Acked-by

    • อยากรู้ว่า “push เป็นคอมเมนต์” กับ “ดึงคอมเมนต์ข้อความออกมา” หมายถึงอะไรกันแน่ เป็น custom logic เฉพาะภายในบริษัทหรือเปล่า?
  • ใน codebase ที่ใหญ่มากและซับซ้อนมาก ซึ่งมีวิศวกรเกี่ยวข้องจำนวนมาก เรื่องนี้เป็นปัญหาใหญ่
    เหตุผลที่ code review ยากคือ diff มักดูสมเหตุสมผลเสมอ, test มักผ่านเสมอ และสิ่งพื้นฐานต่าง ๆ ก็ถูกตรวจไว้แล้วเสมอ
    แต่แม้การเปลี่ยนแปลงจะดูสมเหตุสมผล ในความเป็นจริงก็มักผิดอยู่บ่อย ๆ
    การเปลี่ยนแปลงแย่ ๆ ที่ดูสมเหตุสมผลเพียงรายการเดียวอาจทำให้ สถาปัตยกรรมทั้งระบบค่อย ๆ drift ได้
    เช่นเคย เรื่องนี้พูดอย่างเคร่งครัดแล้วไม่ใช่ปัญหาเครื่องมือ แต่ใกล้เคียงกับปัญหาวัฒนธรรมและการแบ่งปันความรู้มากกว่า เครื่องมือที่ดีกว่าอย่างเดียวแก้ไม่ได้

    • สองประโยคอย่าง “test มักผ่านเสมอ” กับ “แม้การเปลี่ยนแปลงจะดูสมเหตุสมผลก็มักผิดอยู่บ่อย ๆ” ยอมรับพร้อมกันได้ยาก
      ตอน code review แทบไม่ค่อยได้หาบั๊กโดยตรง แต่จะดูว่ามี test ที่จะจับบั๊กแบบนั้นหรือไม่มากกว่า
  • เหมือนผมพลาดอะไรไปบางอย่าง ผู้เขียนบอกว่า split diff ไม่เหมาะกับตัวเอง แต่ไม่ได้บอกเหตุผล
    diff ในอุดมคติดูแทบเหมือน split diff ที่ตัด context ซ้ำออกไป คือแทนที่จะมี context ซ้ำทั้งสองฝั่ง ก็มีอยู่แค่ฝั่งซ้าย
    เลยสงสัยว่าการเอา context ซ้ำออกจากแผงขวาให้ประโยชน์อะไร

    • ผู้เขียนเขียนว่าจำเป็นต้องรัน test, ใช้ go to definition และฟีเจอร์นำทางอื่น ๆ ของ editor, apply การเปลี่ยนแปลงในเครื่องเพื่อดูว่าสามารถเขียนอีกแบบได้ไหม, ดู context ที่กว้างขึ้นเพื่อหาจุดที่ควรเปลี่ยนไปด้วยกัน และสังเกตจุดแปลก ๆ ใน codebase ปัจจุบันโดยไม่ผูกกับเส้นทางการเปลี่ยนแปลงในอดีต
      editor/IDE ที่ผมเคยใช้มักรองรับฟีเจอร์เหล่านี้ใน diff แบบพื้นฐานมาก go to definition ก็ทำได้แค่ในไฟล์เดียวกัน หรือ autocomplete ก็ไม่ค่อยทำงานกับรายการที่เพิ่มใหม่ และมักไม่มี ฟีเจอร์ refactoring
    • ฝั่งซ้ายแสดงโค้ดปัจจุบันที่ยังไม่ถูกแก้ไข ถ้าฝั่งหนึ่งมี context เต็มพร้อมฟีเจอร์นำทางโค้ด และอีกฝั่งแสดงการเปลี่ยนแปลง ก็จะเห็นได้ว่าการเปลี่ยนแปลงใดถูก apply ใน context เฉพาะนั้น
      ตามความเข้าใจของผม ผู้เขียนอยากกลับทิศของ diff คือแทนที่จะดูตัวการเปลี่ยนแปลงเอง เขาอยากดู โค้ด แล้วตรวจว่ามีการเปลี่ยนแปลงที่เกี่ยวข้องอยู่หรือไม่
      บทความขาดรายละเอียด แต่ดูเหมือนว่าเขาอยากนำทางไปยัง implementation หรือ call site แล้วตรวจว่ามีการเปลี่ยนแปลงที่เหมาะสมหรือไม่
    • ไม่ใช่ผู้เขียน แต่เห็นด้วย
      การไฮไลต์ diff อาจทำให้เสียสมาธิมากกว่าที่คิด และบางครั้งพอปิดแล้วอ่านง่ายขึ้นชัดเจน ผมเองก็ปิดใน diff viewer เป็นครั้งคราวเพื่อดูโค้ดด้วยสายตาใหม่ แต่ไม่มีตัวเลือกให้แสดง unified diff ไว้ใน split pane ไปด้วย
  • ถ้ากด . บน GitHub จะเข้าสู่ IDE เต็มรูปแบบในเบราว์เซอร์
    ตอนรีวิวมีประโยชน์มาก เพราะแทนที่จะเห็นแค่ชิ้นส่วน ก็เห็นการเปลี่ยนแปลงใน context ของไฟล์ทั้งไฟล์ ทำให้จับ ปัญหาการออกแบบที่ละเอียดอ่อน ได้ดีกว่ามาก

    • อันนี้ดีจริง เพิ่งเคยเข้า IDE นี้เฉพาะตอนแก้ไฟล์บน GitHub โดยตรง ไม่รู้เลยว่ามี shortcut จาก commit diff ได้ทันที
      อนึ่ง shortcut นี้ใช้ได้บน GitLab ด้วย
  • คิดถึงฟีเจอร์บางอย่างของ p4merge เช่น ฟีเจอร์ที่แสดงในช่องว่างระหว่าง split diff ว่าส่วนไหนของไฟล์หนึ่งสอดคล้องกับส่วนไหนของอีกไฟล์ พร้อมแสดงผลกระทบของ diff จากทั้งสองฝั่งด้วย: https://www.perforce.com/manuals/p4merge/Content/P4Merge/dif...
    ผมชอบฟีเจอร์ 3-way merge ด้วย: https://www.perforce.com/manuals/p4merge/Content/P4Merge/dif...
    ฟีเจอร์เหล่านี้ไม่ได้เข้ามาอยู่ในเครื่องมือ diff บนเว็บที่ใช้กันแพร่หลาย ผมมองว่า 3-way diff เป็นวิธีที่ดีในการแสดงผลลัพธ์ของ merge ที่ยาก

  • ถ้าใช้ GitHub อยู่ ก็แค่กด . บนหน้า pull request ของ github.com หรือเปลี่ยนโดเมนเป็น github.dev
    จากนั้น VSCode จะเปิดในเบราว์เซอร์ และ pull request จะแสดงเป็น diff view
    ข้อดีคือดูไฟล์ทั้งไฟล์ได้ และอัลกอริทึม diff ต่างจาก github.com จึงอาจอ่านง่ายกว่าใน diff ที่ซับซ้อน

    • ข้อเสียคือช้าและมีบั๊กเยอะ
      side-by-side diff view ที่แสดงคอมเมนต์ PR เป็นรายการนอกบรรทัดอาจมีประโยชน์มาก แต่เสียดายที่ต้องเปิด instance ของ VSCode ทั้งตัวในเบราว์เซอร์
      จริง ๆ แล้วมันมีประโยชน์มากจน GitHub เคยมี split view แบบนี้มาก่อน และไม่จำเป็นต้องผลักคนเข้าไปในสภาพแวดล้อมพัฒนาที่เต็มไปด้วย buzzword อย่าง AI/ML/crypto/blockchain/cloud-enabled
      ไอเดียดี แต่การลงมือทำแย่มาก ฟังดูเหมือนเป็นคำสรุปของ GitHub โดยรวมในช่วงนี้ด้วย
  • Meld ค่อนข้างเหมาะกับการใช้งานลักษณะนี้
    https://meldmerge.org/

    • https://kdiff3.sourceforge.net/ ก็มีมุมมองที่ดีหลายแบบ จึงควรกล่าวถึงด้วย
    • ดูค่อนข้างคล้ายกับ FileMerge ที่รวมอยู่ในเครื่องมือสำหรับนักพัฒนาของ Apple
  • เครื่องมือที่ชอบที่สุดคือ diff2html-cli: https://diff2html.xyz/
    https://www.npmjs.com/package/diff2html-cli
    สามารถดู diff เป็น HTML ได้ และรองรับทั้งรูปแบบ side-by-side และ unified