ข้ามไปยังเนื้อหา
Tayakorn
Git Handbook

Git Handbook

LEVEL 4 · ระดับเทพ

เครื่องมือทรงพลัง

เครื่องมือเฉพาะทางที่แก้ปัญหาซึ่งคำสั่งพื้นฐานทำได้ลำบาก รู้ไว้ว่ามีอยู่ วันที่เจอโจทย์ตรงจะนึกออก

13.1 worktree — หลายโฟลเดอร์ ประวัติเดียว

ปกติหนึ่ง repo เปิดได้ทีละ branch git worktree ให้คุณกาง branch หลายอันลงหลายโฟลเดอร์พร้อมกันโดยใช้ประวัติชุดเดียว — แก้ฟีเจอร์ที่โฟลเดอร์หนึ่ง ขณะตรวจ PR อีกโฟลเดอร์ ไม่ต้อง stash สลับไปมา:

$ git worktree add ../myapp-hotfix hotfix      # กาง branch "hotfix" ที่มีอยู่แล้วลงโฟลเดอร์ใหม่
$ git worktree add -b fix/urgent ../myapp-fix main  # หรือสร้าง branch ใหม่จาก main พร้อมกางในตัว
$ git worktree list
/path/myapp           9f2c1a8 [main]
/path/myapp-hotfix    3b7d8c1 [hotfix]
$ git worktree remove ../myapp-hotfix        # เลิกใช้แล้วเก็บโฟลเดอร์ทิ้ง

ทั้งสองโฟลเดอร์ชี้ไปที่ .git ชุดเดียวกัน — commit จาก worktree ไหนก็เห็นได้จากอีกอันทันที ต่างจากการ clone ซ้ำที่ได้ประวัติแยกกันคนละชุด

13.2 hooks — สั่งให้ Git ทำงานอัตโนมัติ

ในทุก repo มีโฟลเดอร์ .git/hooks/ สำหรับสคริปต์ที่ Git เรียกอัตโนมัติเมื่อเกิดเหตุการณ์ ที่นิยมคือ pre-commit — รันก่อน commit ทุกครั้ง ใช้ตรวจ lint หรือฟอร์แมตโค้ดให้ผ่านก่อนถึงจะ commit ได้ ป้องกันงานเสียเข้าประวัติตั้งแต่ต้นทาง:

# .git/hooks/pre-commit — ตั้งชื่อไฟล์ให้ตรงเป๊ะ ไม่มีนามสกุล แล้ว chmod +x ให้รันได้
#!/bin/sh
npm run lint || { echo "lint ไม่ผ่าน — commit ถูกยกเลิก"; exit 1; }

ถ้าสคริปต์จบด้วย exit code ที่ไม่ใช่ 0 Git จะยกเลิก commit ทันที — ยังไม่ทันขอข้อความ commit ด้วยซ้ำ hook ยอดนิยมอื่น ๆ: commit-msg (ตรวจรูปแบบข้อความ commit), pre-push (รันเทสต์ก่อนส่งขึ้น remote) หมายเหตุ: hook อยู่เฉพาะเครื่อง ไม่ถูก push ไปกับ repo — ถ้าอยากให้ทั้งทีมใช้ชุดเดียวกัน ตั้งค่า core.hooksPath ให้ชี้ไปโฟลเดอร์ที่ commit เก็บไว้ในโปรเจกต์แทน

13.3 submodule กับ subtree — ฝัง repo ในอีก repo

SubmoduleSubtree
เก็บอะไรแค่ตัวชี้ไป commit ของ repo อื่นก๊อปโค้ดเข้ามารวมในประวัติเลย
ข้อดีrepo หลักเล็ก แยกเวอร์ชันชัดclone ทีเดียวได้ครบ ไม่ต้องสั่งเพิ่ม
ข้อเสียคนในทีมต้องรู้จักคำสั่ง submoduleประวัติปนกัน อัปเดตย้อนกลับยุ่ง

13.4 rerere & sparse-checkout

  • rerere (reuse recorded resolution) — เปิดไว้แล้ว Git จะจำวิธีที่คุณแก้ conflict หนึ่ง ๆ พอเจอ conflict เดิมซ้ำ (เช่นตอน rebase ยาว ๆ) มันแก้ให้เองอัตโนมัติ
  • sparse-checkout — กางเฉพาะบางโฟลเดอร์ของ repo ลงเครื่อง มีประโยชน์มากกับ monorepo ขนาดมหึมาที่คุณสนใจแค่ส่วนเดียว

สรุปบทที่ 13worktree กาง branch หลายอันหลายโฟลเดอร์พร้อมกัน · hooks (เช่น pre-commit) รันสคริปต์อัตโนมัติตามเหตุการณ์ · submodule = ตัวชี้ repo อื่น, subtree = ฝังโค้ดเข้ามาเลย · rerere จำวิธีแก้ conflict ซ้ำ, sparse-checkout กางเฉพาะบางส่วนของ repo ใหญ่

อ่านแบบเต็มเล่ม