4 คะแนน โดย GN⁺ 2025-01-18 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Git เป็นสิ่งที่ค้นหาวิธีแก้ได้ยากหากไม่รู้ชื่อของสถานการณ์ที่ทำพลาด เอกสารนี้จึงรวบรวม คำสั่งตามสถานการณ์กู้คืนที่พบบ่อย เพื่อให้ค้นหาแล้วนำไปใช้ได้ทันที
  • เมื่อทำ repository พังหนัก หรือต้องการย้อนการลบ/การ merge ที่ผิดพลาด สามารถใช้ git reflog เพื่อหา history ของการทำงาน แล้วใช้ git reset HEAD@{index} เพื่อกลับไปยัง สถานะก่อนหน้า ได้
  • การแก้ไขเล็กน้อยหรือเปลี่ยนข้อความของ commit ล่าสุด ทำได้รวดเร็วด้วย git commit --amend แต่ไม่ควรใช้กับ commit ที่ push ไปยัง branch สาธารณะ/ที่ใช้ร่วมกัน แล้ว
  • หาก commit ผิด branch สามารถย้ายได้ด้วย flow reset, stash, checkout, stash pop หรือใช้ cherry-pick แต่แนวทางที่ปลอดภัยจะแตกต่างกันตามว่ามีการ push แล้วหรือไม่
  • reset --hard และ git clean -d --force ที่ใช้บังคับกู้คืนให้ตรงกับสถานะของ remote repository อาจลบไฟล์ที่ไม่ได้ถูกติดตามไปด้วย จึงต้องตรวจสอบก่อนรัน

ทำไมการกู้คืนความผิดพลาดใน Git ถึงยาก

  • Git ทำพลาดได้ง่าย และหลายครั้งถ้าต้องการแก้ปัญหา คุณต้องรู้ชื่อแนวคิดที่จำเป็นอยู่แล้วจึงจะค้นหาได้
  • เอกสารนี้รวบรวมสถานการณ์แย่ ๆ ที่พบบ่อยใน Git ด้วย ภาษาอังกฤษแบบเข้าใจง่าย พร้อมตัวอย่างคำสั่ง
  • ไม่ใช่ reference ที่ครบถ้วนสมบูรณ์ และงานเดียวกันอาจมีวิธีจัดการแบบอื่นได้เช่นกัน

ย้อน repository กลับไปยังสถานะในอดีต

  • เมื่อทำ repository พังหนัก หรือต้องการกู้สิ่งที่ลบไป ให้ตรวจสอบ history ของการทำงานด้วย git reflog
git reflog


# 모든 브랜치에 걸친 Git 작업 목록을 볼 수 있음


# 각 항목은 HEAD@{index} 형태의 인덱스를 가짐
git reset HEAD@{index}
  • reflog ใช้ได้ในสถานการณ์ต่อไปนี้
    • กู้คืนสิ่งที่ลบโดยไม่ตั้งใจ
    • ลบความพยายามที่ทำให้ repository พัง
    • กู้คืนหลังจาก merge ที่ไม่ดี
    • ย้อนกลับไปยังจุดที่เคยทำงานได้จริง

วิธีแก้ commit ล่าสุด

  • หากต้องเพิ่มการแก้ไขเล็กน้อยหลัง commit ล่าสุด ให้ใช้ git commit --amend --no-edit
# 변경 후
git add . # หรือเพิ่มไฟล์ทีละไฟล์
git commit --amend --no-edit
  • คำสั่งนี้จะรวมการเปลี่ยนแปลงใหม่เข้าไปใน commit ล่าสุด
  • คุณอาจสร้างการเปลี่ยนแปลงเดียวกันเป็น commit ใหม่แล้วค่อยรวมด้วย rebase -i ได้เช่นกัน แต่ amend เร็วกว่ามาก
  • ไม่ควรใช้ amend กับ commit ที่ push ไปยัง branch สาธารณะ/ที่ใช้ร่วมกัน แล้ว
  • หากต้องการเปลี่ยนเฉพาะข้อความของ commit ล่าสุด ให้ใช้คำสั่งต่อไปนี้
git commit --amend


# 안내에 따라 커밋 메시지 변경

เมื่อ commit ผิด branch

  • หากเผลอ commit ลง master แต่ควรอยู่ใน branch ใหม่ ให้สร้าง branch ใหม่จากสถานะปัจจุบัน แล้วลบ commit ล่าสุดออกจาก master
git branch some-new-branch-name
git reset HEAD~ --hard
git checkout some-new-branch-name
  • วิธีนี้ไม่เหมาะกับ commit ที่ push ไปยัง branch สาธารณะ/ที่ใช้ร่วมกัน แล้ว
  • หากเคยลองวิธีอื่นมาก่อน อาจต้องใช้รูปแบบ HEAD@{number-of-commits-back} แทน HEAD~
  • หาก commit ลง branch ผิดโดยสิ้นเชิง สามารถย้ายด้วย flow reset --soft, stash, checkout, stash pop ได้
git reset HEAD~ --soft
git stash
git checkout name-of-the-correct-branch
git stash pop
git add . # หรือเพิ่มไฟล์ทีละไฟล์
git commit -m "your message here"
  • ในสถานการณ์เดียวกัน ยังมีวิธีใช้ cherry-pick ได้ด้วย
git checkout name-of-the-correct-branch
git cherry-pick master
git checkout master
git reset HEAD~ --hard

ย้อนการเปลี่ยนแปลงและ commit เก่า

  • หากแก้ไฟล์แล้ว git diff ว่างเปล่า อาจเป็นเพราะ stage ไปแล้ว จึงต้องใช้ flag --staged
git diff --staged
  • หากต้องการย้อนการเปลี่ยนแปลงจาก commit เมื่อหลาย commit ก่อน ให้หา hash ด้วย git log แล้วรัน git revert
git log
git revert [saved hash]
  • git revert จะสร้าง commit ใหม่ ที่ย้อน commit นั้น
  • หากต้องการย้อนเฉพาะไฟล์บางไฟล์ ไม่ใช่ทั้ง commit ให้เอาเวอร์ชันเก่าของไฟล์ขึ้น index แล้ว commit
git log
git checkout [saved hash] -- path/to/file
git commit -m "Wow, you don't have to copy-paste to undo"

บังคับกู้คืนให้ตรงกับสถานะของ remote repository

  • แทนที่จะลบ repository แล้ว clone ใหม่ สามารถใช้คำสั่ง Git เพื่อปรับให้ตรงกับสถานะของ remote repository ได้
git fetch origin
git checkout master
git reset --hard origin/master
git clean -d --force
  • git reset --hard origin/master จะปรับ branch ให้ตรงกับสถานะของ master บน remote
  • git clean -d --force จะลบไฟล์และไดเรกทอรีที่ไม่ได้ถูกติดตาม
  • ต้องทำซ้ำ checkout, reset, clean กับแต่ละ branch ที่พัง
  • งานเหล่านี้เป็นการกระทำที่ ทำลายข้อมูลและกู้คืนไม่ได้ จึงต้องระวังก่อนรัน

ขอบเขตและการมีส่วนร่วม

  • เอกสารนี้ไม่ใช่ reference ของ Git ที่ครบถ้วน แต่เป็นชุดขั้นตอนกู้คืนภาคปฏิบัติที่ได้มาจากการลองผิดลองถูก
  • หากต้องการช่วยเพิ่มคำแปล สามารถส่ง PR ได้ที่ GitHub

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

 
GN⁺ 2025-01-18
ความคิดเห็นจาก Hacker News
  • มีอยู่สองสามจุดที่อยากเปลี่ยน: จะใช้ git switch แทน git checkout เสมอ และจะพยายามหลีกเลี่ยง reset --hard ให้มากที่สุด
    ตัวอย่างเช่น กรณี “เผลอ commit ลง master ทั้งที่ควรอยู่บน branch ใหม่” สามารถจัดการตามลำดับ git branch some-new-branch-name, git switch -d HEAD~, git switch -C master, git switch some-new-branch-name ได้
    กรณี “commit ผิด branch” ก็จะจัดการโดย git switch ไปยัง branch ที่ถูกต้อง แล้วใช้ git cherry-pick master, git switch -d master~, git switch -C master
    ส่วน “ยอมแพ้ทั้งหมดแล้วย้อนกลับไปเป็นสถานะบน remote” ก็จะประกอบเป็น git fetch origin, git restore -WS ., git clean -d --force, git switch -d origin/master, git switch -C master ประมาณนี้

    • โมเดลภายในของ Git นั้นสวยงามด้วย blob, commit tree, commit pointer แต่ช่องว่างกับอินเทอร์เฟซบรรทัดคำสั่งใหญ่เกินไป
      ต่อให้เข้าใจโมเดลของ Git ดี สูตรพวกนี้ก็ไม่เป็นธรรมชาติ และยังต้องรู้พฤติกรรมเฉพาะของแต่ละคำสั่งด้วย
      เช่น git switch -c some-new-branch-name มีอยู่แล้วก็จริง แต่คำสั่งอย่าง git move-branch master HEAD~ ที่ย้ายเฉพาะ branch ไปยัง commit อื่นน่าจะเข้าใจได้เป็นธรรมชาติกว่า
    • ไม่ได้จะคัดค้านทิศทางการใช้ git switch และ git restore แทน git checkout แต่คำสั่งเหล่านี้ถูกนำเข้ามาใน Git v2.23 และ release นั้นก็เมื่อราว 5 ปีก่อน
      ในหน้า help ยังมีคำเตือนว่า THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE. อยู่
      แน่นอนว่าคำเตือนนี้มีมาตั้งแต่ช่วงแรก ๆ ที่คำสั่งเกิดขึ้น และผ่านไป 5 ปีแล้วก็น่าจะถึงเวลาที่ไม่ต้องเรียกว่าทดลองได้แล้ว
      ถึงอย่างนั้น git checkout ก็ backward compatible กว่า และถือได้ว่าสะท้อนวิธีใช้ Git ในช่วงเวลาที่เว็บไซต์นี้ถูกสร้างขึ้นเดิม
      https://github.com/git/git/blob/757161efcca150a9a96b312d9e78...
      https://github.com/git/git/releases/tag/v2.23.0
      https://github.com/git/git/commit/4e43b7ff1ea4b6f16b93a432b6...
    • การสอน git add . เป็นค่าเริ่มต้นเวลาเอาการเปลี่ยนแปลงขึ้น staging area นั้นไม่ค่อยดี
      การระบุไฟล์ที่ต้องการเพิ่มอย่างชัดเจนมีโอกาสน้อยกว่าที่ภายหลังจะต้องพูดว่า “แย่แล้ว”
    • อยากรู้เหตุผลว่าทำไมถึงแนะนำวิธีนี้
      อยากรู้ว่า switch ดีกว่า checkout อย่างไร และทำไมถึงไม่ควรใช้ reset --hard
    • ไม่เข้าใจว่า “หลีกเลี่ยง reset --hard” หมายความว่าอะไร
      อยากรู้ว่าจริง ๆ แล้วมันไม่เพียงพอตรงไหน และผมใช้มันค่อนข้างบ่อยร่วมกับ alias git-restore-file='git restore --source=HEAD --' ซึ่งดูเหมือนจะทำงานได้ดี
  • ควรเริ่มแนะนำ GUI client เป็นเส้นทางพื้นฐานในการเรียน Git
    แบบนั้นปัญหาหนึ่งในสามจะถูกแก้ได้ และอีกหนึ่งในสามจะไม่เกิดขึ้นตั้งแต่แรก
    ถ้าภายหลังตัดสินว่า command line เร็วกว่าก็ค่อยใช้ ตอนแรกผู้คนควรได้เห็นภาพว่าพวกเขาโต้ตอบกับ tree อย่างไรก่อน
    ส่วนตัวชอบ fork.dev แต่ client สมัยนี้โดยรวมก็คล้าย ๆ กัน

    • เห็นด้วยว่า GUI มักมอบประสบการณ์ผู้ใช้ที่ดีกว่าสำหรับ Git
      เมื่อใช้ Magit การกระทำอย่าง “ยกเลิก cherry-pick” สามารถค้นพบได้จากใน interface และใช้ shortcut เดียวกับงาน “ยกเลิก X” อื่น ๆ
      ถ้าต้องใช้แต่ command line ของ Git อย่างเดียว คงไม่รู้จะเริ่มจากตรงไหน
      เคยลบ commit ที่ไม่ควรลบระหว่าง interactive rebase ด้วย แต่ทุกครั้งที่เริ่ม rebase จะมี snapshot ที่เข้าถึงได้จาก reflog เกิดขึ้น จึงปลอดภัยที่จะย้อน rebase ที่ผิดพลาด
      UI ของ reflog ใน Magit เหมือนกับ UI ของ log เลยไม่หลงทางแม้เห็นครั้งแรก แต่ถ้าเป็น Git CLI ก็น่าจะไม่รู้ว่าเกิดอะไรขึ้น
    • เริ่มแนะนำ jj ในฐานะทางเลือกที่เข้ากันได้กับ Git
      ชอบตรงที่เมื่อรัน jj โดยไม่ใส่ argument มันจะแสดงส่วนที่เกี่ยวข้องของ commit tree และตำแหน่งปัจจุบัน
      สามารถเห็น commit ที่กำลังทำงานอยู่, branch ที่เชื่อมอยู่กับ history, branch อื่นที่ยัง active ใน repository, ข้อความของแต่ละ commit และสถานะว่ามีการเปลี่ยนแปลงหรือไม่ ได้ในที่เดียว จึงยอดเยี่ยมมากสำหรับการตั้งหลักใหม่
    • สำหรับมือใหม่ Git มักแนะนำเสมอให้หา UI ที่เหมาะกับตัวเองแล้วใช้สิ่งนั้นแทน command line
      แต่แทบไม่มีใครฟัง สุดท้ายก็ไปทรมานกับ CLI ทำ branch พัง ตาม main ไม่ทัน และกลัว rebase
      ใน UI หลายเรื่องแก้ได้ด้วยการลากวางหรือวิธีคล้าย ๆ กัน ดูเหมือนเป็นการทรมานตัวเองรูปแบบหนึ่ง
    • ถ้าจำเป็นต้องเห็นภาพวิธีโต้ตอบกับ tree มี interactive tutorial ที่เคยช่วยเพื่อนร่วมงานได้: https://learngitbranching.js.org/
    • จากประสบการณ์ที่เคยใช้ GUI frontend สำหรับ version control ในอดีต ตอนทุกอย่างทำงานดีมันก็โอเค แต่พอมีอะไรยุ่งเหยิงและต้องเก็บกวาด จะหาคนช่วยได้ยาก
      แม้ interface จะเลวร้ายแค่ไหน การใช้ interface เดียวกับที่คนอื่นในทีมใช้ก็สื่อสารกันง่ายกว่า และแหล่งข้อมูลแก้ปัญหาออนไลน์ส่วนใหญ่ก็สมมติ “วิธีปกติ” เอาไว้ จึงนำมาใช้ได้สะดวกกว่า
  • พอคิดว่าเดือนเมษายน 2025 Git จะมีอายุครบ 20 ปี แล้ว ก็รู้สึกแปลกอยู่ไม่น้อย
    ตอนนั้นผมอยู่หน้างาน และจำได้ว่าเคยลังเลว่าควรเรียน git, darcs หรือ bazaar เพื่อมาแทน SVN หรือ CVS ดี
    ไม่แน่ใจว่าเคยลอง Mercurial ด้วยหรือเปล่า
    สงสัยว่า “ผลของ GitHub” ได้ฆ่าความจำเป็นของผู้เล่นหน้าใหม่ในวงการระบบควบคุมเวอร์ชันไปโดยปริยายหรือไม่
    บางทีอาจเป็นจุดที่การไล่โกนขนจามรีทำกันมาพอแล้วก็ได้

    • ผลของ GitHub มีอยู่จริงเหมือน network effect ทั้งหมด แต่นั่นไม่ได้แปลว่าจะปรับปรุงไม่ได้
      ผมย้ายไปใช้ jj เต็มตัวแล้ว และเพราะมันเข้ากันได้กับ Git จึงไม่ต้องรอให้คนอื่นเปลี่ยนตาม
      ผมผิดหวังกับ GitHub ในหลายด้านมากขึ้นเรื่อย ๆ เลยหวังว่าสักวันทุกคนจะก้าวข้ามมันไปได้ด้วย แต่เส้นทางฝั่งนั้นดูไม่ได้ง่ายขนาดนั้น
    • SVN ทำงานได้ดีเสมอมา
      SVN เข้าใจง่าย และทำงานได้ดีพอใน 99% ของกรณี จนไม่จำเป็นต้อง “สอน” ผู้คนเป็นพิเศษ
      อยากให้พวกเราทุกคนเลิกทำตัวเป็นแฮ็กเกอร์ 1337 แล้วก็ยอมรับว่า Git เป็นเครื่องมือที่เกินจำเป็นสำหรับคนส่วนใหญ่
    • การปรับปรุงแบบไหนก็ตาม อย่างน้อยคงต้อง เข้ากันได้กับ Git เช่น jj
  • ผมคิดว่าตัวเองมี mental model ที่ค่อนข้างดีว่า Git ทำอะไรอยู่ แต่พอคำสั่งซับซ้อนขึ้นนิดเดียวก็จำอาร์กิวเมนต์ไม่ได้
    คำสั่งทั้งหลายค้นพบเองได้ยาก และก็จำไม่ง่าย
    ไม่รู้ว่าเป็นเพราะ text UI แย่ หรือเพราะการอธิบายงานจัดการ tree ด้วยข้อความนั้นยากในตัวมันเองกันแน่

    • ทั้งคู่
      การจัดการ tree ที่ซับซ้อนด้วยข้อความไม่ใช่เรื่องง่าย และ text UI ก็แย่ในเชิงวัตถุวิสัย: https://stevelosh.com/blog/2013/04/git-koans/
  • ดีใจที่ในเธรดนี้มีผลการค้นหา hg กับ Mercurial โผล่มา
    ยังไม่อยากเชื่อว่า Mercurial แพ้ในสงคราม distributed version control และผมมองว่ามันเป็นเครื่องมือที่ดีกว่า

    • แม้เทียบกับปัจจุบัน Mercurial ก็ยังเป็นเครื่องมือที่ดีกว่าอย่างไม่ต้องสงสัย
      ใช้งานได้ เสถียร ผ่านการพิสูจน์ในงานจริง และยังมีการซัพพอร์ตอย่างคึกคัก
      มันใกล้เคียงกับแนวคิด “จงเป็นความเปลี่ยนแปลงที่คุณอยากเห็น” ดังนั้นก็แค่ใช้มัน
      การพูดว่ามันแพ้แล้วส่งผลเสียมาก และแรงกดทับโดยนัยจากคำพูดแบบนั้นก็ทำให้อัตราการยอมรับ Mercurial ยังคงต่ำ
      สำหรับโฮสติ้ง อย่างน้อยก็ทำได้ที่ Sourcehut และ heptapod.host
      ผมรันอินสแตนซ์ Heptapod ส่วนตัวอยู่ด้วย ซึ่งเป็น Gitlab fork ที่ใส่การรองรับ Mercurial โดยตรง และมันก็ทำงานได้ดี
    • น่าสนใจนะ แต่สงสัยว่ามีลิงก์ GitHub ไหม
    • Mercurial เป็นเครื่องมือที่ช้ากว่า
    • ถ้าต้องการโฮสติ้ง Mercurial ใช้โฮสติ้งนี้ได้: https://hg.reactionary.software/
  • Git เป็นหนึ่งในเทคโนโลยีที่ท้ายที่สุดก็ไม่ค่อยเข้าหัวผม เพราะมันไม่เป็นไปตามสัญชาตญาณในหลายแง่
    ถ้าไม่ได้ใช้มานาน ก็มีโอกาสสูงที่แทบทุกงานต้องค้น Google หรือดู man page

    • ผมเริ่มจาก SVN แล้วค่อยย้ายมา Git ถึงจะต้องเรียนรู้ความแตกต่าง แต่รู้สึกว่ามันง่ายขึ้นในหลายด้าน
      โดยเฉพาะหลังจากเจอความสยองของการพยายามจัดการ codebase ขนาดใหญ่ใน SVN ด้วย branch จำนวนมากแล้ว merge กลับเข้าไป จะเห็นว่า Git ดีกว่าอย่างเหลือเชื่อในส่วนนั้น
      สำหรับคนที่เริ่มจาก Git ตั้งแต่แรก เส้นโค้งการเรียนรู้อาจชันกว่ามาก แต่บางครั้งผมก็ยังเข้าใจยากอยู่ดีว่าคนไปติดตรงไหนกัน
    • เมื่อวานผมพยายามลบไฟล์ออกจาก history
      ถ้าใช้วิธีในตัวอย่าง filter-branch ก็จะมี delay ยาว ๆ แล้วขึ้นคำเตือนให้กด Control+C และไปดาวน์โหลดสคริปต์ Python ของ third-party ชื่อ filter-repo
  • ไม่ได้ภูมิใจนัก แต่ปฏิบัติการ Git แบบ “พังแล้ว” ที่ผมใช้บ่อยที่สุดคือ ลบ repository ในเครื่อง แล้ว clone ใหม่ จากนั้นค่อย apply การเปลี่ยนแปลงกลับเข้าไป
    95% ใช้ได้ดีมาก ส่วนที่เหลือก็ขอความช่วยเหลือจากคนดูแล DevOps

    • ผมใช้ Git มาเกือบ 15 ปี และเคยสร้างโปรแกรม/ผลิตภัณฑ์ที่ใช้ Git ภายในเพื่อให้ได้ผลลัพธ์เฉพาะมาแล้วสองครั้ง แต่ก่อนจะทำอะไรเสี่ยง ๆ ใน Git ผมก็ยังมีบางครั้งที่ทำประมาณ cp -R .git ../git-backup ไว้ก่อน
      เพราะถ้าทำพังหนักเกินไป ก็แค่เอาไดเรกทอรี .git ทั้งหมดไปแทนด้วยสำเนาเก่า
      เร็วกว่าการหาวิธี undo งานใดงานหนึ่งหรือชุดงานให้ถูกต้องมาก
    • คุณไม่ได้เป็นคนเดียว: https://xkcd.com/1597/
  • สิ่งที่อยากให้คนซึมซับเกี่ยวกับ Git ให้ได้คือ Git เป็น data store แบบ append-only
    ถ้าจะเอางานใส่ repository ก็ commit เข้าไป และเมื่องานเข้าไปแล้ว จะเอาออกด้วยคำสั่ง Git ไม่ได้
    reflog ก็ทำงานตามหลักการนี้
    ไม่ว่าคุณจะทำอะไร ก็สามารถย้อนกลับไปยังสถานะ branch ก่อนหน้า และกู้คืนงานจาก data store ได้
    แต่ถ้าไม่ commit Git ก็ช่วยไม่ได้ ดังนั้นก็ commit ไปเถอะ
    commit เสมอ และถ้าภาระมันมากเกินไปหรือคุณลืมอยู่เรื่อย ๆ ก็ควรแก้เครื่องมือ
    ถ้าเขียนโค้ดทั้งวัน โดยทั่วไปอย่างน้อยควร commit ชั่วโมงละครั้ง

  • เรื่องเล็กน้อย แต่ทุกครั้งที่เห็น git reflog มันดูเหมือน re-flog
    อาจเป็นเหตุผลที่ผมจำคำสั่งนี้ไม่ค่อยได้ และเหมือนในจิตใต้สำนึกไม่ได้คิดว่ามันคือ “reference log”
    กลับให้ความรู้สึกเหมือนกำลังสั่งให้ Git ขายอะไรบางอย่างให้ถูกลงอีกครั้ง

  • แม้จะไม่ใช่ผู้ใช้ Git แต่พอเห็นแบบนี้ก็ยิ่งรู้สึกว่า git commit เองไม่ได้มีความหมาย สิ่งสำคัญมีแค่ตอนที่ commit ถูก push หรือ merge เท่านั้น
    คล้ายกับการบันทึกไฟล์ข้อความ
    เราไม่ได้เขียนข้อความสั้น ๆ ทุกครั้งที่บันทึกไฟล์ ดังนั้นก็ข้ามไปได้

    • ถ้าเป็นการเปลี่ยนแปลงที่เกิดขึ้นหลังจากการเดินทางดีบักอันยากลำบาก และมีโอกาสที่คนอื่นจะย้อนกลับมาอ้างอิงในภายหลัง ก็เขียนข้อความไว้
      ไม่ใช่แค่สั้น ๆ บางครั้งยิ่งการเปลี่ยนแปลงเล็ก คำอธิบายกลับยิ่งยาวขึ้นด้วยซ้ำ
      เคยเขียน 2–3 ย่อหน้าให้กับการเปลี่ยนแปลง 2–3 บรรทัดที่มีผลกระทบใหญ่
    • ดูชัดเจนมากว่า commit ในเครื่องกับ commit บนรีโมตมีจุดประสงค์ต่างกัน
      commit ในเครื่อง คือวิธีสร้าง checkpoint ณ จุดที่ทุกอย่าง compile ได้และทำงานได้
      เพื่อให้ stash การเปลี่ยนแปลง หรือย้อนกลับไปยังสภาพที่ยังทำงานได้เมื่อทำพัง
      ก่อน push ก็ reset แล้วแบ่งเป็น commit ที่เหมาะสมได้ ประวัติบนรีโมตก็จะยังสะอาดและไม่กลายเป็นกอง wip
      หรือจะ squash merge PR เพื่อได้ข้อดีของทั้งสองฝั่งก็ได้
    • commit เป็นการกระทำที่ทำให้ Git สร้างสำเนาไฟล์ไว้ภายใน จึงสำคัญมาก
      เพียงแต่ไม่จำเป็นต้องใส่ข้อความที่ไม่มีความหมายอย่าง more fixes
      โดยปกติจะสร้าง commit แรกประมาณ (WIP) ชื่อฟีเจอร์ แล้ว amend commit ซ้ำไปเรื่อย ๆ จนพอใจ จากนั้นค่อยลบ (WIP) ออกจากข้อความในตอนท้าย
    • แม้จะเปรียบเทียบกับการบันทึกไฟล์ข้อความ แต่ก็มีคนจำนวนมากที่เขียนบันทึกสั้น ๆ เกี่ยวกับวันนั้นทุกครั้งก่อนนอน
      มองว่า revision log ของ Git ก็คล้ายกับ ไดอารี แบบนั้น
      มันเป็นระเบียบกว่าเอกสาร TODO แยกต่างหาก และชวนให้เราอธิบายสิ่งที่ทำไปแล้วในรูปแบบที่อ่านง่าย
      เวลาตัดสินใจว่าจะย้อนกลับไปแค่ไหน การรู้ว่าตอน commit นั้นคิดอะไรอยู่อาจมีประโยชน์ และถ้าแนวทางผิดพลาด ก็ช่วยในการวิเคราะห์ย้อนหลังได้ด้วย
      ถ้างานที่ยังไม่ได้ merge หรือ push ถูกจัดเป็นการเปลี่ยนแปลงแยกกันพร้อมเป้าหมาย เมื่อบางส่วนดีและบางส่วนแย่ การเก็บเฉพาะส่วนที่ดีไว้ก็จะง่ายขึ้นมาก
    • ก่อน push ทั้งหมดก็ยังเป็น local อยู่ จะทำอย่างไรก็ได้ตามต้องการ
      ถึงอย่างนั้น ในเชิงเทคนิค commit ก็ไม่ได้ไร้ความหมาย
      ถ้าไม่มี commit ก็ไม่มีอะไรให้ push หรือ merge
      ในเชิงไม่ใช่เทคนิค การบันทึกเป็นข้อความธรรมดาว่าทำไมถึงเปลี่ยนบางอย่างก็มีประโยชน์มาก
      ถ้าต้องเขียนคำอธิบายแบบนั้นบ่อยเกินไป ก็ควรทำให้หน่วยของ “การเปลี่ยนแปลง” แคบลง หรือคัดสิ่งที่แตะพร้อมกันให้เข้มงวดขึ้น
      ถ้าไม่ได้ใช้ Git ก็สงสัยว่าใช้เครื่องมืออะไรในการจัดการเวอร์ชันและการจัดการการเปลี่ยนแปลง