Git คืออะไร ? + พร้อมสอนใช้งาน Git และ Github
ถ้าพูดถึง Git ณ ชั่วโมงนี้หากใครที่ไม่เคยได้ยินหรือไม่เคยใช้งานเลย ก็ต้องบอกว่าท่านเชยมากครับ สำหรับนักพัฒนาแล้ว Git เป็นสิ่งที่จำเป็นมากๆ แม้ว่าเราจะทำงานคนเดียวหรือทำงานเป็นทีมก็ตาม ฉะนั้นบทความนี้ผมจึงเขียนขึ้นเพื่อสำหรับมือใหม่ ที่กำลังศึกษา หรือยังไม่รู้จัก Git ให้สามารถใช้ Git เบื้องต้นได้
สำหรับบทความก่อนหน้าที่ผมเขียนก็เป็นสรุปๆ จาก Try Git และ Cheat Sheet ตามนี้ครับ
ส่วนเนื้อหาของบทความนี้ก็ประกอบไปด้วย
Table of Contents
- Step 0 : ปัญหาการไม่ใช้ Git
- Step 1 : Git คืออะไร ?
- Step 2 : เริ่มต้นติดตั้ง Git
- Step 3 : สร้างโปรเจ็คแรกด้วย Git
- Step 4 : รู้จักกับ Github
- Step 5 : Git GUI / Client
- Step 6 : Workshop
ปัญหาการไม่ใช้ Git
สำหรับคนที่ยังไม่เคยได้ใช้ Git หรือกำลังคิดว่า Git มันมีประโยชน์อย่างไร ให้ท่านลองคิดว่าเคยเจอปัญหาเหล่านี้หรือไม่ ?
- Backup Project ทุกๆวัน โดยการ copy folder แล้วเปลี่ยนชื่อ เช่น ตั้งเป็น วันเดือนปี เป็นต้น
- หากวันใดอยากกลับไปแก้งานที่เคยทำไว้ จะหา project ที่เรา backup ไว้อย่างไร? จำได้ไหมว่าที่แก้ไปนั้น แก้ไว้วันไหน ?
- หากเผลอลบโค๊ด หรือทำโค๊ดหาย อยากจะกู้คืนทำยังไง ? ใช้ Backup เก่า? หากต้องการแก้แค่ก่อนหน้า ไม่ได้แก้ทั้งหมดของวันละ ?
- อยากทดลองทำ feature ใหม่ๆจากโปรเจ็คเก่า จะทำยังไง โดยไม่ต้องก็อปปี้ทั้งโปรเจ็ค แล้วมาเปลี่ยนชื่อโฟลเดอร์ ?
- ปัญหา Hard Disk เต็ม เนื่องจากนั่ง backup ทุกๆวัน จนเนื้อที่ไม่พอ
- ทำงานกันเป็นทีม ยังต้องเซฟใส่ Flash Drive ส่งให้กันอยู่หรือเปล่า ?
- ทำงานกันเป็นทีม แล้วจะแบ่งแยกงานกันยังไง แล้วถ้าเกิดว่าแก้ไขที่เดียวกัน ถ้าใช้การเซฟลง Flash Drive จะแก้ปัญหายังไง ? ช่วยกันนั่งไล่โค๊ด ? เสียเวลาไหม :)
- หากงานที่เราทำเป็น Production ใช้งานไปแล้ว แต่เราอยากพัฒนาโดยไม่กระทบกับ Production จะทำยังไง ?
หากด้านบน เป็นปัญหาที่ท่านพบเจออยู่ทุกๆวัน ได้เวลาแล้วที่ท่านจะมาเรียนรู้การใช้งาน Git กันครับ
Step 1 : Git คืออะไร ?
Git คือ Version Control ตัวหนึ่ง ซึ่งเป็นระบบที่มีหน้าที่ในการจัดเก็บการเปลี่ยนแปลงของไฟล์ในโปรเจ็คเรา มีการ backup code ให้เรา สามารถที่จะเรียกดูหรือย้อนกลับไปดูเวอร์ชั่นต่างๆของโปรเจ็คที่ใด เวลาใดก็ได้ หรือแม้แต่ดูว่าไฟล์นั้นๆใครเป็นคนเพิ่มหรือแก้ไข หรือว่าจะดูว่าไฟล์นั้นๆถูกเขียนโดยใครบ้างก็สามารถทำได้ ฉะนั้น Version Control ก็เหมาะอย่างยิ่งสำหรับนักพัฒนาไม่ว่าจะเป็นคนเดียวโดยเฉพาะอย่างยิ่งจะมีประสิทธิภาพมากหากเป็นการพัฒนาเป็นทีม
อ่านรายละเอียดเพิ่มเติมได้ที่ Pro Git : แปลไทย
Step 2 : เริ่มต้นติดตั้ง Git
แน่นอนเว็บสำหรับดาวน์โหลดและติดตั้ง Git ก็ที่เว็บนี้เลย เลือกลงตาม OS ที่ใช้งาน Git SCM
อีกทั้งภายในเว็บยังมีบทความทั้ง Tutorials หรือ Documents ต่างๆให้อ่านอีกด้วย
หากใช้ Linux ก็ติดตั้งง่ายๆ ผ่าน Terminal ด้วย:
sudo apt-get install git
หรือบน Mac OS X ถ้าไม่ใช้ตัว Git Installer ด้านบน ก็ติดตั้งผ่าน Homebrew ได้เช่นกัน
brew install git
เมื่อดาวน์โหลดและติดตั้ง Git เรียบร้อยแล้ว สิ่งที่ต้องทำต่อมาก็คือ Setup ชื่อและอีเมล์สำหรับใช้งาน Git ครับ ตั้งค่าผ่าน Terminal ด้วย:
git config --global user.name "YOURNAME"
git config --global user.email "your@email.com"
เช็คสถานะ ว่า config อะไรไปแล้วบ้างด้วย
git config --list
Step 3 : สร้างโปรเจ็คแรกด้วย Git
เริ่มต้นสร้างโปรเจ็คขึ้นมาเปล่าๆ ผมทำการตั้งชื่อว่า git101
ภายในประกอบด้วยไฟล์ index.html
1 ไฟล์ ง่ายๆดังนี้
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Introduction to Git and Github by DevAhoy</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
git init
เปิด Terminal แล้วไปที่ Folder ของโปรเจ็คเรา จากนั้นสั่ง:
git init
Initialized empty Git repository in /path/to/your/project/.git/
คำสั่ง git init
เอาไว้เพื่อสร้าง git repository เปล่าๆขึ้นมา โดย Git จะทำการสร้างโฟลเดอร์ .git
ขึ้นมาภายในโปรเจ็คของเรา (Hidden ไว้อยู่)
บางครั้งเราจะเรียกโปรเจ็คที่ใช้ Git ว่า repository ก็ได้
git status
ต่อมาทดสอบสั่งรัน:
git status
เพื่อตรวจสอบสถานะ repository ของเรา จะเห็นข้อความประมาณนี้
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
index.html
nothing added to commit but untracked files present (use "git add" to track)
ข้อความด้านบน จะทำให้เรารู้ว่า Git บอกว่าไฟล์ของเรา index.html
ยังไม่ได้ถูก track
git add
วิธีที่เราจะทำให้ไฟล์เราโดน track โดย Git ก็คือการใช้ git add FILENAME
เช่น
git add index.html
ตอนนี้ไฟล์ของเราได้ถูก track โดย Git แล้ว ต่อมาลองเช็คสถานะด้วย git status
อีกครั้ง จะเห็นว่าสถานะของ repository เราได้เปลี่ยนไปแล้ว
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: index.html
เราสามารถ ignore ได้ว่าจะให้ git ไม่ต้องเก็บไฟล์ไหน โดยสร้างไฟล์ชื่อ
.gitignore
ไว้ที่ root folder ภายในก็กำหนดค่าเช่น*.log
ไม่ต้องเก็บไฟล์ .log ทั้งหมดไว้บน git เป็นต้น
ตอนนี้ไฟล์ index.html ของเราอยู่ใน staged ซึ่งเป็นสถานะที่พร้อมจะทำการ commit แล้ว
เกี่ยวกับ Git Life Cycle
- Staged : คือสถานะที่ไฟล์พร้อมจะ commit
- unstaged : คือไฟล์ที่ถูกแก้ไขแต่ว่ายังไม่ได้เตรียม commit
- untracked : คือไฟล์ที่ยังไม่ถูก track โดย Git (ส่วนมากจะเป็นไฟล์ที่เพิ่งสร้างใหม่)
- deleted : ไฟล์ที่ถูกลบไปแล้ว
git commit
ต่อมา เราจะทำการ commit ด้วยคำสั่ง git commit -m "YOUR MESSAGE"
ฉะนั้น commit แรกผมจะใส่ข้อความบอกไว้ว่า ได้ทำการเพิ่มไฟล์ index แล้วนะ ดังนี้
git commit -m "add sample index page"
[master (root-commit) 2a33074] add sample index page
1 file changed, 10 insertions(+)
create mode 100644 index.html
git commit
คือการสร้าง snapshot ให้กับ repository ทำให้เราสามารถย้อนกลับมาดูว่าเราเปลี่ยนหรือแก้ไขโค๊ดอะไรไปบ้างได้
เกี่ยวกับการใช้งาน git add
เราสามารถ add ที่ละหลายๆไฟล์ด้วยการใช้ * ก็ได้ เช่น
git add .
: add ไฟล์ทั้งหมดgit add '*.txt'
: add ไฟล์ทั้งหมดที่นามสกุล .txt เป็นต้น
git log
เราสามารถตรวจสอบดูได้ว่าเราทำอะไร git ไปแล้วบ้าง ด้วยการใช้คำสั่ง
git log
ต่อมาผมทำการสร้างไฟล์เปล่าๆ ขึ้นมาอีก 2 ไฟล์คือ about.html
และ contact.html
จากนั้นลองเช็คสถานะด้วย git status
อีกครั้ง จะได้ดังภาพ
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
about.html
contact.html
nothing added to commit but untracked files present (use "git add" to track)
สิ่งที่เราต้องทำก็คือ ทำการ git add
เพื่อให้ไปอยู่ใน staged และพร้อมที่จะ commit ก็เริ่มเลย
git add about.html contact.html
git commit -m "add empty about and contact page"
ลองนึกถึง หากตอนนี้ถ้าเป็นโปรเจ็คจริงๆ แล้วเราเผลอลบไฟล์ไปจะทำยังไง ? Git ช่วยได้ครับ ตอนนี้สมมติ ลองลบไฟล์ index.html ทิ้งดูครับ แล้วลอง git status
ดูว่าเป็นยังไง
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: index.html
no changes added to commit (use "git add" and/or "git commit -a")
Git ก็รู้ทันทีว่าไฟล์ของเราถูกลบออกไปแล้ว แต่ Git มัน track ไว้ให้ และลองใช้อีกคำสั่งครับ นั่นก็คือ
git diff
git diff HEAD
เอาไว้เช็คว่ามีอะไรเปลี่ยนแปลงบ้าง จากข้อความด้านล่าง โค๊ดสีแดงคือโค๊ดที่ลบ ถ้ามีสีเขียวแสดงว่าเป็นโค๊ดที่ถูกเพิ่ม
diff --git a/index.html b/index.html
deleted file mode 100644
index 144f699..0000000
--- a/index.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <title>Introduction to Git and Github by DevAhoy</title>
-</head>
-<body>
- <h1>Hello World</h1>
-</body>
-</html>
\ No newline at end of file
git reset
ทีนี้อยากจะ reset กู้คืนไฟล์ที่เผลอลบไป เช่น เผลอลบ index.html
ก็เพียงแค่ใช้คำสั่ง
git checkout index.html
แต่ถ้าเราดันเผลอลบ แล้วก็ยังไป add เข้าสู่ staged แล้ว ก็ต้องใช้
git reset index.html
แล้วถ้าเราดันไป commit มันซะแล้ว วิธีที่จะย้อนกลับไป commit ล่าสุดก็คือ
git reset --soft HEAD~1
ส่วนถ้าเราใช้คำสั่งนี้ จะเป็นการลบไฟล์ index.html
ออกจากการ track ของ Git แต่ไม่ได้ลบไฟล์ในโปรเจ็คของเรา
git remove --cached index.html
Git branch
ต่อมาเป็นการพูดถึง git branch
เป็น feature ที่ช่วยให้นักพัฒนาสามารถที่จะทำงานได้สะดวกขึ้น ยกตัวอย่างเช่น เรามีโค๊ดที่ดีอยู่แล้ว แต่อยากจะทดลองอะไรนิดๆหน่อย หรือแก้ไขอะไรก็ตาม ไม่ให้กระทบกับตัวงานหลัก ก็เพียงแค่สร้าง branch ใหม่ขึ้นมา เมื่อแก้ไขหรือทำอะไรเสร็จแล้ว ก็ค่อยเซฟกลับมาที่ master เหมือนเดิม
วิธีการสร้าง branch ใหม่ จะใช้คำสั่ง
git branch create_new_page
ลองดูรายชื่อ branch ทั้งหมดที่เรามี ดังนี้
git branch
* master
create_new_page
ตอนนี้เรามี 2 branch อยู่ในเครื่อง วิธีการสลับ branch เราจะใช้ git checkout
git checkout
git checkout branch_name
เอาไว้สำหรับเปลี่ยน branch ตัวอย่างเช่น git branch create_new_page
ย้าย branch ไปยัง create_new_page
เราสามารถสั่ง
git checkout -b create_new_page
แบบสั้นๆได้ เป็นการสร้าง branch ใหม่และcheckout
ให้เลย เป็นการรวมสองคำสั่งเป็นคำสั่งเดียว นั่นเอง
ใน branch create_new_page
ผมเพิ่มไฟล์มาสองไฟล์ service.html
และ portfolio.html
จะเห็นว่าไฟล์ในโฟลเดอร์จะเป็นแบบนี้
จากนั้นทำการ commit ไฟล์ที่เพิ่มลงไปใหม่
git add '*.txt'
git commit -m "I just added new two pages on create_new_page branch"
แล้วลองย้อนกลับไป brach master ด้วย git checkout master
ไฟล์ในโฟลเดอร์จะไม่มี service.html
และ portfolio.html
เนื่องจากเราไม่ได้สร้างที่ brach master นั่นเอง
git merge
ทีนี้สมมติว่าเรา ทดลองทำ feature อะไรใหม่ๆ แล้วคิดว่ามันดีแล้ว อยากเอามารวมกับ master เราก็ใช้คำสั่ง git merge
โดยตัวอย่าง ผมสร้างไฟล์ service.html
และ portfolio.html
ที่ branch create_new_page
และจะนำมารวมกับ master ก็เพียงแค่ใช้:
git checkout master
git merge create_new_page
- เริ่มต้นด้วยการ ไปที่ branch หลัก (master)
- จากนั้นก็สั่ง
git merge branch_name
จาก branch ที่ต้องการ มาที่ master
Updating 9d0d9f8..4f176d9
Fast-forward
portfolio.html | 0
service.html | 0
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 portfolio.html
create mode 100644 service.html
จะเห็นว่าตอนนี้ brach master มีไฟล์ 2 ไฟล์ที่เพิ่มเข้ามาใหม่ พร้อมกับ commit message ที่เคย commit ไว้ก็จะถูกรวมมาอยู่ใน master หมด ทีนี้เมื่อเราทำ feature อะไรเสร็จแล้ว brach create_new_page
ก็ไม่ต้องการละ สามารถลบ branch ได้ด้วยคำสั่ง
git branch -d branch_name
git branch -d create_new_page
สำหรับ Git เบื้องต้นในส่วนของ local ก็หมดเพียงเท่านี้ครับ ต่อไปจะเป็น Git บน Server ห
Step 4 : รู้จักกับ Github
Github คืออะไร ? Github เป็นเว็บเซิฟเวอร์ที่ให้บริการในการฝากไฟล์ Git (ทั่วโลกมักนิยมใช้ในการเก็บโปรเจ็ค Open Source ต่างๆ ที่ดังๆ ไม่ว่าจะเป็น Bootstrap, Rails, Node.js, Angular เป็นต้น)
ขั้นตอนแรก ให้ทำการสมัครสมาชิกกับ Github จากนั้นเมื่อสมัครสมาชิกแล้ว เราสามารถที่จะสร้าง Repository ของเราแล้วเอาไปฝากไว้บน Github ได้ครับ (การทำงานทุกอย่างก็เหมือนตอนทำ local)
จุดเด่นของ Github คือใช้ฟรี และสร้าง repository ได้ไม่จำกัด แต่ต้องเป็น public repository เท่านั้น หากอยาก private ก็ต้องเสียตังครับ
Create Repo
ตอนนี้ผมจะทำการสร้าง repository โดยจะเอาโค๊ดที่ได้เขียนไว้ ก็โปรเจ็ค git101
จาก Step 3 นั่นแหละครับ คราวนี้มันจะถูกอัพโหลดขึ้นเซิฟเวอร์แล้ว วิธีการก็ไม่ยาก เพียงแค่กด +
มุมบนขวา แล้วเลือก New repository
จากนั้นก็ทำการตั้งชื่อ repo รวมถึงคำอธิบาย
ไม่ต้องติ๊กเลือก initialize this repository with a README เนื่องจากเรามี repository อยู่แล้ว
ซึ่งจริงๆแล้ว Github ก็มีคำอธิบายบอกไว้แล้วว่าเราจะต้องทำยังไงต่อ ดังรูป
สิ่งที่เราต้องทำต่อมาก็คือ เพิ่ม url ของ remote (Server) เพื่อให้รู้ว่าเราจะฝากโค๊ดไว้ที่ใด
กลับมาที่เครื่องเรา เข้าไปที่โฟลเดอร์ปัจจุบัน จากนั้นพิมพ์คำสั่ง
git remote add origin git@github.com:Phonbopit/git101.git
ที่อยู่ url ของ repository แต่ละคนก็ต่างกันไปนะครับ อย่าเผลอก็อปปี้ url ของผมไปละ ซึ่งบางคนอาจจะเป็น https ก็ไม่ต้องแปลกใจครับ
ต่อมาเช็คให้แน่ใจว่าเราทำการเพ่ิม remote ได้ถูกต้องด้วย git remote -v
origin git@github.com:Phonbopit/git101.git (fetch)
origin git@github.com:Phonbopit/git101.git (push)
Git Push
ต่อมาเราจะทำการส่งโค๊ดจากเครื่อง local ไปที่ Github ด้วยคำสั่ง
git push -u origin master
-u
: เอาไว้จำ parameter origin master ต่อไปก็แค่พิมพ์git push
origin
: คือชื่อ alias ของ remote (github)master
: คือชื่อ branch ที่เราต้องการ push ขึ้นไป
จากนั้นก็ใส่ชื่อ accout github และ password (โดย password เราจะไม่เห็นว่าพิมพ์อะไรลงไป เมื่อพิมพ์ password เสร็จให้กด Enter)
สำหรับคนที่เลือกเป็น https จะต้องใส่ Username และ Password ทุกครั้งที่มีการ connect github แต่ถ้าเลือกแบบ ssh จะไม่ต้องใส่ Password แต่จะต้องไปเซ็ทค่า ตามนี้ Generating SSH Keys
เพื่อ push โค๊ดเรียบร้อย จะได้ข้อความประมาณนี้
ounting objects: 8, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (8/8), 829 bytes | 0 bytes/s, done.
Total 8 (delta 1), reused 0 (delta 0)
To git@github.com:Phonbopit/git101.git
* [new branch] master -> master
Branch master set up to track remote branch master from origin.
เมื่อเราทำการ Push Code ขึ้นไปบน Github แล้วเมื่อลองเข้าเว็บไซต์ https://github.com/Phonbopit/git101 ก็จะเห็นไฟล์ของเราขึ้นไปแล้ว(url แต่ละคนจะไม่เหมือนกันนะครับ ต่างกันที่ username และชื่อ repo)
Git Fetch
Git Fetch เป็นการเช็คโค๊ดของเราระหว่าง local กับ remote(server) ว่าโค๊ดตรงกันล่าสุดหรือไม่ ซึ่งตอนนี้เราเพิ่ง Push ลงไป ทำให้โค๊ดมันเหมือนกัน ถ้าเรา fetch
ก็ไม่มีไรเกิดขึ้น ฉะนั้นลองเข้าหน้า project ใน Github แล้วกด Add a README ปุ่มเขียวๆ เพื่อเพิ่มไฟล์ README.md
ผ่านบราวเซอร์เลยครับ
จากนั้นก็พิมพ์ข้อความ เสร็จแล้วกด Commit new file
เราก็จะได้ไฟล์ README.md
เพิ่มเข้ามาในโปรเจ็คแล้ว ใน Github มี แต่ว่าลองย้อนกลับมาที่โปรเจ็ค local ของเรา ยังคงไม่มีไฟล์ README.md ที่เพิ่งเพิ่มลงไป วิธีการก็คือ ทำการ
git fetch
จะเห็นข้อความประมาณนี้
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:Phonbopit/git101
4f176d9..a7f9fd4 master -> origin/master
เมื่อลอง git status
ก็จะได้ดังนี้
On branch master
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
nothing to commit, working directory clean
นั้นหมายความว่า โค๊ด local ของเรานั้นล้าสมัย หรือว่าตามหลัง master บน remote อยู่ 1 commit วิธีการที่เราจะรวมโค๊ดจาก remote มาที่ local ก็ใช้วิธีเดียวกันกับการรวมโค๊ดคนละ branch นั่นก็คือ git merge
ครับ
โดยทำการระบุ branch ที่ต้องการ ในที่นี้คือ origin/master
git merge origin/master
Updating 4f176d9..a7f9fd4
Fast-forward
README.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 README.md
ตอนนี้ที่เครื่อง local ก็อัพเดทตรงกับ remote แล้ว และก็มีไฟล์ README.md ที่สร้างไว้ด้วย คราวนี้ลองนึกถึงกรณีที่ทำงานร่วมกันหลายๆคน แต่ละคนก็ Push โค๊ดขึ้นไปเก็บไว้ และวิธีที่จะอัพเดทโค๊ดให้ล่าสุดเสมอก็คือการใช้ git fetch
และ git merge
นั่นเอง
Git Pull
จริงๆแล้ว git pull
ก็คือรวมโค๊ดจาก remote มายัง local โดยที่เราไม่สามารถรู้ได้เลยว่าจะรวมโค๊ดอะไรบ้าง รู้แค่หลังจาก pull เสร็จแล้วนั่นเอง ซึ่งจริงๆแล้ว git pull
มันก็คือการทำ git fetch
และต่อด้วย git merge
อัตโนมัตินั่นเอง
Git Conflict
โดยปกติแล้ว git merge
จะรวมโค๊ดให้เราเองอัตโนมัติ แต่ก็จะมีข้อยกเว้นเมื่อ แก้ไขไฟล์เดียวๆกัน ลองนึกถึงกรณีที่เราและเพื่อนร่วมทีม แก้ไขไฟล์เดียวกัน Git จะเกิดการ conflict เมื่อเราจะ merge โค๊ด โดยไม่รู้ว่าจะใช้โค๊ดของเราหรือของเพื่อน วิธีแก้ก็คือ ทำการ edit แล้ว commit ไปใหม่นั่นเอง
ตัวอย่างคร่าวๆ ของไฟล์ที่เกิด conflict
git pull
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
และตัวอย่างไฟล์
git101
---
Sample git repo
<<<<<< HEAD
edit on sublime text.
=======
last edit on browser via github.com
>>>>>>> origin/master
format ของไฟล์ conflict จะถูกขั้นด้วย <<<<<<< HEAD
จนถึง =======
สำหรับโค๊ดส่วนที่เราแก้ไข และ =======
ถึง >>>>>>>> branch_name
ส่วนที่เป็นโค๊ดของคนอื่นๆ/branch อื่น
วิธีแก้ก็แค่ลบพวกโค๊ดส่วนเกินออก แล้วแก้ไขใหม่ให้เรียบร้อย จากนั้นลองเช็คสถานะ จะขึ้นประมาณนี้
git status
Your branch and 'origin/master' have diverged,
and have 1 and 1 different commit each, respectively.
(use "git pull" to merge the remote branch into yours)
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
ก็ commit และ push ได้ปกติแล้วครับ
git add README.md
git commit -m "fixed conflict on README.md"
git push
เป็นอันเรียบร้อย
Git Clone
ในกรณีที่เราไปเจอโปรเจ็ค cool cool น่าสนใจ เราสามารถที่จะเซฟมาลงเครื่องของเราได้เลย เราเรียกการทำแบบนี้ว่าการ clone เหมือนกับการกดดาวน์โหลดโปรเจ็คมานั่นแหละครับ วิธีง่ายๆ ก็คือ ใช้คำสั่ง
git clone git_url
วิธีการดูโปรเจ็คที่เราต้องการ ก็อย่างเช่น gitignore ด้านขวามือจะมี url แสดง ก็จะได้เป็น
git clone https://github.com/github/gitignore.git
Cloning into 'gitignore'...
remote: Counting objects: 4776, done.
remote: Total 4776 (delta 0), reused 0 (delta 0), pack-reused 4776
Receiving objects: 100% (4776/4776), 1.04 MiB | 227.00 KiB/s, done.
Resolving deltas: 100% (2323/2323), done.
Checking connectivity... done.
แค่นี้โปรเจ็คบน Github เราก็สามารถจะ clone มาลงเครื่องเราได้แล้ว :)
Fork
Fork เป็น feature ของทาง Github เอาไว้สำหรับ copy โปรเจ็คหรือว่า clone โปรเจ็คอื่นมาเป็นของเรา เพียงแต่ว่าการ clone จะเกิดขึ้นบน remote(server) เท่านั้น ข้อดีของการ Fork ก็คือ กรณีที่เราเจอโปรเจ็คที่น่าสนใจ แล้วเราอยากจะช่วยพัฒนา เราสามารถที่จะ Fork มาเป็นของเรา จากนั้น clone มาที่ local เมื่อแก้ไขโค๊ดเสร็จ ก็ทำการ Push โค๊ดขึ้นไป ทีนี้ก็จะทำการ Pull Request เพื่อ merge โค๊ด (Pull Request ดูหัวข้อถัดไป)
ซึ่งวิธีการ Fork นั่นทำได้ง่ายๆ เช่น ตัวอย่าง จะทำการ Fork Bootstrap ครับ
กดปุ่ม Fork ด้านมุมบนขวามือ
เมื่อทำการ Fork แล้ว ก็รอมัน Forking แปปนึง
จากนั้น Github จะทำการ copy โปรเจ็คมาอยู่ที่ account เรา (url จะเปลี่ยน แต่ก็จะบอกว่าเรา fork มาจากที่ใด)
หากเราลอง clone โปรเจ็คที่เรา fork มา ในกรณีที่เราอยากช่วยพัฒนา และตัวต้นฉบับมีการ commit เพิ่มตลอด เราจะทำยังไงที่จะให้รู้ว่าโค๊ดของเรานั้นเหมือนกับต้นฉบับแล้ว วิธีการก็คือ ทำการเพิ่ม remote ของต้นฉบับ จะเรียกว่า upstream
ดังนี้
git remote add upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git
ตัวอย่างผม Fork Bootstrap และทำการ add upstream ไปที่ original ตอนนี้เมื่อลอง git remote -v
จะได้ดังนี้
origin git@github.com:Phonbopit/bootstrap.git (fetch)
origin git@github.com:Phonbopit/bootstrap.git (push)
upstream git@github.com:Phonbopit/bootstrap.git (fetch)
upstream git@github.com:Phonbopit/bootstrap.git (push)
ถ้าอยากเช็คการอัพเดทจาก original ก็เพียงแค่พิมพ์
git fetch upstream
git checkout master
git merge upstream/master
ส่วนเวลาเราแก้ไขโค๊ดแล้ว Push ขึ้นไป ก็ไม่ต้องกลัวว่าจะไปกระทบกับโค๊ดต้นฉบับที่เรา Fork มานะครับ การ Push มันจะไปที่ repo ของเรา ไม่มีทางที่จะไปรวมกับ Original นอกจากเราจะ Pull Request และเจ้าของ repo นั้นกด accept
Pull Request
Pull Request เป็น feature ที่ช่วยให้นักพัฒนาคนอื่นๆ ที่ไม่ใช่เจ้าของ repo สามารถที่จะร่วมกันส่งโค๊ดเข้ามา merge รวมกับโค๊ดต้นฉบับได้ โดยการใช้งาน Pull Request ต้องทำการ Fork โปรเจ็คมาก่อน
ตัวอย่างการ Pull Request ในกรณีที่เราทำการแก้ไขโปรเจ็คที่ Fork แล้วทำการ commit และ push โค๊ดขึ้นมา จะเห็นปุ่ม Pull Request ขึ้นมาแสดงว่าเราจะต้องการ Pull Request หรือไม่ อย่างในตัวอย่างด้านล่าง ผมเพิ่ง push โค๊ดที่ branch new_style
ขึ้นมา
เมือกดเข้าไปจะเจอหน้า Pull Request เพื่อให้ใส่รายละอียด มีการเปรียบเทียบระหว่าง Original Repo และตัว Fork ของเรา รวมถึงเปรียบเทียบและให้เลือก branch ที่ต้องการ Pull Request ก็ได้
เพื่อ Pull Request ไปแล้ว ก็แค่รอให้ทางเจ้าของ Repository รออนุมัติว่าจะ merge โค๊ดของเราหรือไม่
ในกรณีที่ต้องการส่ง Pull Request(PR) เราควรจะแตก branch ออกมา จากนั้นถึงส่ง PR เป็น featureๆ แต่ละ branch ไป ไม่ควรทำใน master
Step 5 : Git GUI / Git Client
สำหรับบางคน อาจจะบ่นว่าใช้งาน Git ยุ่งยากเหลือเกิน ต้องพิมพ์ command line ตลอดเลยหรือเปล่า ? จริงๆแล้วก็มี Program GUI หลายๆตัวให้ใช้งานอยู่เหมือนกันนะครับ ในบทความนี้ก็จะยกตัวอย่างมาคร่าวๆ 2 ตัวครับ ก็คือ SourceTree และ Github Desktop
Source Tree
การใช้งาน Source Tree นั้นก็ง่ายเลยครับ
Setting Account สำหรับ BitBucket สมัครได้ที่นี่
เพื่อเอาไว้สร้าง repository แบบ private ฟรี คล้ายๆกับ Github เลย
หน้าตาการ clone url ก็จะประมาณนี้ ใส่ url ของ repository ที่เราต้องการจะ clone
หน้าตาเมื่อเปิดโปรแกรม SourceTree ขึ้นมา จะเห็นว่าผมทำการ clone repo ตัว git101
ก็จะเห็น history ต่างๆทั้งหมด ว่าแต่ละ commit ทำอะไรไปบ้าง ซึ่งจริงๆมันก็คือการเรียก git log
นั่นแหละ
เมนูด้านบนของ SourceTree ก็มีฟีตเจอร์ครบครันครับ ไม่ว่าจะเป็น commit
, checkout
, reset
, fetch
, pull
, push
เป็นต้น
และเมื่อเราลองแก้ไขไฟล์ อย่างเช่นผมเพิ่มเนื้อหาที่ไฟล์ about.html
แล้วกลับมาดูที่ SourceTree จะเห็นว่า มีไฟล์อะไรที่ถูกแก้ไขและแก้ไขบรรทัดไหนไป ได้ทันที โดยปกติถ้าเป็น Command Line ก็เช็คด้วย git diff HEAD
ทำการเลือกไฟล์จาก unstaged ไปที่ staged ไฟล์ จากนั้นกด Commit
เทียบเท่ากับ
git add about.html
git commit -m "Update content for about page"
สุดท้ายก็สั่ง git push
โดยกดที่ปุ่ม Push ด้านบน เป็นอันเรียบร้อย
นี่ก็เป็นการใช้ SourceTree เบื้องต้นเท่านั้น รายละเอียดปลีกย่อยอื่นๆ ก็ต้องไปศึกษา ไปลองเรียนรู้กันเอาเองนะครับ
Github Desktop
เมื่อติดตั้ง Github Desktop แล้ว สิ่งแรกที่ต้องทำคือทำการ Login ด้วยบัญชี Github ของเราครับ
จะเห็นว่าในส่วนแท็ป Advanced เราสามารถที่จะ config ชื่อและอีเมล์ได้ด้วย เหมือนกันกับทำ command line ด้วย
git config --global user.name "YOURNAME"
git config --global user.email "your@email.com"
ต่อมาทำการ clone repo จาก Github สำหรับ Github Desktop เราจะ clone ได้เฉพาะ repo ที่เราเป็นเจ้าของอยู่ครับ วิธีการจะ clone repo คนอื่น ก็ต้องเข้าหน้าเว็บไซต์ของ Github แล้วเลือก Clone in Desktop เอาครับ
เหมือนกับ SourceTree เลย เราสามารถที่จะดู History ต่างๆที่เกิดขึ้นกับโปรเจ็คของเราได้ ไม่ว่าจะเป็นไฟล์ไหนถูกแก้ไขบ้าง บรรทัดไหนบ้าง
เมื่อแก้ไขงานไฟล์ใดๆไป Github Desktop ก็จะมีบอกว่า uncommit มีอะไรบ้าง และต้องการ add และ commit ไฟล์ใดบ้าง
การ commit ก็ทำได้ง่ายๆ เพียงแค่เลือกมาแท็ป Uncommitted Changes แล้วก็เลือกไฟล์ที่จะ add จากนั้นใส่ commit message ที่ต้องการ
เมื่อ commit แล้วก็แค่กดปุ่ม Sync ขวามือ มันก็จะทำการ Push ให้เอง
สำหรับ Github Desktop ปุ่ม Sync จะทำการ
fetch
,pull
,push
ให้เราเอง
การใข้งาน Github Desktop เบื้องต้นก็มีเท่านี้ครับ อยากรู้รายละเอียดให้มากขึ้นก็ต้องไปหัดเล่นกันเอาเองละครับ
Step 6 : Workshop with Github
สำหรับส่วนสุดท้าย จะเป็น Workshop ให้ลองใช้งานครับ โดยผมจะทำการสร้าง repository ขึ้นมา 1 ตัว โดยผมทำการสร้างไว้ที่
หลังจากนั้นก็จะให้ผู้ที่เข้ามาอ่าน ได้ลองทำจากสิ่งต่างๆที่ได้เรียนรู้จากบทความนี้ครับ โดยมีเงื่อนไขดังนี้
- ให้ทำการ clone repository นี้ไปไว้ที่เครื่อง local ของตัวเอง (ต้องทำการ Fork โปรเจ็คของผม ไปเป็นของผู้อ่านเองก่อน)
- จากนั้นก่อนทำการแก้ไขไฟล์ใดๆ ให้แตก branch ออกมาก่อน ห้ามทำใน master เด็ดขาด
- การสร้างโฟลเดอร์ (จะเรียกว่า subfolder) จะมีเงื่อนไขโดยตั้งชื่อตาม username ของ Github
- ภายในโฟลเดอร์ของตัวเอง จะเป็นสิ่งที่แต่ละคนจะแก้ไขครับ สามารถใส่อะไรมาก็ได้ อยากแนะนำตัว ใส่โค๊ด snippets มาหรืออะไรก็ได้ แต่ขอแค่ ต้องมีไฟล์
README.md
มาด้วย - เมื่อแก้ไข้เรียบร้อยแล้ว ให้ทำการกด Pull Request เพื่อทำการส่ง Pull Request มาที่ตัว original repository ของผม
ใครทำไม่ตรงตามเงื่อนไขจะไม่ได้รับการกด Accept Pull Request (PR) นะครับ สำหรับตัวอย่าง Example โฟลเดอร์ของผม สามารถดูได้ที่นี่
Hint :
เป็นอันเรียบร้อย ง่ายมั้ยครับ? หากใครมีอะไรสงสัย สอบถามได้ที่นี่ หรือว่าที่ Issue on hello github ก็ได้ครับ
สรุป
หวังว่าบทความนี้จะเปิดมุมมองของคนที่ยังไม่ได้ใช้งาน Git หรือว่ายังช่างใจว่าจะใช้ดีหรือไม่ ให้มาสนใจและใช้งาน Git มากขึ้นนะครับ โดยบทความนี้พูดถึงการใช้งาน Git ผ่าน Command Line เพื่อให้เราได้รู้ที่มาที่ไป และใช้คำสั่งได้ถูงต้อง เมื่อไปใช้พวก GUI จะทำให้เราเข้าใจว่ามันทำงานยังไง ซึ่งทั้ง SourceTree และ Github Desktop ก็ใช้งานเบื้องต้นได้เหมือนๆกัน แต่ SourceTree จะมีฟังค์ชันที่ครอบคลุมดีกว่า ทีเหลือก็ให้ผู้อ่านไปลองดูกันเองครับว่าชอบแบบไหน จะ command line, GUI ก็แล้วแต่สะดวก ขอแค่ให้เข้าใจว่าจะทำอะไรกับมันเท่านั้นก็พอ
หากส่วนไหนผิดพลาด หรือมีข้อเสนอแนะ แนะนำติชมมาได้เลยครับ ขอบคุณครับ
Additional Resoures
- Authors
- Name
- Chai Phonbopit
- Website
- @Phonbopit