git stash & git patched commit

Published on

(สถานการณ์จำลอง)

(สถานการณ์จำลอง 2)

การมี git นั้นทำให้เราสามารถทำ snapshot ของงานส่วนที่เรากำลังทำอยู่ได้ โดยไม่ไปทำของคนอื่นพัง และงานเราไม่หายด้วย ปกติผมจะใช้ 2 command นี้ครับ

1. git stash

git stash ถ้าแปลตรงตัวก็แปลว่า “ซ่อน” code ของเราไว้ก่อน โดย code ที่เราซ่อนไว้จะถูกเก็บใน stash stack และทำให้ repo ของเรา clean เมื่อ stash ไว้แล้วครับ

ตัวอย่างเช่น ใน repo ของเรามี dirty file จาก git status (ข้างขวาเป็น output ของ git diff)

a dirty repo

เราอยากซ่อน changes ของทั้ง 2 file นี้ไว้ ก็ใช้คำสั่ง git stash

$ git stash

repo ของเราก็จะกลับมา clean เหมือนเดิม โดยคำสั่ง stash จะบอก HEAD commit hash ว่า repo ของเราถูก revert ไปที่ commit ใด (ปกติก็เป็น commit ล่าสุดก่อนที่มันจะ dirty แหละ)

git stashed

ถ้าเราแก้ code ไปแล้ว อยาก stash อีก ก็ทำได้ โดยที่ stash ครั้งต่อๆ ไปจะถูกเก็บใน stack เรียกดูได้จาก command git stash list

git 2nd stash

$ git stash list

git stash list

เอา code ที่ stash ไว้ ออกมาจาก stack เพื่อทำงานต่อ ใช้ command git stash pop

git stash pop

และเนื่องจากมันเป็น stack เวลา pop มันเลยเอา stash ล่าสุดออกมาก่อน ซึ่งพอ pop ออกมาแล้ว stash นั้นก็จะหายไปจาก list ครับ (ถ้าอยาก pop แบบไม่ให้มันหาย ใช้ command git stash apply แทน)

git stash กับ untracked file

ปกติแล้ว git stash จะไม่เก็บไฟล์ที่ untracked ไปด้วย (ไฟล์ที่ยังไม่ได้ add ใน git)

git stash ไม่เก็บไฟล์ untracked

ต้องเพิ่ม parameter -u เข้าไปด้วย ให้มัน stash ไฟล์ที่ untracked ไปด้วยครับ

git stash with -u

พอ pop ออกมา ไฟล์ที่เป็น untracked file ก็ยังอยู่ครบเหมือนเดิม

git stash pop with untracked file

workflow คร่าวๆ ก็คือ stash งานของเราไว้ก่อน > ทำส่วนอื่นให้เสร็จ > push งานใหม่ไป > pop stash ออกมาทำต่อ ประมาณนี้ครับ

2. git add/commit -p

--patch หรือ -p เป็น parameter ของ command git add และ git commit ทำให้เราสามารถเลือก add หรือ commit เฉพาะบางส่วนของ code ที่เราแก้ไขไปแล้ว โดย code ส่วนที่เหลือ ก็ยังคงเป็นสถานะ modified (unstaged) อยู่

ตัวอย่างเช่น ผมมีไฟล์ index.html ที่อัพเดท code ไปบางส่วนแล้ว รัน git diff แล้วได้ออกมาแบบนี้

modified code

รัน git add -p index.html git จะแบ่ง code ออกเป็นส่วนย่อยๆ (hunks) แล้วให้เรารีวิวว่า จะเลือกทำอะไรกับ hunk นั้นๆ รูปข้างล่างนี้จะเห็นว่ามี prompt ให้มาให้เราเลือก ซึ่งตัวเลือกก็มี y n q a d / j J g e และก็ ? ซึ่งเราสามารถเลือก ? แล้วกด enter เพื่อดูความหมายของแต่ละตัวเลือกได้ (ผมเองก็ไม่เคยจะจำได้เหมือนกัน)

interactive add

available options

ที่ผมใช้บ่อยๆ ก็จะมี

ตัวเลือก s นั้นมีประโยชน์มาก เนื่องจากปกติแล้ว git จะแบ่ง code ออกเป็น hunk ให้เอง โดยที่ code ที่อยู่ใกล้ๆ กันรวมเป็น hunk เดียวกัน ซึ่งจริงๆ แล้ว code ที่อยู่ใกล้กันนั้นอาจจะเป็นคนละส่วนกันก็ได้ (จริงๆ แล้ววิธีการแบ่ง hunk ของ git นั้นมีหลักเกณฑ์มากกว่านี้ แต่ขอข้ามไปละกันครับ ผมเองไม่ได้เข้าใจทั้งหมดเหมือนกัน)

อย่างตอนนี้ผม add เฉพาะ hunk แรก พอรัน git status ก็จะเห็นสถานะทั้ง staged และ modified (unstaged) จากไฟล์เดียวกัน

added patch

ซึ่งพอ commit ไปแล้ว code ส่วนยังเหลือ ก็ยังอยู่ในสถานะ modified (unstaged) เหมือนเดิม

remaining code

สรุป

ในชีวิตประจำวัน ผมจะใช้ git add -p เกือบทุกครั้ง หลักๆ เพื่อเลือก add/commit เฉพาะเท่าที่จำเป็น กรองเอา code ขยะออก และได้โบนัสเป็นการ review code ที่ตัวเองเขียนไปในตัวด้วย ส่วน git stash นั้น นานๆ จะได้ใช้ทีนึงครับ

Share

(Edit on GitHub)