วิธีการใช้ Subversion (SVN) - แนวคิดพื้นฐาน

1. February 2009

ปัญหาอย่างหนึ่งที่ทำให้ผมสนใจเรื่อง Software Engineering คือจะทำยังไงให้คนหลายๆคนทำงานด้วยกันได้ครับ ประเด็นหนึ่งที่น่าสนใจเกี่ยวกับปัญหานี้ก็เป็นเรื่องการจัดการ "สถานะ" ของระบบนี่แหละ (ราชบัณฑิตแปล Configuration ว่า "โครงแบบ" อ่านไม่รู้เรื่องเลยแฮะ) หรือถ้าพูดภาษาชาวบ้านมันก็คือ Software Configuration Management (SCM) นั่นเอง

Subversion (หรือเรียกย่อว่า SVN) เป็น Tool อันหนึ่งในกลุ่ม Version Control ครับ ซึ่งก็มีหลายตัวตั้งแต่ CVS, Team Foundation Server, Git, Bazaar แต่ SVN ดูเหมือนจะเป็นที่นิยมที่สุด ส่วนหนึ่งเป็นเพราะผู้สร้าง SVN เป็นคนเดียวกับผู้สร้าง CVS ที่เคยโด่งดังและใช้กันแพร่หลายมากมาก่อนครับ แต่ด้วย Architecture ของ CVS มันทำให้ไม่สามารถเพิ่ม Functionality เจ๋งๆบางอย่างเข้าไปได้ เลยตั้งโปรเจคใหม่คือ SVN ซะเลย

SubversionLogo

วิธีการเข้าใจ Subversion ในระดับพื้นฐานนั้นไม่ยากครับ

เรื่องของ Repository

Repository

ก่อนอื่นขอให้เข้าใจ Concept เรื่องของ Repository ก่อน ตัว Repo นี่จะเป็นเหมือนศูนย์กลางในการเก็บข้อมูลซึ่งทุกคนจะใช้ร่วมกันครับ ดังนั้น หากมีการแก้ไขข้อมูลใน Repo โดยสมาชิกคนหนึ่ง คนอื่นก็จะเห็นการแก้ไขนั้นๆด้วย ถ้าพูดให้ง่ายๆก็คือมันเป็น Shared Folder เหมือนที่เราเห็นใน Network นั่นเอง

อย่างไรก็ตามตัว Repo นี่มันมีความสามารถกว่านั้นมาก เพราะมันจะเก็บ "สถานะ" เก่าๆย้อนหลังไว้ได้ด้วย ดังนั้นหากมีสมาชิกเผลอลบไฟล์บางไฟล์ออกไปจาก Repo ก็ยังสามารถกู้กลับมาได้โดยง่ายโดยการย้อนไป "สถานะ" ก่อนหน้า ... เจ๋งใช่มั้ยล่ะ

สถานะแต่ละสถานะก็จะมีหมายเลขกำกับด้วย ซึ่งเราจะเรียกว่า Revision Number ซึ่งทำการแก้ไขเข้าไปหลายๆครั้ง Revision Number ก็จะยิ่งเพิ่มมากขึ้น และเราสามารถดึงข้อมูลจาก Revision ใดๆใน Repo ก็ได้ Revision ล่าสุดใน Repo จะมีชื่อเรียกพิเศษเรียกว่า Head Revision ด้วยครับ

คำสั่งพื้นฐาน: Checkout

ขั้นแรกก่อนสิ่งอื่นใด เราต้องทำการดึงข้อมูลที่เราต้องการออกมาจาก Repository ก่อน ข้อมูลนี่จริงๆแล้วมันก็มักจะเป็น Source Code และ Project File ทั้งหลายนั่นแหละครับ กระบวนการนี้เรียกว่าการ Checkout ซึ่งเราต้องระบุตำแหน่ง Repository และ Path ใน Repository ที่เราต้องการ Checkout ออกมา หลังจาก Checkout ออกมาแล้ว ก็จะได้เป็น Copy อยู่บนเครื่องของเรา อยากแก้ไขทำอะไรก็ได้

อาจจะสงสัยเรื่อง Path ใน Repo ว่าทำไมต้องระบุด้วย ? สาเหตุก็เพราะจริงๆแล้ว Repo อันเดียวอาจเก็บโปรเจคไว้หลายๆโปรเจค และเราอาจจะต้องการจัดการแค่โปรเจคเดียว หรือเราอาจจะต้องการทำงานบน "กิ่ง" (Branch) อันเดียวก็ได้ (ไว้ค่อยพูดต่อไปว่าคืออะไร) ตัว Repo ของเราเองก็สามารถจัดเป็นโครงสร้างต้นไม้ได้เหมือน Directory ทั่วๆไป การใช้ Path จึงเป็นประโยชน์มากครับ และก่อให้เกิด "รูปแบบการจัดวาง" (Layout) มาตรฐานของ Repository ขึ้นมา เช่นโฟลเดอร์ trunk, branches, tags และอื่นๆ ไว้ว่ากันทีหลัง

คำสั่งพื้นฐาน: Commit

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

คำสั่งพื้นฐาน: Update

ถ้ามีคนแก้ไขไฟล์อื่นแล้ว Commit กลับเข้าไปใน Repo การแก้ไขนั้นย่อมยังไม่ส่งผลใดๆกลับมาที่ Copy ที่อยู่บนเครื่องทำงานของเราใช่มั้ยครับ ดังนั้นเราต้องใช้คำสั่ง Update เพื่อให้ผลการแก้ไขนั้นลงมาบนเครื่องเราด้วย

คำสั่งพื้นฐาน: Add, Delete

ในความเป็นจริงเราไม่ได้ทำการแก้ไขไฟล์อย่างเดียว เรามีการ เพิ่ม ลบ ไฟล์เข้าไปอยู่เสมอ เช่นตอนสร้าง Class ใหม่ เป็นต้น การเพิ่มไฟล์เข้าไปทำได้โดยใช้คำสั่ง Add และในทางกลับกัน การลบไฟล์ออกใช้คำสั่ง Delete ครับ

ปัญหาที่เกิดขึ้น

SharingProblem

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

    1. นาย ก Update
    2. นาย ข Update
    3. นาย ก แก้ Gant.cs
    4. นาย ข แก้ Gant.cs
    5. นาย ก Commit
    6. นาย ข Commit

การทำงานในขั้นตอนแบบด้านบนจะไม่เกิดขึ้นเพราะ Subversion จะไม่ยอมให้ นาย ข Commit ในขั้นตอนสุดท้ายครับ โดยจะเกิดสิ่งที่เรียกว่า out-of-date error แทน

เหตุการณ์นี้เรียกว่า Conflict ครับ และวิธีการแก้โดยปกติก็คือ ต้องให้สมาชิกที่เป็นมนุษย์ทำการ Review เอง โดยการทำการเปรียบเทียบความแตกต่างระหว่างไฟล์ แล้วทำการสร้าง Version ใหม่ที่เป็นการรวม (Merge) ระหว่างสองไฟล์ขึ้น ก่อนที่จะทำการ Commit กลับเข้าไปครับ โดยจะมี Tool มากมายคอยช่วยเหลือเช่น Diff ใช้ดูความแตกต่างระหว่างไฟล์สองไฟล์แบบ "ฉลาด" ไม่ใช่การเทียบบรรทัดต่อบรรทัดธรรมดาครับ และใช้ได้ดีกับไฟล์ Source Code หรือ Text File เท่านั้น งาน Merge นี้เป็นงานที่คอมพิวเตอร์ทำเองไม่ได้ครับ เดี๋ยวทำมาแล้วไม่ถูกใจ แย่เลย 

สรุป

ผมพยายามเขียนโพสต์นี้ให้มัน Generic มากๆเพราะอยากเน้น Concept แต่ตอนต่อๆไปจะลองเขียนให้มันเฉพาะมากขึ้น เช่น TortoiseSVN กับ Visual Studio แต่ ไม่รู้จะเข้ามาเขียนเมื่อไหร่น่ะ o__o

Subversion Tutorials ,