ลองดูผลของ git status ที่ผ่านมา สังเกตไหมว่า เราอยู่ที่ branch ชื่อ master เอ๋มันคืออะไรน้าาา?
"จากข้อความของ git status ข้างต้น branch ที่เราสนใจอยู่นี้มีชื่อว่า master คือต้องบอกเพื่อนๆว่า สมบัติอย่างหนึ่งของ git ก็คือการแตกสาขาการพัฒนาออกไปอย่างกว้างขวาง กล่าวคือ สมมติเพื่อนๆมี project ที่ต้องคนมากกว่าหนึ่งคนร่วมกันพัฒนา และพัฒนากันคนละส่วน (ไม้ในไฟล์เดียวกัน) เพื่อนๆสามารถแยก branch ของ project นี้ออกเป็นหลายแขนงได้ และให้แต่ละแขนงพัฒนาโค้ดในส่วนของตัวเองไปเรื่อยๆ โดยไม่ต้องห่วงว่ามันจะไปกระทบแขนงอื่น ทำให้เราพัฒนางานไฟล์เดียวกันได้ในหลายส่วนในเวลาเดียวกัน !!! ฮั่นเช้ สุดท้ายเจ้าแขนงก็จะประกอบรวมกลับเขามาใน branch เดิม นี่จึงเรียกว่าเป็นหนึ่งข้อดีที่ดีงามล้ำเลิศ"
"เรื่องนี้ก็คือการแตก branch หรือกิ่งสาขาออกไปเพื่อจัดการกับปัญหาที่เกิด หรือบางที่อาจใช้คำว่าแบ่งงานกันทำก็ได้ ในขณะที่เวลาของพวกเขาเดินไปพร้อมๆกัน"
ทบทวนกันก่อนนะ
เพื่อนๆจำกันได้ใช่ไหม git ไม่เก็บ ความแตกต่าง ของไฟล์ที่ถูกแก้ไขไปแล้ว (doesn't store data as a series of change-sets or differences) แต่มันเก็บไฟล์ที่ถูกแก้นั้นเป็น series of snapshots
การ commit ลงถังแต่ละครั้งเพื่อนๆก็ทราบแล้วว่าจะมีปมเกิดขึ้น (เห็นใน source tree) ปมเหล่านั้นก็คือ snapshot ของไฟล์ที่ถูกเปลี่ยนแปลงในสถานะ staged
พูดกันให้ละเอียดคือ git จะสร้าง object ขึ้นมาตัวหนึ่งเพื่อเก็บ meta data สำคัญเพื่อใช้อ้างอิงไปยัง snapshot ต่างๆ ซึ่ง object ดังกล่าวนี้จะเก็บชื่อผู้ทำ (author's name) แล้วก็ email ของเขา เราจะได้รู้ไงว่าใครเป็นคน committed
นอกจากนี้ยังเก็บ message ที่เราเคยพิมพ์ไปว่า -m ลงไปด้วย เพื่อใช้อธิบายว่าการ commiit ครั้งนี้เกี่ยวกับอะไร หรือทำอะไรก็ว่าไป
ขออธิบายด้วยภาพนะครับ สมมตินี่เป็นการ commit ครั้งเดียว โดยคุณที่ชื่อ Scott และเขาเขียน description ว่า The initial commit of my project
ส่วนตัวเลขสมมติที่เขียนว่า 92ec2 นั้นเป็น pointer เพื่อชี้ไปว่ามันกำลังให้ความสำคัญกับสิ่งอื่นและ 98ca9 ด้านบนสุดนั้นคือตัวมันบนหน่วยความจำหลัก (RAM)
ในตัวอย่างเขามีไฟล์อยู่สามไฟล์ ได้แก่
- README
- test.rb
- LICENSE
จากนั้นเพื่อนๆก็ส่งมันเข้าไปใน staging area การณ์นี้ git จะสร้าง checksum หรือก็คืออัลกอริทึม SHA-1 ขึ้นคำนวณในแต่ละ sub directory (folder ย่อยต่างๆ) ซึ่งไม่มีทางซ้ำกัน เท่ากับว่าได้สร้าง version ถัดไปเกิดขึ้น ด้วยทั้งหมดนี้เก็บใน git repository
ง่ายๆคือ เราสร้างไฟล์ขึ้นมาสามไฟล์แล้ว commit มันลงถัง ไฟล์เหล่านี้จะมีชนิดเป็น blob ให้หน้าตาของทั้งสามไฟล์ที่ถูกจัดการเป็น blob แล้วในถังดังนี้
ส่วนใน staging area ก็มี snapshot เกิดขึ้น (ไม่แน่ใจว่าเกือบจะพร้อมกัน) มันก็จะสร้าง root project tree ด้วย ดังนี้
เจ้า snapshot ที่เกิดก็จะมี pointer อ้างอิงไปยัง blob ทั้งสาม ส่วนตัวเองนั้นก็ถูก pointer อ้างอิงมาจาก commit object รวมกันเป็นภาพใหญ่อย่างนี้
สรุปว่าภาพนี้คือการ commit หนึ่งครั้งกับไฟล์สามไฟล์
- เกิด commit object 1 object สีขาว
- เกิด root project tree ซึ่งจะถูกทำเป็น snapshot เก็บเป็น version ไว้ สีเขียว
- ไฟล์ทั้งสามถูกจัดเก็บแบบ blob สีส้มๆ
***เพิ่มเติม
เราพูดถึง checksum ถูกต้องไหม ซึ่งจะกระทำทุกครั้งเมื่อมีไฟล์ถูกเลือกให้ staged ใน staging area และโดยหลักการทั่วไปแล้วไฟล์เหล่านั้นก็มีแต่จะเพิ่มขึ้นเรื่อยๆ ส่วนตัวก็ยังไม่รู้ว่าการ re-create สร้าง snapshot เกี่ยวข้องอย่างไรกับ root project tree แต่เอาเป็นว่า git จะสร้าง snapshot ขึ้นตรงนี้แหละครับ
สมมติว่าเพื่อนอ้อย ยังคงทำงานกับตัวอย่างนี้ต่อไปแล้ว commit เป็นครั้งที่สอง ก็จะเกิดภาพลักษณะแบบนี้ (ซ้ายสุดคือครั้งแรกที่ commit)
เห็นไหม commit ในครั้งที่สองจะชี้ไปที่ commit ในครั้งแรก สักเกตที่ matadata ชื่อ parent จะเป็นตัวบอกว่า commit ก่อนหน้าคือใคร
และหากเพื่อน commit เป็นครั้งที่สามล่ะ ?
ทีนี้ก็มาถึงเรื่อง branch กันบ้าง จำได้ไหมทุกครั้งที่เราเรียก git status มันจะบอกว่าเรากำลังทำงานอยู่ที่ branch อะไร อะดู
อะแต่เดี๋ยวกัน (ถ้าท่านโทรมาในสิบสายนี้) อะ ผมจะลองเล่น gi gui หน่อย ดุว่าหน้าตามันเป็นอย่างไร แต่พอดูแล้ว ผมก็อยากดูหน้าตาของ git bash
เห็นไหม มันบอกว่าเราอยู่ที่ branch ชื่อ master และเมื่อเราย่อภาพจำลอง commit object ลงให้เป็นแบบนี้ เพื่อนๆดูนะ ว่า master branch เราอยู่ตรงไหน
ตำราบอกว่า master branch นั้นจะ move forward ไปเรื่อยๆกับ commit ล่าสุด ดังนั้นตัวมันจะชี้ไปที่ commit ชื่อ f30ab นะครับ โดยตรงนี้เมื่อทำ snapshot ก็มีหมายเลขเวอร์ชันเกิดขึ้นด้วยอยู่แล้ว
ใครที่เคยเขียน data structrue (โครงสร้างข้อมูล) อารมณ์มันก็คือ LinkedList ตัวหนึ่งที่ถูก desgin ต่างออกไป
ทีนี้การจะแบ่ง branch นั้นเราจะดูว่า pointer ที่ชื่อ header นั้นกำลังชี้ที่ branch อะไร โดยธรรมดาแล้ว header pointer นั้นจะชี้ master branch ไว้เสมอ (เพราะเรายังไม่เคยสั่งให้มันไปชี้ที่ branch อื่น)
ฉะนั้นการสร้าง branch ใหม่ก็คือการสร้าง pointer ชื่อใหม่ขึ้นมาชี้ยัง commit ล่าสุดเท่านั้นเอง
สั่ง commit profile.html ให้เรียบร้อยก่อน
จากนั้นผมจะสร้าง pointer ตัวใหม่ชื่อ testing เพื่อแตกเป็น branch ใหม่
พิมพ์ git branch testing
คำสั่งนี้เป็นการสร้าง branch ใหม่เท่านั้น มีชื่อว่า testing แต่ยังไม่ได้ย้ายการทำงานไปยัง branch ใหม่ เราทำงานที่ branch อะไรให้ดู header pointer ว่ากำลังชี้อยู่ที่ branch ไหน
จากตัวอย่างนี้ header pointer ยังคงอยู่กับ master branch ครับ
ถ้าเราดูในรูปนี้ของ source tree เราจะเห็นว่า header pointer ชี้ที่ master ส่วน branch ใหม่ก็คือ testing
ให้เพื่อนๆลองพิมพ์
git log
ก็จะเห็นรายละเอียดของ branch และจุดเชื่อมโยงต่างๆ
ต่อไปเราจะ switch branch จากที่เคยอยู่ master มาเป็น testing มันก็คือการย้ายที่ชี้ดีๆนี่เอง
พิมพ์
git checkout testing
ตอนนี้ header pointer ชี้ที่ testing branch เรียบร้อยแล้ว ไม่ว่าจะแก้ไขไฟล์หรือเพิ่มไฟล์ใหม่ การ commit ก็จะไปเป็นของ testing branch โดยปริยาย
ผมจะแก้ไขไฟล์ index.html เพิ่มโค้ดเข้าไปเล็กน้อย จากนั้นจะใช้ git add และ git commit ตามที่เรียนรู้มา
เจ้า source tree ทำงานกับ IO นะครับ ดังนั้นเพื่อนๆอาจไม่เห็นผลการเปลี่ยนแปลง UI ในทันที ให้เพื่อนๆกดที่ drop-down ที่เขียนว่า all branches ด้านบนมุมซ้ายในภาพสลับไปมา
เราจะได้ภาพแบบนี้
ต่อไปให้ลอง switch กลับไปที่ master branch อีกครั้ง การทำแบบนี้เท่ากับเพื่อนๆได้กลับไปใช้ version เก่านั่นเอง
นี่ไง version control system คือทำงาน version ใหม่ไปเรื่อยๆเพื่อแตกขยายงาน หรือแก้ issue ต่างๆ หรือจะกลับไปยัง version ก่อนหน้าก็ได้ เพื่อแตกขยายงานใหม่ หรือยกเลิกงานที่เคยแตกสาขาไปแล้ว
การกลับมายัง master branch เท่ากับได้ reverted ประดาไฟล์ทั้งหลายที่อยู่ใน working directory กล่าวคือได้กลับมายัง snapshot เดิมที่เคยทำไว้แล้ว ดังนั้นให้เพื่อนๆแน่ใจว่าจะทำงานที่ branch เก่าจริงๆนะ เพราะสิ่งที่ git จะเห็นใน working directory ของเพื่อนๆจะเป็นภาพตาม snapshot ที่ถูกย้อนกลับมานั่นเองครับ
ผมสั่งกลับมาที่ mater branch
git checkout master
จากนั้นผมแก้ไข index.html อีกครั้งแบบนี้
อ่อ เห็นไหม we are strong หายไปแล้ว เพราะผม reverted กลับมาหาของเก่า version เก่ากว่า
ภาพที่ได้จะเป็นแบบนี้
และนี่คือสิ่งที่ current branch เห็น คือเห็นตาม header pointer ที่ชี้ไปยัง master branch ครับ
อะพอแล้ว โอกาสต่อไปเราจะมาเรียนรู้การรวม branch ที่แตกย่อยออกมานี้เข้าด้วยกัน สายการพัฒนาจะได้รวมมาบรรจบกัน สวัสดี
ไม่มีความคิดเห็น:
แสดงความคิดเห็น