Geeky Academy: Git 4 Geeks Part I



เมื่อก่อนเราแชร์ Open Source Software โดยใช้ Centralized SCM (Source Control Management) คือการมีเซิร์ฟเวอร์เพื่อเก็บ Code เอาไว้และใครต้องการเข้ามาทำงานก็โหลดลงไปทำงาน โดยซอฟต์แวร์ที่เป็นที่นิยมเช่น SVN แต่เนื่องจากไม่เหมาะกับ Project ที่มี Contributor (ผู้ร่วมพัฒนา) เยอะ โดยมีปัญหา เนื่องจากมี Code กลางแค่ชุดเดียว ขอยกตัวอย่าง Linux Kernel ยุคแรกๆ Linus ก็ต้องหาคนที่ไว้ใจในการที่จะส่งโค้ดไปรวมที่โค้ดกลาง (ซึ่งก็มีเพียงไม่กี่คน) แต่ Developer มีเยอะ ดังนั้นต้องให้คนที่ถูก Linus ไว้ใจช่วยกัน Review Code โดย Developer ที่ Linus เองถ้าให้ตรวจทั้งหมดก็ไม่ไหว ก็ต้องมีมือขวามาช่วยตรวจอีก ถ้า Developer เยอะขึ้นเรื่อยๆ ปัญหานี้ก็จะ Recursive ไปเรื่อยๆ นั่นเอง 

จึงทำให้ Linus เกลียดมาก เพราะสภาพการทำงานแบบ Centralized SCM ยากต่อการ Scale Linux Kernel จึงหันมาใช้ BitKeeper แทน มาช่วยให้ Linux Kernel Scale ต่อได้ แต่ก็พบข้อจำกัดต่างๆ (ส่วนใหญ่เป็นเรื่อง Comercial License) Linus และทีมจึงทำการ Reverse Engineer Protocol ของ BitKeeper จนผิด Policy และทะเลาะกันรุนแรง เลยต้องหาอะไรบางอย่าง มาทดแทน BitKeeper ที่ใช้อยู่ จนแล้วจนรอดก็หาไม่ได้ จึงต้องคิดสร้างขึ้นมาใช้เอง โดยเครื่องมือที่จะหาหรือสร้างเองต้องมีคุณสมบัติดังต่อไปนี้
  1. เป็น Source Control ที่ใช้แนวคิด Distributed เหมือน BitKeeper
  2. ประสิทธิภาพต้องดีมากๆ เพื่อรองรับ Software ขนาดใหญ่อย่าง Linux Kernel ได้
  3. Code ที่ถูกนำเข้า และส่งออกจาก Source Control ต้องมีความถูกต้อง (มีโอกาส)


Linus ถึงกับประกาศเลยว่าจะไม่พัฒนา Linux Kernel ต่อถ้าพัฒนาอะไรที่จะมาแทนที่ BitKeeper ไม่ได้โดย Version แรกของ Git เขียนเป็น Bash Script ใครอยากดูเต็มลองดูที่นี่ครับ :)

Linus Torvalds on Git: Google Tech Talk 2007
อะไรคือ Distributed Source Control Management ?
เกริ่นกันไปบ้างแล้วด้านบนตอนเล่าประวัติของ Git กับ Linux Kernel Project นะ แต่ถ้าจะให้เห็นภาพชัดขึ้นมาดูนี่กันก่อน นี่คือ Centralized SCM ที่เราพูดถึงกันเมื่อตอนต้น
จะเห็นว่าไฟล์มีชุดเดียว A อยากทำงานต้องนำโค้ดลงไปจาก Server กลางเมื่อทำงานเสร็จก็ส่งโค้ดขึ้นมา โดย B และคนอื่นๆ ก็ต้องทำแบบเดียวกัน ปัญหาคือ ถ้า Server พังล่ะ ? เราก็จะทำงานต่อไม่ได้เลย เพราะเราไม่สามารถส่งโค้ดขึ้นมาบน Server เพื่อเก็บเวอร์ชั่นได้ แล้วถ้าเป็นแบบ Districbuted ล่ะ ?
แบบนี้จะทำให้เราจบงาน ไม่ว่าจะกี่เวอร์ชันได้บนเครื่องตัวเองก่อนเสมอ เพราะเราได้ฐานข้อมูลของเวอร์ชั่นซึ่งสามารถจัดการได้เองมาด้วย เหมือนกับว่าเรามีเซิร์ฟเวอร์ที่เก็บฐานข้อมูลเวอร์ชันของไฟล์มาในเครื่องตัวเองเลย 
เมื่องานนั้นๆ เราสามารถจบได้บนเครื่องตัวเองก่อนเสมอ ก็ไม่ต้องพะวงเรื่องปัญหา Network แล้วเรียกได้ว่า เราสามารถทำงาน Offline ได้แบบ 100% เลย ถึงเวลาก็ค่อยส่งโค้ดขึ้น Remote Repository
** ทุกอย่างทำผ่าน Command Line Interface หมดนะ

เราสามารถเช็คว่าเครื่องเรามี Git แล้วหรือยัง 
โดยพิมพ์ $ git --version ซึ่งถ้ายังไม่มีให้ไป Download ได้ที่ http://git-scm.com/
$ git --version
$ git init
จะเป็นการ Create Local Repository บน Folder ปัจจุบัน
$ git clone repositoryURL
เป็นการ Clone Repository (คิดว่าเป็นการ Copy แต่มี Version Database ติดมาด้วย) ลงมาจาก Remote SCM สักแห่ง เช่น Github เป็นต้น โดยปกติแล้วเราจะต้อง Identify ทุกครั้ง ว่าเราเป็นใคร แต่เราสามารถ Clone โดยใช้ SSH (Secure Shell) Protocol ได้ โดยทำตามนี้ https://help.github.com/articles/generating-ssh-keys 
ลอง Clone Repository ผมได้เลยนะครับ :)

เมื่อ clone แล้วเราสามารถดูประวัติศาสตร์ของ Code ชุดนี้ได้จากการใช้คำสั่ง 
$ git log --oneline --graph
แต่พิมพ์แบบนี้ทุกรอบก็ดูจะเมื่อไปหน่อย มาตั้ง alias ของคำสั่งนี้กันดีกว่า โดยให้พิมพ์ว่า
$ git config --global alias.tree "log --graph --decorate --oneline --abbrev-commit"
และแถมการใส่สีให้เพื่อความน่ารัก น่าชมด้วยโดยพิมพ์
$ git config --global color-ui auto
คราวนี้มาพูดถึงการใช้งาน Git กันบ้าง เมื่อเรา Initialize Git แล้ว เราจะมองสถานที่เก็บไฟล์ของเราออกเป็น 3 แห่งนั่นคือ ... โดยจะใช้หลักการของ Snapshot ในการเก็บความเปลี่ยนแปลงที่เกิดขึ้น

  • Working Directory คือไฟล์ในขณะที่ยังไม่เกิดการเปลี่ยนแปลง
  • Staging Area คือทำ Snapshot หลังจากที่ไฟล์ใดๆ เกิดการเปลี่ยนแปลงแล้ว
  • Repository คือไฟล์หลังจากการบันทึกความเปลี่ยนแปลงด้วย Git แล้ว (เรียกว่าการ commit)

ในขณะที่เรายังไม่ได้ทำ Snapshot ของไฟล์ เราสามารถที่จะยกเลิกการเปลี่ยนแปลงที่เกิดขึ้นได้ด้วย
$ git checkout -- .
เวลาที่ต้องนำการเปลี่ยนแปลงใดๆ เก็บไว้เป็น Snapshot ที่เกิดขึ้น จะใช้คำสั่ง add ซึ่งจะมี postfix ต่างๆ
$ git add . (สนใจไฟล์ใน Current Directory ทั้งหมด)
$ git add * (สนใจไฟล์ตาม Wildcard ที่กำหนด เช่น *.rb)
$ git add -u (สนใจเฉพาะไฟล์ที่เคยบันทึกว่าถูกติดตามแล้ว)
ถ้าต้องการเปลี่ยนบันทึกสถานะของไฟล์ก็จะใช้คำสั่ง
$ git commit -m 'commit message'
โดยมากแล้ว การ  commit นั้นทำได้บ่อยมากๆ เท่าที่เราต้องการ แล้วแต่คน แต่ผมใช้หลักการที่ว่า เมื่อมีอะไร Work สักอย่าง ก็ควรจะ commit ทันที เพื่อที่จะได้เก็บ Version ที่ Work ตรงนั้นไว้ และย้อนกลับมาในจุดที่งานของเรายัง Work อยู่ได้

เมื่อเข้าใจหนึ่งรอบการทำงานบน Git แล้วเรามาจินตนาการกันสักหน่อย สมมติให้วงกลมสีฟ้าแทนเวอร์ชั่นของไฟล์แต่ละเวอร์ชั่น โดย Git จะใช้แนวคิดของการ Reference (อาจจะพูดได้ว่าเป็น Pointer หรือตัวชี้ถ้าใครเคยเรียนภาษาซีมาบ้าง) เราก็จะได้ภาพประมาณนี้
จุดแรกที่น่าสังเกตุก็คือ ในแต่ละ commit (เวอร์ชั่น) จะมี Pointer ที่ชี้มายัง parent's commit เสมอ (ใครเคยเรียน Linked List ก็น่าจะคุ้นๆ ตาอยู่บ้าง) และก็จะเห็นว่ามี Pointer อยู่ 2 ตัว คือ HEAD และ Master โดยในที่นี้ HEAD คือ Pointer พิเศษที่จะชี้ Commit ล่าสุดของ Branch ที่เราทำงานอยู่เสมอ และ Master เป็นชื่อของ Branch ที่เราทำงานอยู่ (จะอธิบายต่อไป ในเรื่องของ Branching) และด้วย Concept การทำงานแบบนี้ จึงทำให้เราย้อนไป ย้อนมาระหว่างเวอร์ชั่นใดๆ ก็ตามด้วยการเปลี่ยนการชี้ของ Pointer พิเศษเหล่านั้น โดยไม่ต้องเกิดการ Duplicate File ขึ้นมาเลย

อีกคำสั่งที่สำคัญคือการทำงานกับ Remote Repository Service เช่น Github
เมื่อคุณสมัครใช้งาน และสร้าง Remote Repository บนนั้นแล้ว ก็ต้องทำการบันทึกที่อยู่ของที่ที่จะส่ง
Repository ไปเก็บไว้ โดยใช้คำสั่ง

$ git remote add origin remoteRepositoryURL
จากนั้นก็จะสั่งส่งไฟล์ขึ้นไปด้วยคำสั่ง
$ git push origin master (*master is branch name)
จากจุดเริ่มต้นมาถึงตรงนี้ เรายังทำงานบน Master Branch เพียงอย่างเดียว เลย Default ไว้แบบนี้ก่อน
นี่คือพื้นฐานทั้งหมดของ Git ครับ ตอนต่อไป จะมาว่ากันถึงเรื่องการทำ Branching กัน

การได้เรียนกับพี่ดีน เป็นอะไรที่ดีมาก เมื่อก่อนเราใช้ Git โดยที่ไม่รู้พื้นฐานของการทำงานมันจริงๆ
ว่าเกิดอะไรขึ้นบ้าง Git ทำงานอย่างไร ... แต่พอเรารู้ Reason ทุกอย่าง ว่าอะไร ทำไม
"เมื่อเราใช้ Git อย่างมีประสิทธิภาพ เราจะสามารถแก้ประวัติศาสตร์ของเราได้" คนสอนพูดไว้ครับ

Popular posts from this blog

12 วิธี การบริการและดูแลลูกค้าในร้าน Starbucks

[Android Dev] การติดตั้ง Eclipse+AndroidSDK เพื่อพัฒนาโปรแกรมบน Android

5 TED Talk ที่จะช่วยให้คุณทำงานดีขึ้น