เริ่มต้นใช้งาน Git

Git คือ เครื่องมือที่เอาไว้บันทึกเวอร์ชันการเปลี่ยนแปลงของไฟล์ในโปรเจคเรา ทำให้เราสามารถที่จะย้อนกลับไปดูเวอร์ชันต่างๆ ของโปรเจคได้ทุกเมื่อ หรือจะดูว่าใครเป็นคนแก้ไขไฟล์นั้นๆ ก็ได้ ซึ่ง Git นั้นจัดว่าเป็น Version Control แบบ Decentralized/Distributed คือไม่ต้องมีเซิร์ฟเวอร์เก็บโค้ดไว้ตรงกลาง ซึ่งจะต่างกับพวก Subversion หรือ CVS ที่ต้องมีเซิร์ฟเวอร์เก็บโค้ดรวมไว้ตรงกลาง (Centralized) และที่สำคัญ Git นั้นทำงานได้เร็วมากกว่าด้วย

ในบทความนี้จะพูดถึงบ้าง

  • Git basic workflow และ core features

  • วิธีการกู้คืนไฟล์ และการบันทึกหลายๆ เวอร์ชันในโปรเจค

  • การใช้ Git ทำงานร่วมกับคนอื่น (Collaborate) ผ่าน Remote Repository (GitHub)

เตรียมความพร้อมก่อนใช้งาน

การติดตั้ง Git

  • Windows ดาวน์โหลดตัวติดตั้งได้จาก https://git-scm.com/downloadsarrow-up-right

  • Mac OS X Yosemite or later ติดตั่งผ่าน Terminal ให้พิมพ์ $ git version

  • Linux ติดตั่งผ่าน Terminal ให้พิมพ์ $ sudo apt-get install git

Git Configurations

ก่อนจะเริ่มใช้งาน Git ได้นั้น จำเป็นต้องตั้งค่าการใช้งานเบื้องต้นก่อน ในบทความนี้จะใช้โปรแกรม Git Bash ที่ติดตั้งมาพร้อม Git for Windows

  • ตั้งชื่อผู้ใช้งาน “user.name”

  • ตั้งอีเมลของผู้ใช้งาน “user.email”

  • ตรวจสอบว่าที่ตั้งค่าถูกต้องหรือไม่

กำหนด Default Text Editor ให้กับ Git

จะใช้ Text Editor ตัวไหนก็ได้แล้วแต่ความถนัด แต่ในบทความจะเลือกใช้ Notepad++arrow-up-right

  • กำหนด Path ที่ติดตั้ง Notepad++ ใน System Environment

  • กำหนดให้ Notepad++ เป็น Default Text Editor

  • ทดสอบ

สมัครใช้งาน GitHub

เชื่อมต่อ Github ด้วย SSH

  1. ตรวจสอบว่ามี SSH keys แล้วหรือไม่ ผ่านโปรแกรม Git Bash

2. ถ้ายังไม่มี ให้สร้างใหม่โดยใช้ GitHub email โปรแกรมจะถามชื่อไฟล์ และรหัสผ่าน ถ้าไม่ต้องการเปลี่ยนแปลงก็กด Enter ไปได้เลย

3. เพิ่ม SSH keys ที่สร้างมาเข้าใน ssh-agent

4. เพิ่ม SSH keys ในบัญชี GitHub ของเรา โดยให้คัดลอก SSH key ก่อน

5. ล็อกอินเข้า https://github.comarrow-up-right เลือกที่รูปโปรไฟล์ > เลือก Setting > เลือกเมนู SSH and GPG keys > คลิก New SSH Key > ให้ตั้งชื่อเครื่องของเราที่ “Title” และวาง SSH key ลงไปที่ “Key” > สุดท้ายกด Add SSH Key

เริ่มได้สักที

1. Basic Git Workflow

ใน Git project จะประกอบด้วย 3 ส่วน

  1. Working Directory: เป็นที่เก็บไฟล์ที่เราทำงานทุกอย่าง ทั้งสร้างใหม่ แก้ไข และลบทิ้ง

  2. Staging Area: คือ ที่รวบรวมรายการที่แก้ไขไปทั้งหมดจาก working directory ที่จะนำเข้า repository

  3. Repository: เป็นที่จัดเก็บไฟล์ที่มีการเปลี่ยนแปลงอย่างถาวร แยกเป็นเวอร์ชัน

Basic Git Workflow

ดังนั้น Git workflow จะประกอบด้วยการแก้ไขไฟล์ใน working directory แล้วนำไฟล์เหล่านั้นเข้า staging area สุดท้ายบันทึกการแก้ไขเข้า Git repository ด้วยคำสั่ง commit ซึ่งมีวิธีการใช้งาน ดังนี้

  • เริ่มจากสร้าง working directory ชื่อ git-demo และสร้างไฟล์ greeting.txt ไว้ข้างใน

  • สร้าง Git repository (.git/)ด้วยคำสั่ง init

  • ตรวจสอบสถานะไฟล์ในโปรเจค git-demo จะพบข้อความเตือนสีแดงใต้ untracked files ซึ่งหมายความว่า Git มองเห็นว่ามีไฟล์อยู่ แต่ไฟล์นี้ยังไม่ได้เริ่ม tracking การเปลี่ยนแปลงของไฟล์นี้เลย

Git Life Cycle Staged : คือสถานะที่ไฟล์พร้อมจะ commit unstaged : คือไฟล์ที่ถูกแก้ไขแต่ว่ายังไม่ได้เตรียม commit untracked : คือไฟล์ที่ยังไม่ถูก track โดย Git (ส่วนมากจะเป็นไฟล์ที่เพิ่งสร้างใหม่) deleted : ไฟล์ที่ถูกลบไปแล้ว

  • วิธีการเริ่มต้น tracking ไฟล์ greeting.txt นั้น คือต้องเพิ่มไฟล์นี้ลงไฟใน staging area ก่อน โดยใช้คำสั่ง git add filename1 filename2 filename3 แต่ถ้าต้องการเพิ่มทุกไฟล์ที่มีการแก้ไข/เปลี่ยนแปลงที่อยู่ใน working directory ใช้ git add .

  • เมื่อลองตรวจสอบสถานะใหม่อีกครั้ง greeting.txt จะเปลี่ยนเป็นสีเขียวแล้ว พร้อมที่จะ commit

เราสามารถบอก Git ได้ว่าไม่ต้องการให้ Git เก็บไฟล์ไหนบ้าง โดยสร้างไฟล์ชื่อ .gitignore ไว้ที่ไดเรกทอรี Git project ภายในก็กำหนดค่าเป็นชื่อไฟล์ หรือชื่อไดเรกทอรีก็ไร หรือจะกำหนดเป็น *.log คือไม่ต้องเก็บไฟล์ .log ทั้งหมด เป็นต้น

  • คราวนี้ให้แก้ไขไฟล์ greeting.txt โดยเพิ่มข้อความบรรทัดใหม่ว่า “git: Hey, Good to see you.” และเมื่อบันทึกเสร็จให้ลองใช้คำสั่ง git diff filename เพื่อดูความแตกต่างของไฟล์ระหว่าง working directory กับ staging area เสร็จแล้วให้เอาไฟล์นี้เอา staging area ด้วย

คำอธิบาย - “me: Hello Git” คือ ข้อความเดิมที่อยู่ใน staging area แสดงด้วยตัวอักษรสีขาว - ในส่วนที่มีการแก้ไขเพิ่มเข้ามาจะขึ้นต้นด้วย + ตัวอักษรสีเขียว - การออกจาก diff mode ให้กด q

  • ขั้นตอนสุดท้ายของ Git workflow คือการ ‘commit’ ไฟล์ที่อยู่ใน staging area เข้าไปเก็บใน Git repository แบบถาวร ด้วยคำสั่ง git commit -m "commit message" โดย commit message นั้นจะต้องอยู่ใน quotation marks, ข้อความต้องเป็น present tense และควรจะไม่เกิน 50 ตัวอักษร

  • ถ้าจะดูประวัติการ ‘commit’ ใน repository ทำได้โดยใช้คำสั่ง git log

Output ที่ได้ มีดังนี้ - เลขการ ‘commit’ ออกมา 40 ตัวอักษร เรียกว่า SHA ตัวอักษรสีเหลือง แต่เวลาอ้างอิงใช้แค่ 7 ตัวอักษรแรก - ชื่อคน ‘commit’ - วันที่ และเวลาที่ ‘commit’ - commit message

  • เนื่องจากรูปแบบการแสดงผลปกติของ git log นั้นดูยากไปหน่อยถ้ามีประวัติการ ‘commit’ หลายๆ ครั้ง ส่วนตัวชอบใช้วิธีให้แสดงประวัติแต่ละครั้งในบรรทัดเดียว ตามนี้

  • ถ้าความขี้เกียจพิมพ์คำสั่งยาวๆ เราสามารถใช้ Git alias สร้างคำสั่งของเราขึ้นมาเองได้ โดยจะเอาการแสดง log ข้างบน มาสร้างเป็นคำสั่ง git hist

  • ลองทดสอบคำสั่งใหม่ดู

สรุปคำสั่ง git init ไว้สร้าง Git repository git status ตรวจสอบสถานะไฟล์ของ working directory และ staging area git add เพิ่มไฟล์ the working directory เข้าสู่ staging area git diff แสดงความแตกต่างของไฟล์ระหว่าง working directory กับ staging area git commitเก็บประวัติการแก้ไขแบบถาวรจาก staging area ไว้ใน repository git log แสดงรายการที่ commit มาทั้งหมด

2. การกู้คืนไฟล์

บางครั้งในการทำงาน เช่น การแก้ซอร์สโค้ด เราอาจจะแก้ซอร์สโค้ดนั้นจนไม่สามารถรันได้อีก และจำไม่ได้ว่าเราแก้ไขอะไรไปแล้วบ้าง ซึ่ง Git นั้นมีฟีเจอร์ง่ายๆ ในการกู้คืนไฟล์ เพื่อแก้ไขความผิดพลาดที่เกิดขึ้นใน Git project ของเรา

  • สมมุติว่าเผลอลบข้อความในไฟล์ greeting.txt ออกทั้งหมด และบันทึกทับไปแล้ว

  • ลองพิมพ์คำสั่ง git show HEAD ซึ่งจะแสดงข้อมูลทุกอย่างจากคำสั่ง git log จาก HEAD commit และต่อท้ายด้วยสิ่งที่แก้ไขเพิ่มเข้ามาจากการ ‘commit’ ครั้งนั้น

HEAD : คือ pointer ที่เก็บทุกๆ commit ของเรา โดยปกติแล้ว HEAD จะชี้ไปที่ commit ล่าสุด reference ของ HEAD จะอยู่ในรูปแบบ SHA

  • ถ้าเราต้องการย้อนกลับแก้ไขไฟล์ greeting.txt กลับไปยังการ HEAD : commit ล่าสุด ให้ใช้คำสั่ง git checkout HEAD filename ก็จะได้ไฟล์กลับมาเหมือนเดิม

  • แต่ถ้าเราเผลอไปใช้ git add จะทำให้ไฟล์ถูกเปลี่ยนสถานะเป็น staged คือพร้อมที่จะ commit แต่เราไม่ต้องการ commit ไฟล์นั้นก่อน ดังนั้นต้องทำให้ไฟล์นั้นกลับมาเป็นสถานะ unstaged เสียก่อน โดยใช้คำสั่ง git reset HEAD filename แต่ไฟล์ไม่ได้ย้อนกลับการแก้ไขให้เหมือนการ checkout นะ

  • กรณีที่เราต้องการย้อนกลับไปยัง commit ใดๆ ใช้คำสั่ง git reset SHA (SHA ใช้แค่ 7 ตัวอักษรแรก) ซึ่งเมื่อย้อนกลับไปแล้ว HEAD จะถูกย้ายกลับไปยัง commit นั้นๆ ด้วย ดูได้จากรูปข้างล่าง และตรง commit สีเทานั้น ก็จะหายไปจาก Git project ด้วย

สรุปคำสั่ง git checkout HEAD filename: ยกเลิกการแก้ไขใน working directory git reset HEAD filename: ยกเลิกสถานะกลับเป็น Unstages ใน staging area git reset SHA: ยกเลิกการแก้ไขกลับไปยัง commit ก่อนหน้าตามที่เลือก

3. Branching and Merging

โดยปกติแล้วการจัดการไฟล์ทั้งหมดจะถูกทำอยู่บน Git branch ที่ชื่อว่า master แต่ถ้าเราต้องการจะแยกไฟล์ทั้งหมดออกไปเป็นอีกเวอร์ชันนึง ก็สามารถทำได้โดยการสร้าง branch ใหม่ขึ้น ซึ่งการแก้ไขอะไรก็ตาม จะไม่กระทบเวอร์ชันเดิมใน branch master เมื่อแก้ไขเสร็จแล้ว และต้องการจะเอากลับมารวมกันก็สามารถทำได้New branch จะมีไฟล์ทั้งหมดที่ commit มาจาก Master และมีการ commit ใน New branch จะไม่ส่งผลกับ Master

  • วิธีการดูว่าตอนนี้เรามี branch อะไรบ้าง และจะมี * (asterisk) อยู่หน้าชื่อ branch ที่กำลังทำงานอยู่ ทำได้โดย

  • สร้าง branch ใหม่ ชื่อ goodbye โดยใช้คำสั่ง git branch new_branch_name

  • สลับไปใช้งาน branch ใหม่ โดย git checkout branch_name

เราสามารถสั่ง git checkout -b branch_name เพื่อสร้าง branch ใหม่ พร้อมเปลี่ยนไปใช้งานได้เลย

  • ทดสอบสร้างไฟล์ใหม่ และ commit ดู

  • ลองดูจาก log เทียบกันระหว่าง 2 branch ดู จะพบว่า goodbye.txt จะมีอยู่แต่ใน branch ชื่อ goodbye เท่านั้น ส่วนใน master ไม่มีอะไรเปลี่ยนแปลง

  • แต่ถ้าต้องการรวม branch goodbye เข้าไปใน master ให้สลับกลับมาอยู่ master ก่อน จากนั้นใช้คำสั่ง git merge branch_name

เมื่อลองดูจากลอง commit 9afb852 ของ branch goodbye จะถูกรวมเข้ากับ master เรียบร้อยแล้ว

  • แต่ถ้ามีการแก้ไขไฟล์จาก master และได้ทำการ commit ไปก่อนที่จะทำการ merge และใน goodbye branch ก็มีการแก้ไขไฟล์เดียวกันด้วย เมื่อสั่ง merge Git จะไม่ทราบว่าเราจะเอาเวอร์ชันไหนกันแน่ สิ่งนี้เรียกว่า Merge Conflict

  • เมื่อลองเปิดไฟล์ดูข้างใน notepad++ goodbye.txt จะข้อความแปลกๆ แบบนี้

คือ Git จะไม่รู้ว่าเราต้องการเก็บข้อมูลชุดไหนไว้กันแน่ โดยจะมี Git’s special markings บอกเอาไว้ว่าข้อความของ master branch จะอยู่ระหว่าง <<<<<<< HEAD กับ ======= ส่วนของ goodbye branch อยู่ระหว่าง ======= กับ >>>>>> ซึ่งเราต้องแก้ไขเองว่าจะเอาข้อความไหน และต้องลบ Git’s special markings ออกด้วย

เมื่อแก้ไข conflict เสร็จแล้วก็สั่ง add เข้า staging area และ commit เก็บไว้

  • สุดท้ายเมื่อเรา merge branch ที่เราแยกออกไปเสร็จแล้ว หรือไม่ต้องการ branch นั้นๆ แล้ว ก็สามารถลบทิ้งได้ โดยใช้คำสั่ง git branch -d branch_name

สรุปคำสั่ง git branch: ใช้แสดงรายชื่อ branch ทั้งหมด git branch branch_name: สร้าง branch ใหม่ git checkout branch_name: สลับไปใช้งาน branch ที่ระบุ git merge branch_name: ใช้รวมไฟล์จาก branch ที่ระบุ มายัง branch ปัจจุบัน git branch -d branch_name: ลบ branch ที่ระบุ

4. Git Remote Repository

จากที่ศึกษาวิธีการใช้ Git มาจากข้างต้นนั้นจะเป็นการใช้งานแบบ single user บน local repository ที่อยู่บนเครื่องใครเครื่องมัน แต่ Git นั้นจัดเป็น collaboration tool ตัวนึงที่ทำให้เราทำงานร่วมกับผู้อื่นในโปรเจคได้ง่ายขึ้น โดยผ่าน remote repository เช่น GitHub หรือ Bitbucket ซึ่งจะเป็นตัวกลางในการทำ pulling หรือ pushing งานในโปรเจคที่ทำร่วมกัน

ตัวอย่างสร้าง remote repository อยู่บน GitHubarrow-up-right ชื่อ github-demo

  • ล็อกอินเข้า GitHubarrow-up-right เลือกเครื่องหมาย + ข้างๆ รูปโปรไฟล์ แล้วเลือกเมนู New repository

  • ตั้งชื่อ Repository name และเลือก “ Initialize this repository with a README” เพื่อสร้างไฟล์ README.md กดปุ่ม Create repository

เมื่อได้ remote repository มาแล้ว ก็ให้ ‘clone’ มาไว้ที่เครื่องของเรา โดยใช้คำสั่ง git clone remote_location clone_name ซึ่ง remote_location คือที่อยู่ของ remote repository และ clone_name คือชื่อไดเรกทอรีที่จะให้บันทึก แต่ถ้าไม่ระบุ Git จะสร้างไดเรกทอรีชื่อเดียวกับชื่อของ repository ให้อัตโนมัติ

สิ่งที่ Git ทำอยู่เบื้องหลังเมื่อเรา clone โปรเจคมา คือ Git จะสร้าง remote address ขึ้นมาชื่อ origin เพื่อความสะดวกในการอ้างอิงถึง remote repository โดยใช้เพียงแค่ชื่อ ถ้าต้องการจะดูว่าใน Git project ของเรามีรายการ remotes อะไรบ้าง ใช้คำสั่ง git remote -v จากในไดเรกทอรีของ Git project

fetch คือ remote address ที่จะให้ไปดึงจากฝั่ง remote มายังฝั่ง local push คือ remote address ที่จะให้เอาจากฝั่ง local ไปรวมที่ฝั่ง remote ที่ไหน

หลังจากที่เรา clone โปรเจคมานานแล้ว และไม่ทราบว่าทางฝั่ง remote นั้นมีการเปลี่ยนแปลงอะไรเกิดขึ้นแล้วบ้าง เราสามารถตรวจสอบได้โดยใช้คำสั่ง git fetch

  • แก้ไขไฟล์ README.md ที่ GitHub โดยเพิ่มข้อความในบรรทัดใหม่ว่า “This line from remote repository.”

  • ดึงข้อมูลจากฝั่ง remote ว่ามีการเปลี่ยนแปลงอะไรเกิดขึ้นบ้าง

  • ตรวจสอบด้วย git status จะได้ข้อความดังนี้

  • หมายความว่าบน local ( branch master)นั้นตามหลังบน remote ( branch origin/master) อยู่ 1 commit ซึ่งเราสามารถรวมโค้ดจาก remote มายัง local ได้ด้วยวิธีเดียวกันกับการรวมโค้ดจาก branch อื่น โดยใช้คำสั่ง git merge โดยระบุชื่อ branch เป็น “origin/master”

git pull คือการรวมโค้ดจาก remote มายัง local เลยโดยไม่สนใจว่าระหว่าง remote กับ local ต่างกันอย่างไรบ้าง ซึ่งจริงแล้ว git pull คือการทำ git merge แล้วต่อด้วย git pull ให้แบบอัตโนมัติ

ต่อมาเมื่อเรามีการแก้ไขจากฝั่ง local และต้องการจะส่งไปเก็บไว้ที่ฝั่ง remote ด้วย ทำได้โดยใช้คำสั่ง git push remote_alias_name branch_name เช่น git push -u origin master

  • -u : เอาไว้จำ parameter origin master ครั้งต่อๆ ไปก็พิมพ์แค่ git push

  • origin : คือ ชื่อ alias ของ remote (github)

  • master : คือ ชื่อ branch ที่เราต้องการ push ขึ้นไป

  • เมื่อลองไปดูจาก GitHub จะเห็นว่าไฟล์ README.md จะถูกอัพเดทแล้ว

สรุปคำสั่ง git clone: สร้าง local repository จาก remote repository git remote -v: แสดงรายการ remote address ทั้งหมด git fetch: ดึงข้อมูลทั้งหมดจากฝั่ง remote มายัง local git merge origin/master: สั่งรวมไฟล์จาก origin/master มายัง local branch git pull: สั่งรวมไฟล์จาก ฝั่ง remote มายัง local (git fetch + git merge) git push origin <branch_name>: ส่งข้อมูลจาก local branch ไปรวมกับ originremote.

5. Stashing

คือการบันทึกโปรเจคของเรา และซ่อนเอาไว้ เมื่อจะใช้ก็สั่ง restore กลับมาได้ตลอดเวลา เช่น กรณีที่เรากำลังแก้ไขไฟล์อยู่ และจำเป็นต้องสั่ง commit โปรเจคนี้ แต่ไฟล์นี้ยังแก้ไขไม่เสร็จเลยไม่ต้องการ commit ในครั้งนี้ด้วย ก็ใช้ stash เพื่อซ่อนไฟล์นี้เอาไว้ก่อน เมื่อได้ commit เสร็จแล้ว ก็สั่ง restore ไฟล์ที่ซ้อนไว้กลับมา แก้ไขจนเสร็จ แล้วค่อย commit ใหม่

  • git stash: สั่งซ้อนไฟล์

  • git stash list: แสดงรายการที่ซ้อนไว้ โดยรายการล่าสุดจะอยู่ที่ stash@{0}

  • git stash pop: สั่ง restore รายการล่าสุดกลับมา

6. Tagging

ก่อนที่จะทำการ release ระบบออกไปนั้น แนะนำให้ทำการสร้าง tag หรือ ป้ายชื่อ เพื่อบอกให้รู้ว่าเรากำลังทำอะไร อยู่ตรงไหน

  • git tag tag_name SHA: สร้าง tag ขึ้นมาใน commit ที่ระบุ ถ้าไม่ระบุจะเป็น HEAD commit

  • git tag --list: แสดงรายการชื่อ tag ทั้งหมด

  • git tag -d tag_name: สั่งลบจากชื่อ tag ที่ระบุ

  • git show tag_name: แสดงรายละเอียด commit จากชื่อ tag ที่ระบุ

  • git tag -a tag_name -m "message": สร้าง tag แบบระบุข้อความบอกว่า tag นี้คืออะไร ซึ่งเมื่อใส่ git show tag_name จะแสดงข้อความจาก -m ขึ้นมาให้ด้วย

7. Remove

  • git rm filename : สั่งลบไฟล์ และสั่งให้ Git ทำการ untracked ไฟล์ด้วย

  • git rm --cached filename : สั่งลบไฟล์ออกจาก Git repository เฉยๆ ไม่ได้ลบไฟล์จริงใน working directory ออกด้วย

สรุป

บทความนี้จะพูดถึงการใช้งาน Git ผ่าน Command Line เพื่อต้องการให้เกิดความใจว่า Git นั้นทำงานอย่างไร แต่ละขั้นตอนใช้คำสั่งอะไรบ้าง เมื่อเปลี่ยนไปใช้ Git แบบ GUI เช่น SourceTreearrow-up-right หรือ GitHub Desktoparrow-up-right จะได้จะรู้ว่าการทำงานของมันมีที่มาที่ไปอย่างไร แต่สุดท้ายเราจะเลือกใช้งานแบบ Command Line หรือ GUI ก็แล้วความถนัดของเราครับ

Reference : https://medium.comarrow-up-right

Last updated