สวัสดีฮะ วันนี้เราจะมาทำความรู้จักกับ Git กันอย่างคร่าวๆ (เขียนสลับๆทั้ง git หรือ Git ในโพสต์นะ) จริงๆ แล้วมีโพสต์ที่แนะนำ Git ที่เขียนเป็นภาษาไทยจากหลายแหล่งที่ดีมากๆ ยกตัวอย่างเช่น บล็อกนี้โดย @nuuneoi และ git ฉบับอนุบาล 2 ในโพสต์นี้เราจะว่าด้วยประเด็นสำคัญๆ 5 อย่างคือ ทำไมเราต้องใช้ Git, ประวัติที่มาที่ไปกว่าจะมาเป็น Git, Distributed Version Control คืออะไร, ใครควรใช้ Git บ้าง และ work flow ของ Git เป็นยังไง (เนื้อหาส่วนมากเราปรับแต่งมาจาก lynda.com และอีกหลายแหล่งในภาษาอังกฤษ) โพสต์นี้ถือเป็นการเพิ่มเติมให้โพสต์เกี่ยวกับ Git ที่มีอยู่แล้ว และหวังว่าจะทำให้คนเข้าใจหลักการการทำงานของ Git ได้อย่างดีขึ้นไปอีก
ส่วนในโพสต์หน้าๆ เราจะมาลองเขียนโปรเจกต์โดยใช้ Git และ GitHub กัน และเราจะอธิบายรายละเอียดปลีกย่อยเช่น stash, fetch, merge และอื่นๆ รอติดตามกันต่อไปในโพสต์หน้าๆ ฮะ
ทำไมถึง Git?
- ก่อนอื่นเลย เวลาเราเขียนโค้ดหรือต้องการเก็บไฟล์ บางทีเราอาจต้องการติดตามการเปลี่ยนแปลงของไฟล์ เช่นสำหรับ text file เราอยากจะเก็บความเปลี่ยนแปลงของ text ที่เราแก้ และกลับมาดูเวอร์ชันที่เราเก็บไว้ได้ เช่นเวอร์ชัน 1, 2, 3, … และเราต้องการเปรียบเทียบความแตกต่างของไฟล์เวอร์ชันต่างๆ ได้ เราอยากกลับไปดูได้ว่ามีอะไรเปลี่ยนแปลงไปบ้างในแต่ละเวอร์ชันของไฟล์ โดยวิธีการจัดเก็บไฟล์แบบนี้เรียกง่ายๆ ว่า Version Control Systen (VCS) นั่นเอง
- ในบางครั้งเราอาจเก็บไฟล์โดยใช้ชื่อประมาณแบบนี้
my_document_v3.xls
,Logo_v2.gif
ถ้าใช้ git ปัญหาการใช้เซฟไฟล์แบบใช้เวอร์ชันห้อยท้ายก็จะหายไปโดยสิ้นเชิง เพราะเราสามารถย้ายกลับไปยังเวอร์ชันต่างๆ ของไฟล์ได้นั่นเอง คือเราเก็บแค่my_document.xls
และก็กลับไปดู revision ต่างๆ ที่เราเคยแก้ไว้ได้ - นอกจากนี้ Git ก็มีไว้สำหรับการใส่ฟีเจอร์ต่างๆ ในโค้ดของโปรเจกต์ แก้บั้กในโค้ด หลักๆ ก็คือสำหรับ Git เราสามารถแตก branch ของโปรเจกต์ที่ทำอยู่เพื่อเพิ่มฟีเจอร์ต่างๆ เข้าไปได้ และเอามารวมกับโปรเจกต์หลักได้หลังจากเราพัฒนาเสร็จ โดยไม่รบกวนโปรเจกต์หลัก (เราจะว่าถึง branch กันต่อไปในโพสต์หน้าๆ)
- จริงๆ แล้ว Microsoft Word หรือ Adobe Photoshop หรือแม้แต่ Wikipedia ก็มีฟีเจอร์แบบเดียวกัน เพื่อเก็บ history ของโค้ดหรือ document ถ้าลองเข้าไปใน Wikipedia เราจะสามารถเข้าไปดู revision ต่างๆ ที่คนเคยแก้ตั้งแต่ต้นจนถึงปัจจุบันได้
- ฟังก์ชันการย้อนกลับไปดู history ของเอกสารนี้ทำงานคล้ายกับ undo หรือ
ctrl + z
บน Windows หรือcommand + z
บน Mac นั่นเอง
ประวัติก่อนจะมาเป็น Git
โอเค ก่อนเราจะเข้าสู่ Git เบื้องต้น เราจะบอกว่า git ไม่ใช่ version control system ที่เกิดขึ้นอันแรกบนโลก สมัยก่อนหน้าเรามี Version Control Systen ที่ใช้กันมาก่อนจะมาเป็น Git หลายอย่างมากๆ เราลองมาดูกันเลยว่า มีอะไรบ้าง
- ปี 1972 Source Code Control System (SCCS) พัฒนาโดย Marc Rochkind จาก Bell Labs เพื่อใช้งานกับ IBM computer ในยุคนั้น SCCS ถูกใช้งานเป็นที่แพร่หลายกันในมหาวิทยาลัย ข้อดีคือฟรี แต่ยังเป็น close source ส่วนวิธีการเซฟไฟล์ของ SCCS คือเซฟไฟล์ต้นฉบับและ changes ของเวอร์ชันถัดๆ ไป ไม่ได้เซฟไฟล์เต็มของแต่ละเวอร์ชัน ทำให้ประหยัดเนื้อที่ของไฟล์ขึ้น แน่นอนว่าข้อเสียคือถ้าเราเปลี่ยนแปลงไฟล์ไปหลายๆ ครั้ง การดึงไฟล์กลับมาจะยิ่งช้าขึ้นเพราะเราเก็บต้นฉบับกับการเปลี่ยนแปลงจนมาถึงปัจจุบัน
- ปี 1982 Revision Control System (RCS) ได้เปิดใช้งาน พัฒนาโดย Walter F. Tichy ในขณะที่อยู่ที่ Purdue University โดย RCS ดีกว่า SCCS ที่เริ่มใช้ได้ทั้ง UNIX และ PC ส่วนวิธีทำงาน คล้ายกับ SCCS แต่ว่าเซฟไฟล์ฉบับที่แก้ท้ายสุด และเก็บ changes ถอยหลังไปสู่ไฟล์เวอร์ชันแรก
- ปี 1986-1990 Concurrent Version System (CVS) ซึ่งพัฒนาโดย Dick Grune ได้รับความนิยมมากๆ จาก community เพราะเป็น open source โดยได้เผยแพร่ภายใต้ GNU Public License (GPL) ซึ่งถือว่าเป็น License ที่เปิดกว้างมากๆ อันนึง, CVS นี้เริ่มมีการเอา source code วางไปบน remote repositories และให้คนจากหลายที่แก้ไฟล์เดียวกันในเวลาเดียวกันได้ (concurrent ตามชื่อ) และคนสามารถเริ่มแชร์และทำงานร่วมกันบนไฟล์เดียวกันได้ ส่วนข้อเสียของ CVS ก็ยังมีคือ CVS สามารถติดตามได้แค่ไฟล์เดียว ไม่สามารถติดตามเป็น folder ได้
- ปี 2000 Apache Subversion (SVN) ออกมาเป็น free software เช่นกัน ภายใต้ Apache License ซึ่งมีข้อดีกว่า CVS คือติดตาม changes เป็น directory ได้ ดังนั้น ถึงแม้จะเปลี่ยน folder name SVN ก็ยังแทร็กความเปลี่ยนแปลงได้
- ปี 2000 เดียวกันนี่เอง BitKeeper SCM ได้ออกมาและเป็น distributed version control (เราจะอธิบายถัดไป) โดย Larray McVoy แต่ว่าเป็น closed source หรือ proprietary software ในช่วงแรก community version ใช้ได้อย่างฟรีๆ และ BitKeeper ได้ถูกนำมาใช้ใน Linux ตั้งแต่ปี 2002-2005 ซึ่งถือได้ว่าใช้กันอย่างแพร่หลายในหมู่ผู้ใช้ Linux แต่ว่าความน่ากลัวคือ BitKeeper เป็น proprietary software ซึ่งทำให้คนที่ใช้ Linux กลัวมากๆ ในยุคนั้น ผู้ใช้ Linux กลัวว่าถ้า BitKeeper หักหลังขึ้นมาเปลี่ยน community version จากฟรีเป็นคิดเงิน พวกเค้าก็จะไม่มี version control ใช้…
- และเหตุการณ์ก็เป็นจริงในปี 2005 community version ของ BitKeeper ไม่ฟรีอีกต่อไปตามคาด ในปีเดียวกันนั้นเอง Linus Torvalds (ผู้ก่อตั้ง Linux ซึ่งเฮียแกเป็น programming god) จึงคิด git ขึ้นมาในเดือนเมษาปี 2005 เพื่อใช้สำหรับ Linux kernel นั่นเอง
- ปี 2005 Git ตามประวัติข้างบนก็ได้เกิดขึ้นโดย Linus Torvalds, git เป็น distributed version control นอกจากนี้ยังเป็น open source, free software ซึ่งใช้ได้ในเกือบทุก OS platform ทั้ง Linux, Mac OS X, Windows เหล่า community สามารถเข้าไปแก้โค้ดของ git ได้ และ git ยังเร็วกว่า SVN เกือบ 100 เท่าอีกด้วย ทำให้หลังจากนั้นไม่นาน Git ก็เริ่มฮิตในหมู่โปรแกรมเมอร์เป็นต้นมา
- ปี 2008 GitHub ได้เกิดขึ้นเพื่อใช้ host git repositories โดย Github เติบโตอย่างรวดเร็ว เช่นเดียวกับ git
- ปี 2011 Github มี 2,000,000 repositories (1,100,000 Github projects + 900,000 Gists) ลองดูข้อมูลสถิติได้จาก ที่นี่
- ในปัจจุบัน Github เป็นที่ host open-source software ของบริษัทเทคโนโลยีต่างๆ มากมาย ได้แก่ Google, Facebook, Microsoft, มหาวิทยาลัย, government และอื่นๆ อีกมากมาย รวมถึงภาษาโปรแกรมมิ่งที่เป็น open source ต่างๆ เช่น Python และ libraries ที่เกี่ยวข้องอีกมาก
- นอกจาก Github ที่ใช้ host git repo แล้วก็ยังมีอีกหลายบริษัทหรือเว็บไซต์ที่เกิดขึ้นเพื่อใช้ host git repo เช่น Bitbucket, GitLab และอื่นๆ แต่ส่วนมากคนนิยม Github และ Bitbucket ซึ่งถ้าเป็นนักเรียนจะสามารถสมัคร Github Education ได้ ส่วน BitBucket ก็มีจุดเด่นเช่นสร้าง private repository ได้ไม่อั้นอะไรแบบนั้น
ทำไมต้อง distributed version control แล้วมันดีกว่า centralized version control ยังไง?
- ทั้ง SCCS, RCS, CVS, SVN ที่กล่าวในช่วงแรกทั้งหมดนั้นใช้ central code repository model คือหมายความง่ายๆ ว่า changes ของ file ทั้งหมดถูกเก็บอยู่ที่ central repo หรือศูนย์กลางที่เดียว ถ้าสมมติว่า central repo เกิดพังขึ้นมาหรือผู้ใช้ไม่สามารถติดต่อกับ central repo ได้ก็จะทำให้ไม่สามารถดึงไฟล์ที่พึ่งเปลี่ยนแปลงมาทีตัวเองได้
- ส่วน distributed version control ที่ใช้ใน BitKeeper และ git นั้น แต่ละคนจะมี copy ของไฟล์ตั้งแต่เริ่มแรกจนท้ายสุด ดังนั้นแต่ละทีมหรือแต่ละคนสามารถ maintain code ได้โดยที่ทุกคนมี copy ของไฟล์ทั้งหมดอยู่ที่ local computer และ change set ของแต่ละ version ที่เกิดขึ้นจากหลายๆ ทีมนั้นสามารถรวมกันได้ ไม่จำเป็นต้องรอ changes copy จาก central repo อีกต่อไป
- ดังนั้น distributed version control จึงเร็วกว่า และผู้ใช้งานก็สามารถแก้ได้ทุกที่ โดยไม่จำเป็นจะต้องติดต่อกับ central repo ก็ได้
- นอกจากนี้เรายังสามารถ fork projects ได้ด้วย แปลง่ายๆ คือดึงโปรเจกต์มาอยู่ในชื่อเราเพื่อแก้ไขในแบบที่เราต้องการหรือใช้สำหรับแก้โค้ดและส่งกลับไปให้กับเจ้าของที่พัฒนาโค้ดก็ได้ การ fork ในที่นี้คือการยอมให้ outside developers นำโค้ดของผู้พัฒนาไปแก้และ pull request กลับไปให้ผู้พัฒนานั่นเอง
ใครควรใช้ Git บ้าง?
- Git นั้นถูกพัฒนามาสำหรับใครก็ได้ที่ต้องการเก็บเวอร์ชันหรือ revision ของไฟล์ ไม่ใช่แค่ programmer แต่อาจจะเป็น text file สำหรับนักเขียนก็ได้
- Git ใช้ track changes โปรแกรมภาษาอะไรก็ได้ ตั้งแต่ html, CSS, Javascript, Python, Java, txt และอีกมากมาย
- แต่ถึงกระนั้น Git ก็ไม่สามารถติดตามไฟล์ได้ทุกชนิด คือ Git ไม่สามารถ track ไฟล์ไบนารี เช่น ไฟล์ภาพ ไฟล์เสียง หรือ PDF ได้ เพราะ Git ไม่รู้ว่าจะ track changes ในไฟล์เหล่านี้ยังไง ในที่นี้ Git จะเก็บ version เต็มๆ ของแต่ละเวอร์ชันของไฟล์ภาพหรือเสียงไว้ ซึ่งทำให้ไม่ประหยัดเนื้อที่ของการเก็บไฟล์นั่นเอง
Install Git ได้ที่ไหน ยังไงบ้าง?
- เราสามารถใช้ command line บน Terminal ทั้งใน Mac, Windows, Linux ในการ install git ได้อย่างไม่ยากมาก (ในช่วงเริ่มต้นพวกเราแนะนำให้ใช้ command line มากกว่าที่จะใช้ GUI Application เพราะจะได้รู้รายละเอียดที่แท้จริงของ git)
- การ install Git นั้นไม่ยากเลย เราเพียงแค่ต้องดาวน์โหลด Package Management System เข้ามาใน Terminal นั่นเอง อย่างบน Mac OSX ที่คนใช้หลักๆ ก็ได้แก่ Homebrew หรือ MacPorts โดยหลังจากที่โหลดมาแล้ว เราแค่พิมพ์
brew install git
(สำหรับ Homebrew) หรือport install git
(สำหรับ MacPorts) ก็จะได้ git มาอยู่บนเครื่องง่ายๆ - สำหรับการ install Git บน Ubuntu เราจะใช้
apt-get
หรือพิมพ์apt-get install git
ไปบน Terminal - แต่ว่า Git ก็มี GUI Application ให้เลือกเช่นกัน ได้แก่ Git GUI, Gitk ดูเพิ่มเติมได้ที่ https://git-scm.com/download/gui/linux
ลองอ่านเพิ่มเติมได้ที่เว็บนี้ https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
Git Work Flow
พูดถึงประวัติและเบื้องต้นของ Git ไปซะเยอะ เราจะมาเกริ่นถึง work flow ของ Git ก่อนที่เราจะลองใช้ Git กันอย่างจริงจังในโพสต์หน้าเล็กน้อย ข้างล่างนี้เราใส่ diagram การทำงานของ Git ให้ดูคร่าวๆ
- Work Flow ที่ใช้สำหรับ Git นี้เรียกว่า 3-tree architecture หมายความง่ายๆ ว่า Git แบ่งสถานะของไฟล์เป็น 3 สถานะหลักๆ คือ working state, staging state, repository state ซึ่งทั้งหมดนี้สามารถจัดการอยู่ใน local computer ของเราได้เลย เราเพิ่ม remote repository เข้าไปด้วย เพราะทุกวันนี้โปรเจกต์ส่วนมากถูกอัพขึ้นไปบน remote repo เช่น Github หรือ Bitbucket ซะส่วนใหญ่
- ถ้าเราพูดรวมถึง remote repository ด้วย เราชอบเรียกว่ามี 3+1 state เพราะว่ารวมถึงตอนเราผลักไฟล์ขึ้นไปที่ remote repository ด้วย เช่น Github หรือ Bitbucket
- ขั้นตอนหลักๆ ของการย้ายไฟล์จาก working state ไปถึง repository state เป็นประมาณนี้ ตอนแรกเราจะต้องเริ่มด้วยโฟลเดอร์ที่มี
.git
ไฟล์ก่อน (git init
) หลังจากนั้นเมื่อเราแก้ไฟล์ หรือ make changes แล้วเราสามารถย้ายไฟล์นั้นไปใน staging โดย add ไฟล์นั้น ใช้คำสั่งgit add <filename>
(การ add นี่ทำได้หลายๆ ครั้ง เช่นเราต้องการเพิ่มไฟล์ที่พึ่งแก้ใหม่เข้าไปก็ได้), หลังจากนั้นเราสามารถย้ายไฟล์จาก staging ไปยัง repository ได้โดยใช้คำสั่ง commit ซึ่งส่วนมากเราจะใส่คอมเม้นเล็กๆ ไว้ด้วยว่าแก้อะไรไปบ้างระหว่าง commit นี้ - แต่ละ commit ที่เราใช้ Git จะเก็บ hashtag ไว้ (เรียกว่า SHA hash) เป็นตัวเลขและตัวหนังสือประมาณนี้
1bd8dwa...
ซึ่งเอาไว้ใช้ refer ถึง commit ที่เราเขียนไว้ได้ - หลังจากเรา commit แล้วเนี่ยตอนนี้ทุกการแก้ไขทั้งหมดยังอยู่ในคอมพิวเตอร์ของเรา หรือคือยังอยู่ใน local นั่นเอง เราจะ commit กี่รอบก็ได้ตามแต่ที่ชอบ และเมื่อเรา commit จนพอใจแล้วอยากจะย้ายการแก้ไขทั้งหมดไปยัง remote repository (ไปบน Github หรือ Bitbucket) เพื่อให้เพื่อนร่วมงานหรือคนอื่นๆ ดูได้ ก็เพียงใช้คำสั่ง
git push
การแก้ไขที่เรา commit ไว้ก็จะถูกย้ายไปยัง remote repository
ทิ้งท้าย
สำหรับโพสต์นี้เราได้อธิบายความเป็นมาก่อนจะมาเป็น Git ในปัจจุบัน แต่ยังไม่ได้ลงรายละเอียดเล็กๆ น้อยๆ อีกมากมาย เช่น เราจะเขียน command line เพื่อย้ายไฟล์ไปยังสถานะต่างๆ ยังไง หรือว่าถ้า remote repository เกิดการเปลี่ยนแปลง เราจะดึงข้อมูลนั้นลงมาที่ local ยังไง เป็นต้น และยังไม่รวมถึงอีกมากมาย ซึ่งเราจะค่อยๆ เอามาอธิบายในโพสต์ถัดๆ ไป