เคล็ดลับและเทคนิค Git
(blog.gitbutler.com)- แม้แต่ผู้ใช้ที่ใช้ Git มานานก็ยังอาจพลาด ความสามารถที่ไม่ค่อยเป็นที่รู้จัก หลายอย่าง ทำให้สมมติฐานที่ว่าความรู้คำสั่งขั้นสูงบนบรรทัดคำสั่งเป็นเรื่องแพร่หลายเริ่มสั่นคลอน
- ต่างจากคนรุ่นที่ย้ายมาจาก SVN หรือ CVS นักพัฒนาที่ใช้แต่ Git มาโดยตลอดมีโอกาสน้อยที่จะได้เรียนรู้ วิธีใช้งานขั้นสูง บางอย่าง
- Git ได้เพิ่มความสามารถเล็ก ๆ แต่มีประโยชน์อย่างต่อเนื่องตามกาลเวลา และการเปลี่ยนแปลงเหล่านี้อาจมี คุณค่าเชิงปฏิบัติ ในบางสถานการณ์
- สำหรับผู้ใช้ระดับกลางถึงขั้นสูง ได้แบ่งหัวข้อฟีเจอร์ที่เก่าแต่มีประโยชน์ ฟีเจอร์ที่เพิ่งเพิ่มเข้ามา และหัวข้อเรื่องรีโพขนาดใหญ่·โมโนรีโพ ออกเป็น ซีรีส์สั้น 3 ตอน
- หากกลับมาทบทวนความสามารถที่มองไม่เห็นจากพฤติกรรมการใช้ Git แบบคุ้นเคย ก็อาจช่วยให้จัดการงานประจำในรีโพได้อย่างมีประสิทธิภาพยิ่งขึ้น
เหตุผลที่ควรกลับมาดู Git อีกครั้ง
- ระหว่างการบรรยายเกี่ยวกับ Git และ GitButler เมื่อไม่นานมานี้ ผู้เขียนพบว่านักพัฒนาจำนวนมากยังมี สิ่งที่ไม่รู้ เกี่ยวกับ Git อยู่มาก
- เมื่อก่อนเคยบรรยายเรื่อง Git ขั้นสูง แต่ตลอดช่วงประมาณ 10 ปีที่ผ่านมา ผู้คนมักถูกมองว่ารู้ฟีเจอร์คำสั่งขั้นสูงเหล่านี้กันอยู่แล้ว
- นักพัฒนารุ่นที่ใช้แต่ Git มาโดยตลอดไม่เคยต้องย้ายจากเครื่องมืออย่าง SVN หรือ CVS มายัง Git หรือกลับไปเรียนรู้แนวคิดเดิมอีกครั้ง
- Git เองก็เรียนรู้ความสามารถใหม่ ๆ ไปตามกาลเวลา และแม้ส่วนใหญ่จะเป็นการเปลี่ยนแปลงเล็กน้อยหรือเฉพาะทาง แต่ก็อาจช่วยงานจริงได้
- บล็อกซีรีส์นี้จัดทำขึ้นจากงานนำเสนอ FOSDEM 2024 little known Git stuff
ซีรีส์เคล็ดลับ Git ที่แบ่งเป็น 3 ตอน
- กลุ่มเป้าหมายคือ ผู้ใช้ Git ระดับกลางถึงขั้นสูง และกล่าวถึงความสามารถที่อาจพลาดไปได้แม้จะใช้ Git มานานแล้วก็ตาม
- แทนที่จะรวมทุกอย่างไว้ในบทความเดียว จึงแบ่งเป็นบทความสั้น 3 ตอนตามหัวข้อย่อยต่าง ๆ
- หัวข้อที่รวมอยู่:
- Oldies but Goodies: ความสามารถของ Git ที่เก่าแต่ยังมีประโยชน์
- Some Subtle New Things: การเปลี่ยนแปลงเล็กน้อยที่เพิ่งถูกเพิ่มเข้ามาใน Git
- Really Large Repositories and Monorepos: เนื้อหาเกี่ยวกับรีโพขนาดใหญ่มากและโมโนรีโพ
- บทความแรกจะต่อเนื่องไปยัง Oldies but Goodies
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ได้คุยเรื่องสนุก ๆ กับคนฝั่ง Mercurial ด้วย และบอกว่าช่วงหลัง ๆ การเขียนบางส่วนภายในของ Hg ด้วย Rust ทำให้ได้ความเร็วเพิ่มขึ้นอย่างน่าทึ่ง
กำลังคิดถึง Pro Git ฉบับพิมพ์ครั้งที่ 3 อยู่ด้วย หากมีเรื่องที่ได้เรียนรู้มาอย่างยากลำบากเกี่ยวกับ Git หรือเรื่องที่อยากรู้ ก็ขอให้บอกมา
difftasticแทน diff ของ Git ก็ดี: https://difftastic.wilfred.me.uk/alias ใน
gitconfigที่ใช้บ่อยคือfza,gone,rootโดยgit fzaจะแสดงไฟล์ที่แก้ไข/ไฟล์ใหม่ในหน้าต่างfzfแล้วส่งไฟล์ที่เลือกต่อให้git add: https://github.com/junegunn/fzfgit goneจะลบ branch local ที่ไม่มีอยู่บน remote แล้ว ส่วนgit rootจะแสดง root ของ repository จึงเหมาะเวลาจะกลับไปยัง root จาก directory ลึก ๆ ช่วงนี้ใช้zoxideเลยใช้น้อยลง: https://github.com/ajeetdsouza/zoxidegit blameพังhttps://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revltrevgt
เช่น ระหว่าง rebase แค่ลบ commit หนึ่งออก แต่ไม่เข้าใจว่าทำไม commit หลังจากนั้นทั้งหมดถึงเปลี่ยนไป ท้ายที่สุดจึงเข้าใจว่าแม้การจัดเก็บจะอิง snapshot แต่การดำเนินงานอิง diff หลังจากนั้นถึงเข้าใจ rebase และเวลาสอน หากเน้นจุดนี้มากขึ้นก็น่าจะช่วยได้
เคารพคนที่ชอบ Git แต่มันเป็นแค่เครื่องมือที่ต้องใช้สำหรับผม
checkout/commit/pushพื้นฐานไปแล้ว ถ้ารู้บางอย่าง โดยเฉพาะอย่าง การเขียนประวัติใหม่ คุณภาพของ commit history จะดีขึ้นมาก และวิศวกรคนอื่นในโปรเจกต์จะเข้าใจ flow ได้ง่ายขึ้นGit ดูเหมือนจะเป็นค่าคงที่ที่อยู่ในวงการไปอีกนาน และเป็นหนึ่งในเครื่องมือที่แตะบ่อยที่สุดในการพัฒนารายวัน จึงคุ้มค่าที่จะลองดูสักหน่อย
ดังนั้นผมคิดว่า ความซับซ้อน ของ Git ในระดับหนึ่งก็ไม่เป็นไร
core.fsmonitorจากมุมมองของ monorepo ขนาดใหญ่ อยากให้git cloneมีตัวเลือก resumeในยุค 2000 เคยเจอปัญหาเดียวกันตอนพยายาม clone kernel repository ผ่านการเชื่อมต่อ bandwidth ต่ำ และหลังจากขอความช่วยเหลือใน mailing list ก็มีคนเอา repository ทั้งหมดเป็น tar บีบอัดขึ้นไว้บนเว็บส่วนตัวให้ จึงค่อยดาวน์โหลดได้
ทุกวันนี้ถ้า VPN บริษัทหลุดชั่วคราว ก็ยังเกิดปัญหาแบบเดียวกันเป็นครั้งคราวตอน clone repository ใหญ่ ๆ ลองนึกภาพว่าดาวน์โหลด repository ของ Windows ขนาด 300GB ไปแล้ว 95% แล้ว Wi‑Fi หลุดแวบหนึ่ง
แปลกที่ Git กับ Docker ซึ่งเป็นสองเครื่องมือที่ใช้ bandwidth มากในสแตกการพัฒนาสมัยใหม่ กลับไม่รองรับการดาวน์โหลดแบบ resume อย่างเหมาะสม
https://git-scm.com/docs/git-bundle
คล้ายกับการบอกว่าอยากได้ภาษา low-level ที่ซ่อนความซับซ้อนของระบบ ซึ่งจริง ๆ แล้วสองอย่างนี้แทบจะขัดกันเอง Git น่าพอใจและไม่ได้เรียนยากขนาดนั้น ดังนั้นบางส่วนก็ควรแค่เรียน Git
มันเปิดกล่องดำที่นักพัฒนาหลายคนรู้สึกเวลาใช้ terminal ออกไป วางกราฟไว้ด้านหน้า และแสดงการทำ rebase ให้เห็นเป็นภาพอย่างเป็นธรรมชาติ ทำให้ Git สนุกขึ้น
ความชำนาญ CLI ยังมีคุณค่าอยู่ แต่พอเห็นนักพัฒนาประสบการณ์ 10 ปีติดขัดกับปัญหาพื้นฐาน หรือทำ history ของโปรเจกต์พังเพราะบรรยากาศแบบ “ถ้าเป็นวิศวกรตัวจริงต้องใช้ Git CLI เท่านั้น” ก็รู้สึกหงุดหงิด
ทุกวันนี้ถึงจะใช้ CLI ก็ยังบอกให้เปิดกราฟดูในหน้าต่างอื่นทั้งวัน ซึ่งทำได้ฟรีใน VS Code, JetBrains และแม้แต่ใน CLI
เพราะเมื่อเพื่อนร่วมทีม merge PR ผมก็จะเห็นทันทีแล้ว rebase branch ของตัวเอง ทำให้ branch อัปเดตอยู่บนฐาน
mainเสมอ จึงไม่ต้องเจอนรกของการ merge หรือทิ้ง commit “fix conflicts” แย่ ๆ ไว้ระหว่างหาว่าไฟล์ 10 อันดับแรกที่ถูกแก้ไขมากที่สุดหลังจากสร้างเมื่อวานคือไฟล์ไหน ก็เจอ https://github.com/tj/git-extras/blob/main/Commands.md
มี คำสั่งเสริมของ Git ที่น่าใช้หลายอย่าง
git-extrasดีเลย อีกเครื่องมือที่ใช้ได้คือ git absorb: https://github.com/tummychow/git-absorbไม่ค่อยเข้าใจว่าทำไมนักพัฒนาส่วนใหญ่ถึงยืนกรานจะใช้ Git CLI ทั้งที่ client แบบ UI สมัยใหม่อย่าง GitKraken ก็ใช้งานได้ดีและช่วยได้มากพอ: https://www.gitkraken.com/
ไม่ได้ต่อต้าน GUI แบบสิ้นเชิง แต่ตอนนี้ CLI มีประสิทธิภาพกว่า และไม่อยากเสียเวลาไปหา GUI ที่ตรงเงื่อนไขต่อไปนี้
ต้องดูดี เป็นแอป native ที่ไม่ใช่แค่ยัดเว็บเบราว์เซอร์เก่า ๆ เข้ามา ไม่มี telemetry หรือปิดเป็นค่าเริ่มต้น เป็นโอเพนซอร์สเต็มรูปแบบ และคาดหวังได้ว่าจะไม่หายไปในอีก 5 ปี
อีกทั้งต้องไม่ทำให้สับสนกว่าเดิม ที่บริษัทเก่าเคยต้องใช้ Visual Studio แล้วมีปุ่มหนึ่งที่จริง ๆ หมายถึง “ทำเครื่องหมายว่าแก้ conflict แล้ว” แต่กลับเขียนชวนหวาด ๆ ว่า “Accept merge”
ไม่ควรทำให้คนที่คาดหวังว่าคำบางคำมีความหมายเฉพาะต้องสับสน และพฤติกรรมอย่างปุ่ม “Commit changes” ที่ทำตัวเหมือนจะช่วย แต่ดัน push ไป remote ด้วย ก็ไว้ใจได้ยาก
ถ้าต้องสลับไปโปรแกรมอื่นเพื่อทำ commit เดียว แรงจูงใจที่จะ commit บ่อย ๆ ก็ลดลง
push,pull,checkoutเลยรู้สึกว่าการใช้ GUI มันเกินจำเป็นเวลาผมใช้ Git บน CLI ส่วนใหญ่ก็ไม่ได้มีอะไรพิเศษ แค่ไม่กี่คำสั่ง ส่วน tip หรือ trick ที่ไม่ค่อยได้ใช้ก็จดไว้ในไฟล์ข้อความ
รู้จัก
-committerdateอยู่แล้ว แต่ไม่รู้ว่าตั้งเป็นการเรียงลำดับค่าเริ่มต้นได้ และมีประโยชน์มาก มีบันทึกอยู่สองสามอย่างgit columnsถ้ามันไม่พอดีกับหน้าจอจนต้องเลื่อนดูจะค่อนข้างชวนสับสน ถ้ามีตัวเลขด้วยก็คงดีgit maintenanceดูดี แต่กังวลเพราะ rebase บ่อย อยากรู้ว่าจะเสีย loose object เร็วกว่าgcหรือเปล่า เห็นว่าgcถูกปิดอยู่ แต่ยังไม่ชัดเจนเกี่ยวกับ
git blameมีสคริปต์ที่มีประโยชน์แต่ไม่ค่อยเป็นที่รู้จักคือ https://github.com/gnddev/git-blameall มันไม่ค่อยมีคนรู้จักจนผมต้อง port ไปเป็น Python 3 เอง และผมก็ไม่ใช่นักพัฒนา Python ด้วยgcไว้ เมื่อรันmaintenance runแบบระบุเอง จึงจะเปิดเป็น taskมันไม่ได้เก็บ loose object เร็วกว่า
gcสุดท้ายก็แค่ รัน gc นั่นเองgit-blameallดูใช้ได้ น่าจะลองใช้ดูทำให้ flow การใช้ Git ง่ายขึ้นมากด้วย alias ไม่กี่ตัวที่ทำงานได้หลาย environment
git syncedจะซิงก์ branch ปัจจุบันด้วย rebase ให้ตรงกับ upstream ถ้ามี หรือกับ origin ถ้าไม่มี ใช้masterหรือmainโดยให้ความสำคัญกับmainก่อนgit pubจะเผยแพร่การเปลี่ยนแปลงไปยัง remote origin และใช้ force push แบบมี leasegit prจะเปิด URL ของ PR ที่เหมาะสมบน GitHub โดยไม่ต้องใช้ GH client ถ้ากำหนด upstream ไว้ ก็จะส่ง PR ไปทางนั้นgit hubจะเปิดหน้า GitHub ของ repositoryhttps://softwaredoug.com/blog/2022/11/09/idiot-proof-git-aliases.html
เลิกแกล้งทำเป็นรู้ว่ากำลังทำอะไร แล้วใช้ เครื่องมือ Git แบบภาพ แทน เช่น SmartGit หรือเครื่องมือที่อยู่ใน IntelliJ ผมมองว่า Git “ฮีโร่สาย command line” ออกแนวโชว์มากกว่า
ชั้นคำสั่งสำหรับผู้ใช้อาจสับสนจนน่าหงุดหงิดได้ เช่น
YoursกับTheirsอาจมีความหมายตรงข้ามกันโดยสิ้นเชิงตามบริบทอินเทอร์เฟซผู้ใช้ทั้งหมดไม่มีสไตล์หรือธีมร่วมกัน จึงต้องมีชั้นภาพใหม่เพื่อไม่ให้คนใช้แทบบ้า
ผมรู้จักแอปและ Git โดยรวมแค่เท่าที่จำเป็นกับงาน และถ้านาน ๆ ครั้งต้องการมากกว่านั้นก็ค่อยค้นหา ใช้มาหลายปีมีกรณีแบบนั้นแค่ครั้งสองครั้ง
แม้แต่งานซับซ้อนที่ต้องแก้ความผิดพลาดของคนอื่นหรือของตัวเอง ก็จะดู history, commit, reflog และ diff ด้วยเครื่องมือภาพก่อน เพื่อเข้าใจว่าอะไรพังและมีอะไรที่กู้ได้บ้าง
ถ้ามี commit เดียวที่ต้องกลับไป ก็ใช้
reset --hard; ถ้าต้องรวมอะไรบางอย่างจากหลาย commit ปกติจะใช้ command lineทั้งสองอย่างไม่ได้ขัดแย้งกันโดยสิ้นเชิง เรื่องอย่าง diff หรือ conflict ผมใช้แค่เครื่องมือแบบภาพ แต่ก็ได้เรียนรู้อะไรมากมายจากการทำความเข้าใจ commit object, reflog, สิ่งที่ rebase ทำอยู่เบื้องหลัง, interactive rebase, hard/soft reset ฯลฯ