Version Control and Git From Zero to Hero : Part 1

บทความโดย ผศ.ดร.ณัฐโชติ พรหมฤทธิ์
ภาควิชาคอมพิวเตอร์
คณะวิทยาศาสตร์
มหาวิทยาลัยศิลปากร

Undo/Redo

หากพูดถึง Version Control โดยเฉพาะ Git ถ้าใครไม่เคยได้ยินก็ต้องบอกว่าเชยมากครับ สำหรับนักพัฒนาซอฟท์แวร์ (Software Developers)  Version Control ถือว่าเป็นสิ่งจำเป็นจนขาดไม่ได้ เหมือนกับปัจจัย 4 ที่จำเป็นต่อการดำรงชีวิตของมนุษย์เลยทีเดียว

Version Control คือเครื่องมือช่วยติดตามการเปลี่ยนแปลงของ Source Code โดยการเก็บประวัติการเปลี่ยนแปลงลง Database ชนิดพิเศษ เมื่อมีความผิดพลาดเกิดขึ้น (เป็นเรื่องปกติของ Software Developers ที่จะทำเรื่องผิดพลาดเล็กๆ น้อยๆ จนถึงเรื่องผิดพลาดร้ายแรงซึ่งอาจทำให้ Software ที่กำลังพัฒนาพังทั้ง Project) Software Developers จะสามารถย้อนกลับไปยังช่วงเวลาต่างๆ และเปรียบเทียบ Code ใหม่กับ Code ใน Version ก่อนหน้า เพื่อแก้ไขความผิดพลาดให้มีผลกระทบต่อทีมน้อยที่สุด

ถ้าจะเทียบให้เห็นภาพจากเรื่องใกล้ตัว Version Control ก็คล้ายกับคำสั่ง Undo/Redo ในโปรแกรม Microsoft Word สมัยก่อน ที่ช่วยเรียกคืน Version ของเอกสารได้ แต่หากผู้ใช้สั่งบันทึกแล้วปิดโปรแกรม Microsoft Word เมื่อเรียกไฟล์ขึ้นมาแก้ไขอีกครั้ง ผู้ใช้จะไม่สามารถย้อนกลับไปยัง Version ก่อนหน้าได้อีก

Copy File and Folder

ดังนั้นวิธีการหนึ่งที่เราสามารถจัดการได้ คือการบันทึกเอกสารแยกเป็นไฟล์หลายๆ ไฟล์ เช่น

git_project.docx
git_project_v2.docx
git_project_back.docx
git_project_final.docx
git_project_lastest.docx

แต่จะเห็นว่าการเก็บไฟล์ด้วยการตั้งชื่ออาจทำให้ผู้ใช้สับสนในภายหลังว่าไฟล์ไหนใหม่กว่ากัน รวมทั้งไม่สามารถบอกได้ว่าไฟล์ไหนถูกสร้างต่อยยอดมาจากไฟล์ไหนบ้าง

เพื่อไม่ให้เกิดความสับสนเรื่อง Version ของเอกสาร เราอาจแก้ปัญหาโดยการจัดเก็บไฟล์แยกเป็น Folder ตามวันที่ เช่น

แต่วิธีการนี้จะทำให้เราสิ้นเปลืองเนื้อที่เก็บข้อมูลตามจำนวน Version ของเอกสารที่เกิดขึ้น แม้ว่าจะมีการเปลี่ยนแปลงในเอกสารเพียงไม่กี่บรรทัด ก็ต้องคัดลอกไฟล์ทั้ง Folder เพื่อสร้างเอกสาร Version ใหม่ขึ้นมา และบอกไม่ได้ว่าไฟล์ Version นั้นๆ มีความสำคัญขนาดไหน

Patch

เพื่อหลีกเลี่ยงความสิ้นเปลืองพื้นที่จัดเก็บ เราอาจเก็บ Version เอกสารเป็น Patch เหมือนกับการเก็บ Version ของ Source Code ของระบบปฏิบัติการ Linux ในยุคแรกๆ ดังภาพ

จากภาพด้านบนแสดงตัวอย่างของ Patch ที่เกิดจากการเปรียบเทียบไฟล์เก่า (Original file) และ ไฟล์ใหม่ (Changed File) Patch ที่สร้างจะแสดงถึงบรรทัดที่มีการเปลี่ยนแปลง โดยใช้เครื่องหมาย < นำหน้าบรรทัดที่หายไป และ > นำหน้าบรรทัดที่เพิ่มมาแทน

อย่างไรก็ตามการเก็บ Version ในรูป Patch อาจมีความเสี่ยงต่อการทำ Patch บาง Patch หาย จนทำให้ไม่สามารถประกอบร่าง Source Code เพื่อกลับไปยัง Version ต่างๆ ได้

Local Version Control System

เพื่อแก้ปัญหาดังที่กล่าวมา จึงมีการพัฒนา  Version Control System ที่มี Database เฉพาะคอยจัดเก็บทุกการเปลี่ยนแปลงของ Source Code โดยเราจะเรียกการจัดเก็บ Version ของ Source Code ลง Database ว่าการ "Check-In" และการเรียกคืน Source Code จาก Database เพื่อทำงานต่อว่าการ "Check-Out"

Local Version Control System เป็น Version Control ในยุคแรกๆ ที่มีความสามารถในการจัดเก็บ Version (Check-In) พร้อมทั้งข้อความช่วยจำ (Log Message) ลง Database และเรียกคืน Version จาก Database (Check-Out) กลับมายังพื้นที่ทำงาน (Working Directory) เพื่อให้ Software developers แก้ไข Source Code ต่อไป โดยเราสามารถมอง Local Version Control System ได้อีกแบบดังภาพด้านล่าง

Local Version Control System : ภาพจาก https://git-scm.com

แต่การ Check-Out จากผู้ใช้หลายคนพร้อมกันอาจทำให้เกิดปัญหาขึ้นดังภาพด้านล่าง

เมื่อวิธวินท์ และกันตพร Check-Out Source Code ออกจาก Database แต่วิธวินท์ทำงานเสร็จก่อนจึงได้ Check-In กลับเป็นคนแรก เมื่อกันตพร ทำงานของตนเองเสร็จจึง Check-In บ้าง ในกรณีนี้เนื้อหาที่เพิ่งถูกเพิ่มโดย วิธวินท์ใน Version ก่อนหน้าจะถูกลบทิ้ง

เพื่อแก้ปัญหาการสูญเสียข้อมูลเมื่อมีการ Check-Out จากผู้ใช้หลายคนจึงต้องมีการ Lock Database ไว้ ไม่ให้ผู้ใช้ที่ทำงานเสร็จช้ากว่า สามารถ Check-In ตามหลังได้ ซึ่งทำให้เป็นข้อจำกัดสำคัญของ Local Version Control System

Centralized Version Control System

Version Control ในยุคต่อมาจึงพยายามแก้ปัญหาการใช้งานหลายคน โดยเก็บ Database ไว้บน Server เมื่อผู้ใช้ Check-Out งาน version เดียวกัน แล้วกลับมา Check-In  ระบบจะพยายามรวมเนื้อหาเข้าด้วยกัน (Merge) ถ้ารูปแบบการรวมเนื้อหามีความเรียบง่าย ระบบจะ Merge ให้อัตโนมัติ แต่ถ้าการรวมมีความซับซ้อน ระบบจะแจ้งให้ผู้ใช้ผู้ตัดสินใจแทน

โดยเราสามารถมอง Centralized Version Control System ได้ดังภาพด้านล่าง

Centralized version control : ภาพจาก https://git-scm.com

Centralized Version Control System ที่ได้รับความนิยมคือ Subversion (SVN) ซึ่งถูกพัฒนามาเมื่อปี 2000 และจนถึงทุกวันนี้ก็ยังมีผู้ใช้งานอยู่บ้าง

Distributed Version Control System

อย่างไรก็ตาม Centralized Version Control System มีข้อเสียสำคัญคือมันเป็นการทำงานแบบรวมศูนย์ หาก Server ล่มไปชั่วขณะ ผู้ใช้งานจะไม่สามารถ Check-In หรือ Check-Out งานได้ ถ้า Server เสียหายถาวร Version ของ Source Code ทั้งหมดก็ได้รับผลกระทบด้วย

เพราะการดึงงานจาก Centralized Version Control System จะเป็นการ Check-Out เฉพาะเวอร์ชั่น แบบ Online ขณะที่ Distributed Version Control System จะแก้ปัญหาการทำงานแบบรวมศูนย์โดยการ Clone Database มาทั้งหมด (โดยเราจะเรียก Database ที่จัดเก็บ Version ของ Source Code ว่า Repository)

ซึ่งเมื่อ Clone มาแล้วเราสามารถ Check-In และ Check-Out ใน Local Host แบบ Offline ก่อนจะ Push ขึ้นสู่ Server ในภายหลัง

โดยเราสามารถมอง Distributed Version Control System ได้ดังภาพด้านล่าง

Distributed version control : ภาพจาก https://git-scm.com

Distributed Version Control System ที่สำคัญตัวหนึ่ง คือ BitKeeper ซึ่งเป็น Closed Source ไม่ใช่ Open Source โดย BitKeeper ได้ถูกนำมาใช้ในการเก็บ Source Code ของระบบปฏิบัติการ Linux ในปี 2002 แบบให้ใช้ฟรี อย่างไรก็ตามในปี 2005 BitKeeper ไม่ฟรีอีกต่อไป ถ้าเราเป็น Linus Torvalds ผู้ก่อตั้ง Linux เราจะแก้ปัญหานี้อย่างไร

สำหรับ Linus แล้ววิธีแก้ปัญหาของเขาคือการพัฒนา Distributed Version Control System ขึ้นมาเองในชื่อว่า Git  และจากจุดนี้เอง Git จึงถือกำเนิดขึ้นมาในปี 2005 และเปิดให้ใช้งานแบบ Open Source และ Free Software ตั้งแต่นั้นเป็นต้นมา

ขอขอบคุณ Nipa.Cloud ที่ให้การสนับสนุน Environment ในการเรียนการสอน
รายวิชา Dev-Ops and Cloud Engineering 101