45 คะแนน โดย GN⁺ 2026-02-24 | 2 ความคิดเห็น | แชร์ทาง WhatsApp
  • Git ควบคุมวิธีการทำงานผ่าน ไฟล์เฉพาะบางไฟล์ภายในรีโพซิทอรี ซึ่งไม่ใช่การตั้งค่าภายใน .git/ แต่เป็น ไฟล์ที่ถูกคอมมิตและย้ายไปพร้อมกับโค้ด
  • .gitignore, .gitattributes, .lfsconfig, .gitmodules, .mailmap เป็นต้น ต่างทำหน้าที่ ยกเว้นการติดตามไฟล์, กำหนดแอตทริบิวต์, ตั้งค่า LFS, จัดการซับโมดูล, รวมข้อมูลผู้เขียน ตามลำดับ
  • .git-blame-ignore-revs และ .gitmessage ช่วย ละเว้นคอมมิตสำหรับจัดรูปแบบโค้ด และให้ เทมเพลตข้อความคอมมิต เพื่อยกระดับคุณภาพการทำงานร่วมกัน
  • GitHub, GitLab, Gitea เป็นต้น ขยายความสามารถผ่าน โฟลเดอร์ตั้งค่าเฉพาะแพลตฟอร์ม อย่าง .github/, .gitlab/, .gitea/ สำหรับ CI/CD, การระบุรีวิวเวอร์ และฟังก์ชันอื่น ๆ
  • โครงสร้างลักษณะนี้ไม่ได้มีแค่ Git แต่ยังใช้กับ EditorConfig, Docker, เครื่องมือจัดการเวอร์ชันภาษา ฯลฯ ด้วย จนเกิดเป็น ระบบนิเวศการตั้งค่าอัตโนมัติแบบ dotfile

ไฟล์เวทมนตร์หลักของ Git

  • Git รู้จัก ไฟล์พิเศษหลายชนิด เช่น .gitignore, .gitattributes, .lfsconfig, .gitmodules, .mailmap เพื่อควบคุมการทำงานของรีโพซิทอรี
    • ไฟล์เหล่านี้ไม่ใช่การตั้งค่าใน .git/ แต่เป็น องค์ประกอบการตั้งค่าที่ถูกคอมมิตและแชร์ร่วมกัน ช่วยให้การทำงานร่วมกันมีพฤติกรรมที่สอดคล้องกัน

.gitignore

  • กำหนด แพตเทิร์นของไฟล์ที่ Git ไม่ควรติดตาม
    • รองรับไวลด์การ์ด (*.log), ไดเรกทอรี (dist/), การยกเว้นกลับ (!important.log) เป็นต้น
    • ใช้งานตามลำดับ .gitignore, .git/info/exclude, การตั้งค่าระดับโกลบอล (~/.config/git/ignore)
  • ไฟล์ที่ถูกติดตามอยู่แล้วจะยังคงถูกติดตามต่อไปแม้เพิ่ม .gitignore ภายหลัง และสามารถลบออกจากดัชนีได้ด้วย git rm --cached
  • GitHub, GitLab, Gitea เป็นต้น ยังสามารถคอมมิตไฟล์ที่ตรงกับแพตเทิร์นที่ถูก ignore ได้โดยไม่มีคำเตือน
  • GitHub มีเทมเพลต .gitignore ตามภาษาให้ใน รีโพซิทอรีทางการ

.gitattributes

  • ควบคุม filter, diff, merge, การขึ้นบรรทัดใหม่, การตรวจจับภาษา แยกตามไฟล์
    • เช่น *.psd filter=lfs, *.png binary, *.sh text eol=lf
  • text ใช้ทำ normalization ของการขึ้นบรรทัดใหม่, binary ปิดการทำ diff/merge, merge=ours ใช้เก็บเวอร์ชันฝั่งโลคัลเมื่อเกิดคอนฟลิกต์
  • GitHub Linguist อ่าน .gitattributes เพื่อทำ การตัดออกจากสถิติภาษา, พับโค้ดที่สร้างอัตโนมัติ, ตัดเอกสารออก เป็นต้น
  • รองรับทั้ง .gitattributes ในแต่ละไดเรกทอรีและ .git/info/attributes

.lfsconfig

  • เก็บ การตั้งค่า Git LFS ไว้ให้แชร์ไปพร้อมรีโพซิทอรี
    • ตั้งค่าได้ เช่น URL ของเซิร์ฟเวอร์ LFS, จำนวนครั้งในการ retry ระหว่างส่งข้อมูล
    • ตัวอย่าง:
      [lfs]
          url = https://lfs.example.com/repo
      [lfs "transfer"]
          maxretries = 3
      
  • .gitattributes ใช้ระบุไฟล์ที่จะให้ LFS จัดการ ส่วน .lfsconfig ดูแลรายละเอียดอย่างตำแหน่งเซิร์ฟเวอร์
  • หากต้องการย้ายไฟล์จากคอมมิตเดิมไปใช้ LFS ต้องใช้คำสั่ง git lfs migrate

.gitmodules

  • เก็บ ข้อมูลการตั้งค่าของซับโมดูล
    • มีข้อมูล path, URL, branch ของแต่ละโมดูล
    • ตัวอย่าง:
      [submodule "vendor/lib"]
          path = vendor/lib
          url = https://github.com/example/lib.git
          branch = main
      
  • ถูกสร้างเมื่อใช้ git submodule add และถูกอ้างอิงเมื่อใช้ git submodule update
  • ตอน git clone จะไม่ดึงซับโมดูลมาให้อัตโนมัติ ต้องใช้ตัวเลือก --recurse-submodules
  • มีข้อเสีย เช่น ติดตามช่วงเวอร์ชันไม่ได้ และอาจเกิดไดเรกทอรี .git แบบซ้อนกัน

.mailmap

  • ใช้ รวมชื่อและอีเมลของผู้เขียนให้เป็นรูปแบบเดียวกัน
    • ตัวอย่าง:
      Jane Developer <[email protected]> <[email protected]>
      
  • git log, git shortlog, git blame เป็นต้น จะแสดงชื่อที่ถูกรวมแล้ว
  • กราฟผู้มีส่วนร่วมของ GitHub ไม่สะท้อน mailmap
  • สามารถระบุตำแหน่งได้ผ่าน .mailmap หรือการตั้งค่า mailmap.file

.git-blame-ignore-revs

  • ระบุ รายการคอมมิตที่ git blame ควรละเว้น
    • ใช้ตัดการเปลี่ยนแปลงที่ไม่มีนัยสำคัญ เช่น การรัน formatter หรือการใช้ lint
    • ตัวอย่าง:
      # Ran prettier on entire codebase
      a1b2c3d4e5f6g7h8i9j0...
      
  • เปิดใช้งานได้ด้วย git config blame.ignoreRevsFile .git-blame-ignore-revs
  • GitHub, GitLab (15.4+), Gitea รองรับการตรวจพบอัตโนมัติ
  • หากไม่มีไฟล์นี้อาจเกิดข้อผิดพลาดได้ จึงแนะนำให้คงไฟล์ว่างไว้

.gitmessage

  • กำหนด เทมเพลตข้อความคอมมิต
    • ตัวอย่าง:
      # <type>: <subject>
      #
      # Types: feat, fix, docs, style, refactor, test, chore
      
  • ต้องตั้งค่าด้วย git config commit.template .gitmessage
  • หลัง clone แล้วต้องตั้งค่าด้วยตนเอง และบางทีมใช้ husky เป็นต้นเพื่อทำให้อัตโนมัติ
  • อีกทางเลือกคือใช้ hook แบบ commit-msg หรือ prepare-commit-msg

โฟลเดอร์ส่วนขยายเฉพาะแพลตฟอร์ม

  • GitHub, GitLab, Gitea, Forgejo, Bitbucket เป็นต้น ใช้ โฟลเดอร์ตั้งค่าเฉพาะของตนเอง
    • .github/, .gitlab/, .gitea/, .forgejo/, .bitbucket/
  • ภายในอาจมี CI/CD workflow, เทมเพลต issue·PR, ไฟล์ CODEOWNERS เป็นต้น
  • Forgejo มี fallback ตามลำดับ .forgejo/ → .gitea/ → .github/ ส่วน Gitea ใช้ .gitea/ → .github/
  • SourceHut ใช้ .build.yml หรือ .builds/*.yml

ไฟล์ตามธรรมเนียมอื่น ๆ

  • .gitkeep: เนื่องจาก Git ไม่ติดตามไดเรกทอรีว่าง จึงใช้เป็นไฟล์จำลองเพื่อคงไดเรกทอรีไว้
  • .gitconfig: ใช้เป็นตัวอย่างการตั้งค่า Git ระดับโปรเจกต์ แต่จะไม่ถูกโหลดอัตโนมัติ
  • .gitsigners: ใช้จัดการรายการคีย์ลายเซ็น GPG/SSH และระบุได้ผ่าน gpg.ssh.allowedSignersFile
  • .gitreview: ไฟล์ตั้งค่าเซิร์ฟเวอร์รีวิวโค้ด Gerrit
    • ตัวอย่าง:
      [gerrit]
      host=review.opendev.org
      port=29418
      project=openstack/nova.git
      defaultbranch=master
      
  • .gitlint: กำหนดกฎ lint สำหรับข้อความคอมมิต
    • ตัวอย่าง:
      [general]
      ignore=body-is-missing
      [title-max-length]
      line-length=72
      
  • .jj/: ไดเรกทอรีสถานะของ Jujutsu ซึ่งเป็น VCS ที่เข้ากันได้กับ Git และสามารถอยู่ร่วมกับ .git/ ได้

ระบบนิเวศ dotfile ที่ไปไกลกว่า Git

  • .editorconfig: ช่วยคงสไตล์โค้ดให้สม่ำเสมอข้ามเอดิเตอร์
    • กำหนดการเยื้อง, การขึ้นบรรทัดใหม่, การเข้ารหัส, การลบช่องว่าง เป็นต้น
    • เอดิเตอร์หลักอย่าง VS Code, Vim, Emacs รองรับ
  • .ruby-version, .node-version, .python-version: เครื่องมือจัดการเวอร์ชันภาษา (rbenv, nodenv, pyenv เป็นต้น) อ่านเพื่อสลับเวอร์ชันอัตโนมัติ
  • .tool-versions: ไฟล์จัดการเวอร์ชันหลายภาษาของ asdf
  • .dockerignore: ระบุรายการไฟล์ที่จะไม่รวมระหว่าง Docker build
    • ใช้ไวยากรณ์แพตเทิร์นแบบเดียวกับ .gitignore ช่วยเพิ่มความเร็วในการ build และกันข้อมูลลับออก

สิ่งที่ควรคำนึงถึงเมื่อพัฒนาเครื่องมือที่เชื่อมกับ Git

  • เครื่องมือที่จัดการรีโพซิทอรี Git ควรรู้จักไฟล์ต่อไปนี้ให้ครบ
    • .gitignore: ใช้แพตเทิร์น ignore ระหว่างสำรวจไฟล์
    • .gitattributes: ใช้แยกไฟล์ไบนารีและไฟล์ที่สร้างอัตโนมัติ
    • .mailmap: ใช้แสดงข้อมูลผู้เขียนแบบรวมศูนย์
    • .gitmodules: ใช้จัดการซับโมดูล
  • รูปแบบไฟล์ตั้งค่า Git ใช้โครงสร้าง [section "subsection"] key = value และสามารถอ่าน/เขียนได้ด้วยคำสั่ง git config
  • ไลบรารี Git ของภาษาส่วนใหญ่มีความสามารถในการ parse รูปแบบนี้มาให้

2 ความคิดเห็น

 
wedding 2026-02-24

ไม่เคยรู้จัก gitmessage มาก่อนเลย แต่คงต้องลองใช้ดูแล้ว

 
GN⁺ 2026-02-24
ความคิดเห็นบน Hacker News
  • มีการบอกว่า GitHub, GitLab และ Gitea ต่างก็เคารพ .gitignore จึงไม่แสดงไฟล์ที่ถูก ignore ในเว็บ UI แต่ดูเหมือนว่าคำอธิบายนั้นจะไม่ถูกต้อง
    ที่จริงแล้วมันไม่แสดงเพราะ ไฟล์ที่ถูก ignore ไม่ได้ถูกรวมอยู่ใน repository ต่างหาก ถ้าเป็นไฟล์ที่ถูก commit ไปแล้ว ก็ควรจะยังมองเห็นได้
    • ไม่ใช่แบบนั้น ถ้าไฟล์ถูก push ไปแล้ว แล้วค่อยเพิ่มลงใน .gitignore ภายหลัง มันก็ยังแสดงอยู่ใน UI เหมือนเดิม เพราะไฟล์นั้นยังคงเป็น ส่วนหนึ่งของ repo
      ในทางกลับกัน ก็สามารถบังคับ commit ไฟล์ที่ถูก ignore ตั้งแต่แรกได้เหมือนกัน แต่ต้องใช้ทริกเล็กน้อย
    • ใช่แล้ว คอมเมนต์ต้นทางผิด .gitignore มีหน้าที่แค่กำหนดว่าจะ ซ่อนไฟล์ที่ยัง untracked หรือไม่ เท่านั้น ถ้าต้องการก็ยัง commit ไฟล์ที่ถูก ignore ได้
    • รู้สึกว่าน่าจะมีตัวเลือกอย่าง showinwebui=(true|false) 😄
    • รู้สึกว่าไม่น่าใช่ความผิดพลาดที่คนเขียนเอง เลยหยุดอ่านตรงนั้น
  • อยากเน้น .git/info/exclude มาก นี่คือ gitignore แบบใช้เฉพาะเครื่อง สำหรับการตั้งค่าของตัวเองล้วน ๆ
    เช่น เวลาสืบหาบั๊กแล้วสร้างไฟล์ชั่วคราวไว้ และอยากเปลี่ยน branch ไปมาโดยไม่ให้ไฟล์หาย ฟีเจอร์นี้มีประโยชน์มาก
    ผมทำ shell alias แบบนี้ไว้ใช้
    git-ignore-local () {
      echo "$1" >> .git/info/exclude
    }
    
    แบบนี้ก็เพิ่มได้ง่าย ๆ ด้วย git-ignore-local myfile.ext
    • ผมลองทำ เวอร์ชันที่ดูเหมือนเวทมนตร์ขึ้นอีกหน่อย ให้ใช้งานได้แม้จะไม่ได้อยู่ที่ root directory
      บน MacOS แค่แก้ส่วน readlink เท่านั้น
      git-ignore-local () {
        root=$(git rev-parse --show-toplevel)
        path=$(readlink -f "$1")
        relpath=$(relpath -m --relative-to="$root" "$path")
        echo "$relpath" >> "${root}.git/info/exclude"
      }
      
      ถ้าลงทะเบียนฟังก์ชันนี้ไว้ใน PATH ด้วยชื่อ git-ignore-local ก็จะเรียกใช้แบบ git ignore-local ได้
    • มีการพูดถึง .git/info/exclude อยู่แล้วตั้งแต่ช่วงต้นของคำอธิบาย .gitignore
    • เพิ่งรู้ว่ามีฟีเจอร์นี้ โปรเจ็กต์ของผมมี ไฟล์ชั่วคราวเล็ก ๆ พวกนี้จน PR ดูรกไปหมด คิดว่านี่น่าจะช่วยได้
  • ถ้าเพิ่ม /test export-ignore ลงใน .gitattributes ก็จะ ตัดไฟล์ทดสอบออกตอน deploy ไปยัง production server ได้
    เวลามีเครื่องมือ deploy อย่าง Capistrano ใช้ git export มันจะถูกนำไปใช้โดยอัตโนมัติ ทำให้ไฟล์ทดสอบไม่ถูกอัปโหลดขึ้นเซิร์ฟเวอร์
    ระหว่างพัฒนาก็ไม่กระทบอะไร แถมยังช่วยประหยัดพื้นที่ดิสก์ด้วย
    • เป็นฟีเจอร์ที่ดี แต่ดูเหมือนคนส่วนใหญ่จะไม่ค่อยรู้จัก git archive กันเท่าไร
      แทบไม่เคยเห็นเครื่องมือ CI พื้นฐานใช้มันเลย ผมเพิ่งมารู้จักจากการที่ Capistrano เอามาใช้เป็นกรณีแรก
      อนึ่ง ถ้าใช้ตัวเลือก export-subst ก็สามารถแทรกข้อมูลคล้าย git describe ลงไปในไฟล์ได้โดยตรงด้วย
  • ตอนใช้ jj ผมอยากให้โฟลเดอร์ .jj ถูก ตัดออกจาก repo และจากทุกการทำงานของ git อย่างสมบูรณ์
    รวมถึงไม่อยากให้โดนลบจาก git clean -xdf ด้วย ตอนนี้เลยแก้ขัดด้วย alias git clean -e .jj
    • ใช้ .git/info/exclude ได้เลย
  • contributor graph ของ GitHub ไม่รองรับ .mailmap
    มีการพูดคุยไว้ใน GitHub Community Discussion
  • ผมคิดว่าการตั้งค่า package-lock.json merge=ours ค่อนข้างเสี่ยง
    เพราะความหมายของ ours/theirs ในตอน merge หรือ rebase ไม่ชัดเจน
    การตั้งค่าแบบนี้มีความหมายจริง ๆ เฉพาะกับเครื่องมือ merge อัตโนมัติเท่านั้น (เช่น git-annex branch)
    อ้างอิง: คำอธิบายความหมายของ ours/theirs, โครงสร้างภายในของ git-annex
  • .git-blame-ignore-revs เป็นฟีเจอร์ที่ดี แต่ควรอยู่ในหมวด “ธรรมเนียมอื่น ๆ” มากกว่า
    ถ้าไม่ได้ตั้งค่าใน git client, repository ที่ไม่มีไฟล์นี้จะทำให้ git blame ล้มเหลว
    • ตั้งแต่ git 2.52 เป็นต้นไป สามารถใช้ตัวเลือก (:optional) เพื่อไม่ให้เกิด error แม้ไฟล์จะไม่มีอยู่
      ดูคำอธิบายได้ใน คำตอบบน Stack Overflow
  • โดยรวมคิดว่าเป็นลิสต์ที่สรุปได้ดี
    แต่ก็น่าเสียดายที่ไม่ใช่ทุกเครื่องมือจะรองรับ .mailmap เช่น IntelliJ ยังอยู่ในสถานะ บั๊ก/คำขอฟีเจอร์
    อีกทั้ง .git-blame-ignore-revs ก็เป็นเพียงธรรมเนียมอย่างหนึ่งเท่านั้น ต้องตั้งค่าเองถึงจะทำงาน
  • เป็นอีกเรื่องที่ใกล้เคียงกัน แต่ผมเพิ่งรู้เมื่อไม่นานมานี้ว่า VS Code ก็รู้จักไฟล์ .ignore เหมือนกัน
    เดิมคิดว่ามีแค่ .gitignore ที่มีผล แต่พอไปเปลี่ยน การตั้งค่า ripgrep ใน .ignore แล้วผลการค้นหาก็เปลี่ยนไป ซึ่งพอมารู้ทีหลังก็ถือว่าสมเหตุสมผล
  • ผู้เขียนบทความได้ลงภาคต่อเกี่ยวกับ forge-specific repository folders (โฟลเดอร์ “เวทมนตร์” อีกรูปแบบหนึ่ง) ด้วย
    ลิงก์: บทความบน nesbitt.io