มาเรียนรู้ Git แบบง่ายๆกันเถอะ

นี่ก็ปี 2017 แล้วนะ ยังไม่ใช้ Git อีกหรอ?

เนื้อหาของ Git ในบทความนี้ จะเน้นสำหรับสายโค้ดเป็นหลักนะจ๊ะ

มาพูดถึง Version Control Systems (VCS) กันก่อน

ในยุคนี้ต้องบอกเลยว่า Version Control ถือว่าเป็นหนึ่งในคุณสมบัติพื้นฐานของ Developer ก็ว่าได้ โดยเฉพาะอย่างยิ่งบริษัทที่ต้องทำงานร่วมกันเป็นทีม (ถึงจะพัฒนาคนเดียว ก็ควรจะใช้เหมือนกันนะ)

4 Developer กับ 4 Feature ระดับเทพ
รวมโค้ดของนาย A และ B เข้าด้วยกันก่อน ส่วนนาย C กับ D นั่งรอยาวๆไปนะ
  • ช่วยรวมโค้ดจากหลายๆคนเข้าด้วยกันให้ง่ายขึ้น ดูได้ว่าโค้ดเดิมคืออะไร และแก้ไขเป็นอะไร
  • เมื่อเกิดปัญหาก็สามารถติดตามดูประวัติการแก้ไขโค้ดในแต่ละไฟล์แต่ละบรรทัดได้ง่าย
  • ช่วยให้สามารถจัดการโปรเจคได้อย่างเป็นระบบ ไม่แก้โค้ดสะเปะสะปะ มองโค้ดแต่ละส่วนเป็นฟีเจอร์ ไม่เขียนโค้ดข้ามฟีเจอร์ไปมาในโค้ดชุดเดียวกัน
  • เป็น Backup ไปในตัว ไม่ต้องกลัวเวลาโค้ดมีปัญหาแล้วต้อง Rollback กลับไปใช้โค้ดชุดเก่า และใช้พื้นที่ในการเก็บข้อมูลน้อยเมื่อเทียบกับการ Backup แบบเก็บทั้งโปรเจคไว้ทุกครั้งที่ทำการ Backup
  • สามารถ Track การทำงานของทุกคนภายในทีมได้จาก History

Git ทำงานยังไง?

จริงๆมัน็คือการทำงานแบบ Distributed Version Control Systems นั่นแหละ (อยากรู้รายละเอียดมากกว่านี้ก็สามารถเอา Keyword นี้ไปหาข้อมูลเพิ่มเติมได้เลย)

https://git-scm.com/images/branching-illustration@2x.png
ให้นึกภาพแบบนี้ก่อน

Git ออกแบบมาให้ทำงานกระจายแบบไม่มีศูนย์กลาง ทุกเครื่องทำงานเป็น VCS ด้วยตัวเองได้

นั่นหมายความว่าไม่จำเป็นต้องมี Server กลางก็ได้ สามารถใช้เครื่องส่วนตัวทำเป็น VCS ได้เลย แต่ถ้าต้องทำงานร่วมกันหลายๆเครื่อง ก็ต้องใช้ Server เป็นตัวกลางในการรวมข้อมูล

แต่ละเครื่องทำงานเป็น VCS อยู่แล้ว
สามารถใช้ Server หลายตัวทำเป็น VCS ได้เหมือนกันนะ

Git จะ Sync ข้อมูลเมื่อเราสั่งเท่านั้น

ขั้นตอนการ Sync ข้อมูลของ Git เดี๋ยวจะพูดถึงในภายหลัง ขอเน้นไปที่ภาพรวมของการทำงานก่อน

ใครไวกว่าก็สบายไป
ต้องดึงโค้ดมารวมกับโค้ดของตัวเองให้เรียบร้อยก่อน ถึงจะ Sync ขึ้น Remote ได้

การเรียกใช้งาน Git

มีอยู่ 2 แบบหลักๆก็คือ Command Line กับ GUI

สายโหดก็จัดแบบ Command Line กันไป
ขี้เกียจพิมพ์ก็ใช้ Git GUI อย่าง SourceTree เอา
Android Studio ก็มี
Xcode ก็มา

Server สำหรับให้บริการ Git (Version Control Repository Hosting Service)

การใช้ Git ให้เกิดประโยชน์ที่สุดก็คงต้องมี Server ที่ทำหน้าที่เป็น VCS ด้วย ซึ่งในปัจจุบันนี้ก็มีทางเลือกมากมายไม่ว่าจะใช้บริการจากเว็ปต่างๆหรือตั้ง Server ขึ้นมาเอง

GitHub บ้านหลังแรกสำหรับผู้ใช้ Git ทุกๆคน

คำต่างๆที่จะต้องรู้จักเมื่อใช้งาน Git (ชุดที่ 1)

ขอแบ่งเป็นหลายๆชุด เพื่อที่จะได้อธิบายการทำงานทีละส่วนให้เข้าใจได้ง่ายขึ้น

  • Clone
  • Commit
  • Unstaged
  • Staged
  • Push
  • Pull
  • Fetch
  • Conflict
  • Merge Commit

Repository

เวลาที่เราพัฒนาโปรแกรมซักตัว เราจะต้องสร้างสิ่งที่เรียกว่า Project ซึ่งการสร้าง Project สำหรับใช้งาน Git จะเรียกว่า Repository ครับ

Clone

เวลาที่ผู้อ่านมี Repository อยู่บน Remote ซักแห่งอยู่แล้ว และต้องการ Sync มาลงเครื่องของเรา เราจะต้องทำสิ่งที่เรียกว่า Clone Repository หรือก็คือการก๊อป Repository จาก Remote มาลงเครื่องนั่นเอง

Commit

เวลาที่มีข้อมูลที่แก้ไขเสร็จแล้ว (โค้ดที่เขียนคำสั่งบางอย่างเสร็จแล้ว) แล้วอยากจะทำการ Backup เก็บไว้ใน VCS จะเรียกกันว่า Commit ครับ

เขียนโค้ดเสร็จชุดหนึ่งก็ทำการ Commit เก็บไว้ เขียนชุดต่อไปก็ Commit เก็บไว้อีก ทำเช่นนี้ไปเรื่อยๆ
แต่ละ Commit จะจำไว้ว่าไฟล์ไหนมีการแก้ไขอะไรบ้าง — ภาพจากใน SourceTree

Unstaged และ Staged

ขอพูดถึง 2 คำนี้ไปพร้อมๆกันเลยละกัน

แก้ไขโค้ด (ไฟล์จะอยู่ใน Unstaged อัตโนมัติ) > เลือกไฟล์ที่ต้องการเข้า Staged > Commit

Push

เวลาที่มี Commit อยู่ในเครื่องและต้องการจะ Sync ขึ้นไปเก็บไว้ใน Remote จะเรียกขั้นตอนนี้ว่า Push

Push : ส่ง Commit จาก Client ขึ้นไปเก็บไว้ที่ Remote ด้วย

Pull

เวลา Sync จาก Remote เพื่อดึงข้อมูล Commit ใหม่ๆลงมาเก็บไว้ในเครื่องจะเรียกขั้นตอนนี้ว่า Pull

Pull : ดึง Commit ใหม่ๆจาก Remote มาเก็บไว้ใน Client ด้วย

Fetch

ในบางครั้งเราอาจจะไม่ต้องการ Pull ข้อมูลลงมาเก็บไว้ในเครื่องทันที แค่อยากเช็คสถานะของ Remote เฉยๆว่ามีใคร Push ข้อมูลใหม่ขึ้นไปที่ Remote หรือป่าว เราเรียกวิธีนี้ว่า Fetch ครับ ซึ่งการ Fetch จะทำให้เราสามารถอัพเดทและดู History ทั้งหมดที่อยู่บน Remote ได้ โดยไม่ต้องดึงข้อมูลลงมา

Fetch : อยากรู้ว่ามี Commit ใหม่ๆบน Remote มั้ย แต่ไม่ต้องดึงข้อมูล

Merge Commit

สมมติว่านาย A กับนาย B เขียนโค้ดด้วยกันอยู่ และทั้งคู่ก็เขียนโค้ดที่อยู่ในไฟล์เดียวกัน

นาย A เพิ่ม method2 ต่อท้าย method1 ส่วนนาย B ลบ method1 ออก แล้วเพิ่ม method3 กับ method4 เข้าไป
นาย B ทำการ Push ข้อมูลขึ้น Remote
“Push ก่อนได้เปรียบ” นาย B ไม่ได้กล่าวไว้
โค้ดของนาย A และ B แก้ที่บรรทัดเดียวกัน แต่โค้ดไม่เหมือนกัน
// โค้ดเดิม
void main() {
method1();
}
// โค้ดที่นาย A แก้ไข
void main() {
method2();
method1();
}
// โค้ดที่นาย B แก้ไข
void main() {
method1();
method3();
}
void main() {
method2(); // โค้ดของนาย A
method1();
method3(); // โค้ดของนาย B
}

Conflict

ในขณะที่กำลังจะ Merge อยู่นั้น จะเห็นว่าโค้ดของนาย A และนาย B มันชนกัน ไปแก้โค้ดที่เดียวกัน ดังนั้น Git จะแจ้งว่าเกิด Conflict หรือก็คือโค้ดที่ทับซ้อนกันนั่นเอง

Conflict กันแน่นอน~
void main() {
<<<<<<< HEAD
method1();
method2();
=======
method3();
method4();
>>>>>>> 322d39a003e4d9...
}
  • โค้ดที่อยู่ระหว่าง === และ >>> คือโค้ดของนาย B ส่วนตัวเลขต่อท้ายคือหมายเลขของ Commit ที่ทำการ Merge
void main() {
method2();
method3();
method4();
}
  • Conflict เกิดขึ้น
  • แก้ไขโค้ดให้เหมาะสม
  • Merge Commit
  • Push ขึ้น Remote

สรุปวัฏจักรของ Git ในชุดแรก

เวลาพัฒนาโปรแกรมซักตัวก็จะมีขั้นตอนแบบนี้

  • เลือกไฟล์ที่ต้องการเข้า Staged
  • Commit
  • เขียนโค้ดต่อ
  • เลือกไฟล์ที่ต้องการเข้า Staged
  • Commit
  • วนลูปไปเรื่อยๆจนกว่างานจะเสร็จ
  • ถ้ามีก็จะต้อง Pull โค้ดก่อน แล้ว Merge Commit ให้เรียบร้อย
  • Push ข้อมูลขึ้น Remote
  • Pull เพื่อดึงข้อมูลมาไว้ในเครื่อง
  • เกิด Conflict
  • แก้ไขโค้ดให้เหมาะสม
  • Merge Commit
  • Push ข้อมูลขึ้น Remote

เขียนโค้ดไปจนถึงเมื่อไรถึงจะต้อง Commit?

อันนี้น่าจะเป็นคำถามที่เกิดขึ้นบ่อยกับนักพัฒนามือใหม่ที่กำลังเริ่มต้นเรียนรู้และหัดใช้งาน Git กับโปรเจคของตัวเอง

  • “Commit”
  • “Refactor”

ต้อง Push เมื่อไร?

นอกเหนือจากการ Commit แล้ว การ Push ก็เป็นอีกอย่างที่หลายๆคนสงสัยเช่นกัน

คำต่างๆที่จะต้องรู้จักเมื่อใช้งาน Git (ชุดที่ 2)

เมื่อคุณรู้จักคำต่างๆของ Git ในชุดที่ 1 แล้ว นั่นหมายความว่าคุณสามารถใช้งาน Git เบื้องต้นได้แล้ว แต่นั่นก็ยังไม่พอ เพราะคำต่อไปนี้คือสิ่งที่ควรจะรู้จักและเข้าใจด้วยเช่นกัน

  • Merge Branch
  • Stash
  • Unstash
  • Git Flow
  • Tag
  • Fork
  • Pull Request

Branch

เวลาที่เรา Commit เรื่อยๆจนกลายเป็น History มันก็จะมีหน้าตาแบบนี้

แต่ละ Commit จะเรียงต่อกันเป็น Node จนกลายเป็นเส้นยาวๆ
โค้ดไม่ได้เกี่ยวข้องกัน แต่ต้องมาอยู่บน Branch เดียวกัน
แยก Branch เสร็จแล้ว ก็ตัวใครตัวมันละ

Merge Branch

เมื่อใดก็ตามที่อยากจะจับ Branch คู่ใดมา Merge รวมกัน นั่นล่ะครับ Merge Branch

เมื่อรวมโค้ดของทั้งสองเข้าด้วยกัน ความมันส์ก็เกิดขึ้น (บั๊กกระจุยสิครับ)

Stash และ Unstash

สมมติว่าโปรเจคตัวหนึ่งถูกแยกออกมาเป็น 2 Branch ด้วยกัน แล้วก็เป็นหน้าที่ของนาย A และนาย B ที่จะต้องรับผิดชอบเหมือนเคย

อะไร อะไร ก็นาย A กับนาย B ตลอด
เก็บโค้ดที่เขียนยังไม่เสร็จลงใน Stash ไว้ชั่วคราวก่อน
พอกลับมาก็ Unstash ของเก่ามาเขียนต่อ

Git Flow

ใน Development Process จริงๆนั้นมีอะไรอีกหลายๆอย่าง ไม่ว่าจะเป็นการพัฒนาหลายๆ Feature พร้อมๆกัน แต่เวลาขึ้น Production จะหยิบเฉพาะบาง Feature เท่านั้น ส่วน Feature ที่เหลือก็อาจจะพัฒนาต่อหรือปล่อยทิ้งไว้รอขึ้นในรอบหน้า รวมไปถึงขั้นตอนก่อนที่จะขึ้น Production ที่จะต้องให้ QA/Tester ทดสอบก่อน หรือการทำ Hotfix เพราะเจอบั๊กตัวใหญ่ใน Production ที่ต้องแก้ด่วน

  • develop
  • feature
  • release
  • hotfix
develop มีตัวเดียว แต่ feature จะแยกเป็น Sub Branch โดยใช้ชื่อตาม Feature นั้นๆ
Merge Branch แบบนี้ ใน Git Flow จะเรียกว่า Finish Branch
เย้ ในที่สุดวันนี้ก็มาถึง T^T
เอาโค้ดจากใน master ไปขึ้น Production ได้แล้ว เย้!
แก้บั๊กแบบด่วนจี๋
Git Flow ใน SourceTree ใช้โคตรง่ายอ่ะ บอกเลย

Tag

ถ้าดูจากที่ผมอธิบายใน Git Flow ก็จะเห็นว่าใน Master จะมี Tag อยู่ด้วย ซึ่ง Tag จะเป็นเหมือนตัวช่วยบอกว่าอันไหนอยู่ที่ Commit ไหน เพื่อที่ว่าจะได้ตามหาทีหลังได้ง่าย

หาได้ไม่ยากว่าเวอร์ชัน 1.0.7 อยู่ที่ Commit ไหน เพราะว่าใส่ Tag ไว้แล้ว
เห็นแบบนี้ก็รู้ได้ทันทีว่า Release ล่าสุดของ React คือเวอร์ชัน 15.6.1

Fork

โดยปกติแล้ว คนที่สามารถเข้าไป Commit และ Push ใน Repository ได้จะต้องเป็นคนที่ได้รับอนุญาตเท่านั้น ถึงแม้ว่าจะเป็น Public Repository ก็ตาม

Pull Request

เมื่อผมแก้บั๊กใน Repository ที่ Fork มาจาก Library ของคนอื่นแล้ว แต่ผมก็พบว่าคนอื่นที่เอา Library ของคนๆนั้นไปก็ยังเจอบั๊กเหมือนผมอยู่ดี ก็เลยอยากจะช่วยแก้บั๊กนี้ใน Library ของเค้าซะ ดังนั้นผมจึงส่ง Pull Request ไปให้ต้นทางเพื่อให้เจ้าของ Library เห็น Commit ของผมที่แก้บั๊กตัวนั้น

  • รับ Pull Request ของผมเพื่อรวม Commit ที่แก้บั๊กแล้ว เข้าไปใน Repository ของเขา

สรุป

ไม่รู้จะสรุปยังไงดี เพราะเขียนยาวเหยียดมากกกกก

https://www.pexels.com/photo/beverage-black-coffee-business-chart-33972/

ใช้ Git เถอะครับ เพื่อคุณภาพชีวิตที่ดีขึ้น

บทความเกี่ยวกับ Git ที่แนะนำให้อ่านต่อ

Lovely android developer who enjoys learning in android technology, habitual article writer about Android development for Android community in Thailand.

Lovely android developer who enjoys learning in android technology, habitual article writer about Android development for Android community in Thailand.