Geeky Academy: Git 4 Geeks Part II

ในที่สุดก็ได้เวลาเขียนซะที หลังจากที่ได้ลองใช้สิ่งที่พี่ดีนสอน มากขึ้นในการเรียนครั้งนี้ ...
ใครพึ่งเข้ามา Blog นี้ ควรจะอ่าน Part I ก่อนนะครับ

Geeky Academy: Git 4 Geeks Part I

เอาล่ะ มาเริ่มจากการทบทวนของเก่ากันบ้าง ในประเด็นที่ผมไม่ได้เขียนใน Part I 

svn add != git add

การสั่ง svn add จะเป็นการ Tracked File นั้นๆ ไปเลย แต่ git add จะเป็นการไฟล์เข้าพื้นที่ที่เรียกว่า staging area ซึ่งจะเป็นพื้นที่ ที่จะกลายเป็น commit ในอนาคต เราจะได้ภาพแบบนี้ เมื่อเราทำการสั่ง git add 


จุดที่เขียนว่า INDEX นั่นล่ะครับ เรียกว่า Staging Area จนกว่าเราจะ commit ก็จะกลายเป็น commit ที่ 5 แล้วย้าย Pointer ของ HEAD และ Master ไปชี้ต่อ 


$ git diff และ $ git diff --cache



การทำงานของ Git นั้น เราจะแบ่งออกเป็น 3 สถานะ นั่นคือ ขณะที่เราแก้ไขไฟล์ (working directory) จากนั้นเราสร้าง snapshop ด้วยคำสั่ง git add (staging area) และเราทำการ commit (ส่วนนี้จะเรียกว่า repository)
ตามภาพเลย git diff จะเป็นการเทียบความเปลี่ยนแปลงระหว่าง Working Directory และ Staging Area แต่ git diff --cache นั้นจะเป็นการเทียบ staging area กับ commit ล่าสุดในขณะนั้น

แก้ไขไฟล์ไปแล้ว แต่ตรงไหนบ้างก็ไม่รู้ จะย้อนกลับทำยังไง ? (ยังไม่ได้สั่ง $ git add)

ง่ายมากเลย ลอง $ git status ดูว่ามีไฟล์ไหนเปลี่ยนแปลงบ้าง จากนั้นก็ใช้คำสั่ง
$ git checkout -- filename
หรือถ้าต้องการย้อนทั้งหมด
$ git checkout -- .
แล้วถ้ามีการสร้างไฟล์ใหม่ขึ้นมาด้วยล่ะ ?
$ git clean -df
จะเป็นการลบทุกไฟล์ที่ไม่ได้ถูก track ออกทั้งหมด

แล้วถ้าสั่ง $ git add ไปแล้วล่ะ ? 
อย่างที่เราเคยเขียนไปก่อนหน้านี้ การสั่ง $ git add หมายถึงเรานำไฟล์ที่ถูกแก้ไขเข้า Staging Area ดังนั้น เราต้องนำมันลงจาก Staging Area ไปที่ Working Directory เสียก่อน โดยใช้คำสั่ง
$ git reset HEAD filename
หรือ 
$ git reset HEAD .
Git Branching

อีกเรื่องที่สำคัญ และเป็นจุดเด่นมากๆ ของ Git นั่นคือการทำ Branching หรือการแตกกิ่งนั่นแหละ (ตรงตัวเลย) ประโยชน์ของมันก็อย่างเช่น ถ้านาย A ทำงานอยู่ และนาย B ต้องการจะทำ Feature A โดยที่จะแยกกันทำ นาย B ก็จะแตก Branch A ออกมา ก็จะทำให้การทำงานของนาย A และ B ไม่ Conflict กันในแต่ละ commit ที่เกิดขึ้น จนกว่าทั้งสองคนจะนำ Code มารวมกัน 

โดยการทำ Branching ไม่เคยอยู่ใน Architecture ของการสร้าง SVN แต่อย่างใด มีคนบางอาจจะบอกว่า "มันก็เหมือนกันแหละ" มาดูผ่านภาพน่ารักๆ กันครับ ว่าต่างกันอย่าง แล้วทำไมการทำ Branching ใน Git จึงทำได้ง่ายและเร็วกว่าหลายเท่าตัว


จากภาพนี้คือการทำ Branching บน SVN โดยที่เพิ่ม Feature1 เพิ่ม commit ที่ 5 เข้าไปจะเห็นว่า เวลาแตก Branch เป็นเรื่องที่ช้ามาก เนื่องจากเป็นการก๊อบทั้ง Trunk ออกมา และด้วยความที่เป็นแบบนี้ชาว SVN ทั้งหลาย เลยขยาดการ commit บ่อยๆ ลองนึกสภาพตอน merge สิครับ จะต้องใช้เวลาเท่าไหร่ ?

คราวนี้มาดูฝั่ง Git บ้าง ว่าการทำ Branching เป็นอย่างไร


เท่านี้เองครับ เนื่องจากพื้นฐานของ Git เป็น Pointer ดังนั้นก็แค่สร้าง Branch Pointer ขึ้นมาใหม่ ชี้อีกจุดหนึ่ง (ในภาพนี้เป็นกรณีที่ commit Feature1 ไปแล้วหนึ่งครั้ง) 

แล้วเราจะแตก Branch ได้อย่างไร ? การสร้าง Branch ใหม่เราจะใช้คำสั่ง
$ git branch branchName
และเราสามารถย้ายไปทำงานบน Branch ดังกล่าวได้ด้วยคำสั่ง 
$ git checkout branchName
นอกจากนั้น เราสามารถรวบ 2 คำสั่งนี้ได้ด้วยการใช้คำสั่ง
$ git checkout -b branchName
การใช้คำสั่งพื้นฐานเหล่านี้ในการสร้าง Branch เป็นการที่เราแตก Branch ออกจาก commit ที่เราอยู่ (HEAD Pointer) แล้วถ้าอยากแตก Branch ออกจาก commit ที่ไม่ใช่ commit ปัจจุบันล่ะ ? 
$ git checkout -b branchName HEAD~[number]
number จะเป็นตัวเลข เช่นถ้า 1 ก็จะแตก Branch จาก commit ก่อนหน้า ในส่วนของ HEAD~[number] เราสามารถใส่เป็น SHA1 ก็ได้ จะได้ไม่ต้องมานั่งนับกัน เมื่ออยากแตกออกจาก commit แรกๆ

ซึ่ง SHA1 ที่ว่าดูได้จากนี่เลย กรอบแดงๆ น่ะ



แล้วเมื่อทำงานบน Branch Feature1 (ยึดตามภาพข้างบนนะ) ที่แตกออกไปเสร็จแล้ว จะรวม Code กลับมาที่ Master Branch ทำอย่างไรดี เริ่มแรกให้เรากลับมายัง Master Branch ก่อน โดยใช้คำสั่ง
$ git checkout master
จากนั้นก็ทำการ merge ข้อมูลจาก Branch Feature1 โดยใช้คำสั่ง
$ git merge feature1
จะมี 2 กรณีที่เกิดขึ้นในการ Merging นั่นคือ Conflict และ Fast Forward Effect แต่เดี๋ยวเราจะมาคุยกันในเรื่องการ Merge อีกที โดยที่เราจะจบ Blog นี้ด้วยการอธิบาย Fast Forwad Effect ไว้ก่อนแล้วกัน

Fast Forward Effect เป็นพฤติกรรมของการที่แตก Branch ออกไปทำงาน และในการ Merge เข้ามาที่ Branch ใดๆ นั้น Git คำนวณแล้วว่า ไม่มีการเกิด Conflict ระหว่างไฟล์ใดๆ ก็ตามในการ Merge จึงสามารถนำ commit ที่เกิดขึ้นใน Branch ที่แตกออกไปทำงาน มาต่อได้เลย

สุดท้ายเมื่อเราทำการ Merge Branch เรียบร้อยแล้ว ก็ควรที่จะลบ Branch นั้นทิ้งซะ โดยการลบ Branch ใดๆ นั้นเราจะใช้คำสั่ง
$ git branch -d branchName
แน่นอนว่าเราแตก Branch ด้วยแนวคิดของใช้ Pointer 
ดังนั้นการลบ Branch ก็เป็นลบ Pointer Branch ดังกล่าว เท่านั้นเอง 

Popular posts from this blog

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

"อีสุกอีใส" ประสบการณ์เมื่อต้องมาเป็นตอนอายุ 22

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