เรามาลองใช้ Git Command ระดับกลาง (หรือสูง) กันมั้ยครับ: stash, squash, rebase
Kanin James Kearpimy
Posted on March 2, 2022
หากว่าเราพูดถึง git สำหรับคนเริ่มต้น คงจะหนีไม่พ้นคำสั่งต่างๆ เหล่านี้
- git add . // เพิ่ม files ที่ถูกแก้เข้า staged change
- git commit -m "message" // เพิ่ม staged change files เข้า commit history
git push & git pull _// syncing ระหว่าง local (เครื่องที่บ้าน) กับ remote (เครื่องบน server ของผู้ให้บริการ เช่น github)
_
วันนี้เราจะลองดูอีก 3 คำสั่งที่ใช้กันค่อนข้างบ่อย เมื่อเริ่มคุ้นชินกับการทำงานของ git มากขึ้นgit stash
git squash
git rebase
git stash
ลองนึกถึงสถานการณ์ที่พวกเรากำลังแก้ไฟล์อยู่ และทำไปได้ระดับหนึ่งแล้วแต่บังเอิญว่ามีงานด่วนเข้ามา และเราต้องหันไปทำงานนั้นทันที ปัญหาจะเกิดดังนี้ครับ
1) ยังมี change files ที่ยังไม่เสร็จ และยัง commit ไม่ได้ เพราะอาจจะเกิดผลเสียมากกว่าข้อดี
2) เราสามารถสร้าง branch ใหม่ให้เก็บ change ของเราได้ แต่ก็เปลืองอยู่ดี
ในกรณีแบบนี้ git stash จะมีประโยชน์มาก เพราะสิ่งที่ git stash ทำจะเป็นการ save ตัว change files ของเราเอาไว้ใน local แต่จะไม่ถือว่าเป็น commit ทำให้สามารถสลับไปทำงานอื่นและ syncing ข้อมูลกับ remote ได้อย่างอิสระ (เพราะอย่างไร change ก็ไม่ปนขึ้นไปด้วยอยู่ดี)
โดยเมื่อต้องการทำ git stash
ให้ทำการเพิ่มทุก files ที่ต้องการเข้าสู่ staged change (git add
) ก่อน จากนั้นให้พิมพ์คำสั่ง git stash
เพื่อ save เก็บไว้ในเครื่อง (ตามภาพด้านล่าง)
จากนั้นเมื่อทำการ git status (หรือ gst) อีกครั้งจะเห็นได้ว่า change file ได้หายไป (ถูกเก็บเข้า stash) เรียบร้อยแล้ว ซึ่งเราสามารถสลับไปทำ features อื่นได้โดยไม่ต้องกังวลถึง change files อีก โดยสามารถเช็คได้ว่าเรามี change files ที่ stash ไว้กี่ครั้ง สามารถทำได้โดยคำสั่ง
git stash list
และเมื่อต้องการนำสิ่งที่ stash ไปกลับมาเพื่อแก้ไข พัฒนาต่อเราสามารถใช้คำสั่ง
git stash apply stash@{i}
// โดย i คือตัวเลขของ stash order ซึ่ง stash ล่าสุดจะไล่จากน้อยไปมาก เช่น stash@{0} คือ stash ที่ถูกเพิ่มล่าสุด
เพียงเท่านี้ก็จะสามารถจัดการกับ change ที่เราต้องการ แต่ยังไม่อยาก commit ได้แล้ว
git squash
ในสถานการณ์ที่ เรามีการทำงานบน features ใดๆ ไม่ใช่เรื่องแปลกที่จะมีการ commit อยู่บ่อยครั้ง เพื่อความสะดวกในการติดตามการเปลี่ยนแปลง ซึ่งในบางครั้ง เมื่อรู้สึกตัวอีกที commit history ของเราก็หน้าตาเช่นด้านล่างไปแล้ว
เราจะสังเกตุได้ว่า มี commits 3 ครั้งคือ
- init squash
- set up init config in squash.txt
- modify config in squash.txt
ซึ่ง messages ทั้ง 3 ครั้งนี้ รวมถึงตัว source code เองมีความใกล้เคียงกันมาก หากเราทำงานในทีมขนาดใหญ่ การทำให้ commit history มีความกระชับและง่ายต่อการติดตาม เป็นเรื่องที่สำคัญอย่างหลีกเลี่ยงไม่ได้
และ git squash
จะเข้ามาแก้ปัญหาข้างต้นครับ โดยปกติการทำกิจ squash ทักจะใช้คู่กับ git rebase หรือ git merge โดยเราจะใช้ git rebase ในตัวอย่างนี้ เพื่อ rebase squash นั้นวิธีที่ง่ายที่สุดคือใช้ interactive mode ของ git rebase โดยใช้งานคำสั่ง
git rebase [commit hash] -i
// โดย hash คือตัว commit ที่เราต้องการ rebase กลับไป
จากรูปด้านบน เราจะ squash 3 commits เข้าด้วยกัน
หลังพิมพ์คำสั่ง terminal จะเปิดหน้าจอให้เราเลือกว่าจะ squash ตัวใด และตัวใดจะเป็น hash ที่รอรับการ squash ซึ่งเราเลือก hash bdfaf72
สำหรับรองรับ commit ที่กำลังจะถูก squash
- s, squash คือการเลือก commit นั้นๆ ให้ถูกมัดรวม
- p, pick คือการเลือก commit นั้นๆ ให้เป็นที่รองรับ squash commit
จากนั้นตัว terminal (git) จะเปิดหน้าต่างให้เราเลือก commit message ของการ squash
หลังเสร็จสิ้นการ squash เราจะสังเกตุได้ว่า commits ทั้ง 3 ตัวนั้นหายไปและมี commit ใหม่ที่เกิดจากการ squash ขึ้นมาแทนเรียบร้อยแล้ว
git rebase
เมื่อคำสั่งที่ผ่านมา เราได้ใช้ git rebase ไปบ้างแล้ว แต่จริงๆ คำสั่ง git rebase เขาเอาไว้ทำอะไรกันแน่ละ
ลองนึกถึงกรณีที่ระหว่างการพัฒนา ทีมของเรา commit code บางอย่างเข้ามาใน branch main และไม่มีใครสังเกตุ จนกระทั่งเวลาผ่านไป พึ่งรู้ว่ามีปัญหาอยู่ใน source code และต้องการแก้อย่างเร่งด่วน ประเด็นคือ เราไม่สามารถอยู่ๆ ไปไล่ลบ commit ออกได้เลย เพราะ commit ดังกล่าวก็มีคำสั่งอื่นๆ ที่จำเป็นอยู่ด้วย
โดยเราสามารถเลือกแก้ได้หลายแบบ โดยวิธีที่กำลังจะทำก็คือ
- checkout กลับไปยัง commit ที่ต้องการแก้
- แตก branch ใหม่ และแก้ปัญหา
เมื่อทราบ commit ที่ต้องการแก้แล้ว ให้ทำการ checkout กลับไปที่ hash ดังกล่าว
git checkout d0ec37e
จากนั้นให้ทำการแก้สิ่งที่ต้องการและแตก branch แยกออกมา
ซึ่งเมื่อสังเกตุจะเห็นได้ว่า history ของ git นั้นมีบางส่วนหายไป (อิงจากรูปด้านบน) คือ bd3b066
และ eebae51
ซึ่งกรณีนี้นั้น
หากเรา merge main branch ทันที สิ่งที่เกิดขึ้นคือ ตัว history ของเราใน branch นี้จะหายไป (ซึ่งนำไปสู่การตาม track ที่ยากขึ้น)
แต่หากเราใช้ git rebase สิ่งที่เกิดขึ้นคือ git จะนำ history ของ change มาต่อส่วนหัวของ branch ที่เราต้องการ rebase ทำให้ history ไม่หายไป (และตาม track ง่ายขึ้น)
โดยเราสามารถพิมพ์คำสั่ง
git rebase [target branch name] [current branch]
git rebase main fixed-critical-001
และหากเรา git log --oneline
อีกครั้ง เราจะพบว่า history ที่หายไปถูกนำมารวมกลับใน branch ใหม่แล้ว
Posted on March 2, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 30, 2024