Skip to content

Instantly share code, notes, and snippets.

@iporsut
Last active September 13, 2024 07:44
Show Gist options
  • Save iporsut/28844f1ae6fb49b40bab2e84f170176d to your computer and use it in GitHub Desktop.
Save iporsut/28844f1ae6fb49b40bab2e84f170176d to your computer and use it in GitHub Desktop.
อบรมการใช้งาน Git และ Docker เบื้องต้น

Git คืออะไร

Git คือ โปรแกรมระบบจัดการโค้ดโปรแกรม (Source Code Management System - SCM) ซึ่งระบบ SCM ส่วนใหญ่แล้วมีหน้าทีคือ

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

ข้อดีของ Git ที่ต่างจากโปรแกรมอื่น

  • Git ทำงานแบบ distributed คือเก็บข้อมูลการเปลี่ยนแปลงไว้ที่เครื่องของผู้ใช้งาน ไม่จำเป็นต้องมี server กลาง
  • สามารถสร้าง Git Repository server ได้เพื่อให้เป็นตัวกลางในการ sync แต่ข้อมูลบน Repositry คือ copy อีกหนึ่งชุดนั่นเอง
  • ทุกวันนี้ source code ของโครงการใหญ่ๆ และบริษัทใหญ่ๆ ใช้ git เป็นจำนวนมาก และ ใช้บริการของ github ทำให้เราสามารถเข้าไปร่วมพัฒนา หรือ clone ลงมาใช้งานได้ง่ายถ้าเรามีความรู้เรื่อง Git

การใช้งาน Git เบื้องต้น

สร้าง Repository ใหม่ด้วย git init

ตัวอย่างในการฝึก git วันนี้ เราจะทำ Web Applications ที่ชื่อว่า TodoApp กันนะครับ โดยที่เป็น App จัดการลิสต์งานนั่นเอง เราจะเขียนด้วย HTML/CSS/Javascript กัน ไม่ได้ใช้ส่วน server นะครับ เพื่อให้ง่ายต่อการทำความเข้าใจ เพราะเราเอามาใช้เป็นโจทย์ฝึกใช้ Git กันนะครับ

เริ่มแรกให้เราสร้าง folder สำหรับ project ใหม่ของเราก่อนนะครับ ตั้งชื่อว่า todoapp

mkdir todoapp

หลังจากนั้นเราจะสร้าง git repository เพื่อให้ git track และ จัดเก็บ การเปลี่ยนแปลงของ source code ของ todoapp ของเรานะครับ โดยหลังจากเราสร้าง folder แล้วให้เราเข้าไปที่ folder todoapp แล้วสั่ง git init

cd todoapp
git init

เช็คสถานะด้วย git status

หลังจากนั้นให้เราลองสั่ง git status ดูครับ เราจะเห็น git บอกเราแบบนี้

On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

ที่เป็นแบบนี้เพราะเราเพิ่งสร้าง git repository และ folder todoapp ของเราเองก็ยังไม่ได้สร้างไฟล์อะไร ให้เราสร้างไฟล์ index.html แล้วลองเพิ่มโค้ดเข้าไปดังนี้ครับ

<!doctype html>
<html>
  <head>
    <title>Todo</title>
  </head>
  <body>
    Hello World
  </body>
</html>

หลังจากนั้นให้เราลองสั่ง git status อีกครั้งเราจะเห็นแบบนี้

On branch master

No commits yet

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 status บอกเราว่าไฟล์ index.html ของเรานั้นเป็น Untracked files ความหมายของ Untracked files ก็คือไฟล์ที่ยังไม่เคยจัดเก็บเข้าสู่ฐานข้อมูลของ git นั่นเองครับ คือไฟล์ที่เราสร้างใหม่ ยังไม่เคยได้ commit มันเก็บไว้มาก่อนเลย

เพิ่มโค้ดเข้าสู่ staging ด้วย git add

การสร้างการบันทึกการเปลี่ยนแปลงของ git หรือการสร้าง commit ใหม่ของ git นั้น เราต้องจัดการเพิ่มไฟล์ที่ต้องการ commit เข้าสู่ส่วนสถานะ staging ก่อน โดยใช้ git add ไฟล์ที่ถูก add เข้าไปสู่ staging จะเป็นเซตของไฟล์ที่พร้อมจะ commit ที่แยกแบบนี้เพราะ git จะใช้ให้เราเลือกได้ ว่าเราจะจัดกลุ่มไฟล์ในการ commit ยังไง สมมติเราแก้ไป 10 ไฟล์ แต่ว่าทั้ง 10 ไฟล์นี้อาจแบ่งเป็นสองเรื่องที่ไม่เกี่ยวข้องกัน โดย 5 ไฟล์ทำเรื่อง insert อีก 5 ไฟล์ทำเรื่อง update เราก็จะค่อยๆ git add เข้าไปเป็นกลุ่มทีละ 5 แล้ว commit 1 ครั้ง เสร็จแล้ว git add อีก 5 ค่อย commit อีกครั้งนั่นเอง

โอเคเรามาจัดการ commit โค้ด index.html ของเรากันโดยสั่งดังนี้ครับ

git add index.html

หลังจากนั้นลอง git status ดูจะได้

On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   index.html

git status บอกเราว่าไฟล์ index.html ของเรานั้นเป็นไฟล์ที่พร้อมจะถูก commit แล้ว และในวงเล็บนั้นยังไกด์เราอีกต่างหากว่าถ้าเราอยากเอาไฟล์ index.html ออกจากส่วน staging ไปเป็น unstage ต้องทำยังไง

ดูความต่างจากโค้ดเดิมก่อน commit ด้วย git diff --staged

เราสามารถเช็คการเปลี่ยนแปลงทั้งหมด ที่เกิดกับไฟล์ที่อยู่ใน staging ได้โดยใช้คำสั่ง git diff พร้อมกับ option --staged ดังนี้ครับ

git diff --staged

git diff จะแสดงผลลัพธ์ดังนี้

diff --git a/index.html b/index.html
new file mode 100644
index 0000000..76be9b8
--- /dev/null
+++ b/index.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Todo</title>
+  </head>
+  <body>
+    Hello World
+  </body>
+</html>

เนื่องจากไฟล์เรายังไม่เคย commit มาก่อน ดังนั้นจะเห็นว่า git diff จะแสดงเป็น + ข้างหน้าทั้งหมดคือ เป็น code ที่ถูกเพิ่มเข้าไปใหม่ทั้งหมดเลยนั่นเอง

commit โค้ดที่อยู่ใน staging

ต่อไปเราจะทำการ commit โค้ดจริงๆละ โค้ดที่จะถูก commit คือโค้ดที่อยู่ใน staging อยู่แล้วคือ index.html นั่นเอง ให้เราสั่งดังนี้ครับ

git commit -m "Add index.html file"

โดยที่ option -m เป็นการระบุข้อความสำหรับ commit ครับ (commit messages) ซึ่งถือว่าเป็นการอธิบายคร่าวๆว่า เราเปลี่ยนแปลงอะไรไปบ้างกับโค้ดที่เรา commit

จะเห็น git commit แสดงผลแบบนี้ออกมา

[master (root-commit) 68191ae] Add index.html file
 1 file changed, 9 insertions(+)
 create mode 100644 index.html

นั่นคือได้สร้าง commit ใหม่ให้เราแล้ว ส่วน 68191ae คือ commit hash ครับซึ่ง git จะสร้างเพื่อเป็น uniq id ของ commit ให้อ้างอิงแต่ละ commit นั่นเองครับ

หลังจากนั้นให้เราลอง git status ดูจะเห็นว่าได้สถานะแบบนี้แล้วหลังจาก commit

On branch master
nothing to commit, working tree clean

แก้ไขไฟล์ที่เคยอยู่ใน Repository อยู่แล้ว

หลังจากได้ 1 commit แล้ว เราก็แก้ไขโค้ดของเราต่อ แก้ไข index.html ให้เป็นแบบนี้ครับ

<!doctype html>
<html>
  <head>
    <title>Todo</title>
  </head>
  <body>
    <header><h1>TODO</h1></header>
  </body>
</html>

ทุกครั้งเวลาเราแก้ไขไฟล์ สิ่งที่เรามักจะทำบ่อยๆคือเช็คสถานะของ repository เราด้วย git status ครับ ว่าเกิดการเปลี่ยนแปลงอะไรไปบ้างแล้ว ดังนั้นสั่ง git status ดูตอนนี้จะเห็น

On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html

no changes added to commit (use "git add" and/or "git commit -a")

จะเห็นสถานะของไฟล์ index.html ของเราตอนนี้คือ modified ซึ่งต่างจากตอนแรกที่เรายังไม่ได้เคย commit ไฟล์นี้จะขึ้นเป็น Untracked file และนอกจากนั้น git status ยังไกด์ให้เราอีกว่า เราสามารถเพิ่มไฟล์นี้เข้า staging เพื่อทำให้พร้อมจะ commit ได้นะ และยังบอกว่าเราใช้ git checkout -- เพื่อยกเลิกการเปลี่ยนแปลงที่เกิดขึ้นกับไฟล์ของเรา ซึ่งเดียวผมอธิบายอีกทีสำหรับคำสั่งนี้นะครับ

ความต่างต่อไปของไฟล์ในสถานะ modified กับ untracked file คือเราใช้ git diff เช็คการเปลี่ยนแปลงได้ครับ โดยที่ยังไม่ต้อง git add ให้เราลองสั่ง git diff ตอนนี้ดูครับจะได้ผลลัพธ์ออกมาแบบนี้

diff --git a/index.html b/index.html
index 76be9b8..b795be2 100644
--- a/index.html
+++ b/index.html
@@ -4,6 +4,6 @@
     <title>Todo</title>
   </head>
   <body>
-    Hello World
+    <header><h1>TODO</h1></header>
   </body>
 </html>

จะเห็นว่าส่วนที่มี - ข้างหน้าคือส่งที่เราลบออกไป และส่วนที่มี + ข้างหน้าคือส่วนที่เราเพิ่มเข้าไปนั่นเองครับ

หลังจากนี้ให้เราจัดการบันทึกการเขียนแปลงที่เราเพิ่งสร้างไปกับ index.html ให้เป็น commit ใหม่ก่อน โดยเริ่มจาก git add ก่อนครับ

git add index.html

ลอง git status ดูจะได้

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   index.html

นั่นคือ index.html ได้ย้ายไปอยู่ใน staging พร้อม commit เรียบร้อย และ git status ได้แนะนำวิธีการเอา index.html ออกไปจาก staging อีกแบบ เดี๋ยวมาอธิบายกันอีกทีครับว่ามันทำได้ยังไง

จัดการ commit ดังนี้

git commit -m "Add Todo header"

แล้ว git status ดูอีกครั้งก็จะเห็นว่า repository เรากลับมาสู่สถานะ

On branch master
nothing to commit, working tree clean

อีกครั้ง

การลบไฟล์ออกจาก Repository

ก่อนที่เราจะดูวิธีการลบไฟล์ออกจาก repository ให้เราเพิ่มไฟล์ใหม่เข้าไปอีกไฟล์ดูก่อนครับชื่อไฟล์ index.js แล้ว git add , git commit แบบที่เราให้เรียนรู้ไปแล้วดูครับ โดย index.js มีโค้ดแบบนี้

alert('Fail');
git add index.js

git commit -m "Add javascript"

หลังจากนั้นให้เราลบไฟล์ index.js ทิ้งได้เลยครับ แล้วเมื่อเรา 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.js

no changes added to commit (use "git add" and/or "git commit -a")

index.js อยู่ในสถานะ deleted ครับ จะเห็นว่าสิ่งที่เราเคย commit ไว้แล้ว git รู้การเปลี่ยนแปลงของมัน ไม่ว่าจะเป็นแก้ไขบางส่วน หรือแม้แต่ลบมันทั้งไฟล์ออกไปแบบนี้

ต่อไปเราต้องการ commit การเปลี่ยนแปลงนี้เอาไว้ ให้เราใช้ git add index.js แล้ว git commit ได้เหมือนตอนเพิ่มเลยครับดังนี้

git add index.js

เมื่อ git status หลังจาก git add ไปแล้วจะได้แบบนี้

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	deleted:    index.js

คือเราจัดการบันทึกการเปลี่ยนแปลงกับ index.js เข้า staging เรียบร้อย โดยสถานะใน staging ของ index.js คือการถูกลบออกไปนั่นเอง ต่อไปทำการ commit

git commit -m "Remove index.js"

ดูรายการ commit ด้วย git log

เราได้ commit กันไป 4 commit แล้วต่อไปเราจะมาดูอีกคำสั่ง ที่ช่วยให้เราเห็นว่า เราเคย commit อะไรกันไปบ้าง นั่นคือ git log ลองสั่ง git log ดูตอนนี้จะได้แบบนี้

commit 772f7ca0903c0a8e13fdfe7e66e9734b255bfc97 (HEAD -> master)
Author: Weerasak Chongnguluam <[email protected]>
Date:   Wed Dec 20 01:08:02 2017 +0700

    Remove index.js

commit f3918be770c8630e2117b194a12bedd8e5fb7417
Author: Weerasak Chongnguluam <[email protected]>
Date:   Wed Dec 20 00:55:14 2017 +0700

    Add javascript

commit 588f955c902dcd5114531b0e98db46d63e3edc5c
Author: Weerasak Chongnguluam <[email protected]>
Date:   Wed Dec 20 00:54:34 2017 +0700

    Add Todo header

commit 03c0aa4f20132a69bd1bb31f1616a89584aefc5f
Author: Weerasak Chongnguluam <[email protected]>
Date:   Wed Dec 20 00:23:48 2017 +0700

    Add index.html file

ในแต่ละ commit git log แสดงข้อมูลว่า commit hash id คืออะไร , Author คนที่ทำการแก้ไขคือใคร, Date วันที่ทำการ commit คือวันไหน เวลาไหน และ ข้อความที่เราใส่ตอน commit

ซึ่งจริงๆแล้ว git log จะมี option ให้เราเล่นเยอะกว่านี้ในการแสดงข้อมูลของ commit เดี๋ยวเราได้ลองให้กันในส่วนต่อๆไป

ตั้งค่า user.name และ user.email

จาก git log จะเห็นส่วนของ Author จะมีชื่อ และ อีเมล์ เราสามารถตั้งค่าได้ผ่านทางคำสั่ง git config โดยเราจะใส่ option --local เพื่อให้มีผลกับ repository นี้เท่านั้น ให้เราสั่งดังนี้ครับ

git config --local user.name "USER_NAME"

git config --local user.email "[email protected]"

สร้างไฟล์ .gitignore เพื่อกรองสิ่งที่ไม่ต้องการให้อยู่ใน Repository

ในบางครั้ง เวลาเราแก้ไขไฟล์เราด้วย IDE อย่างเช่น PhpStorm จะมี file หรือ folder ที่เป็น configuration ของ IDE อยู่ใน folder ของ git repository เรา แต่เราไม่อยากให้ git มาจัดการไฟล์พวกนี้ เพราะมันเป็นการตั้งค่าที่เราใช้กับ IDE บนเครื่องเรา ต่อให้เพื่อนร่วมงานเราใช้ IDE ตัวเดียวกัน ก็อาจจะตั้งค่าต่างกันได้

git จะมีวิธีการที่จะบอกให้มันรู้ว่าไฟล์แบบนี้ที่ไม่ต้องสนใจ (ignore) ไม่ต้องเทรคการเปลี่ยนแปลง โดยใช้ไฟล์ที่ชื่อว่า .gitignore

ให้เราสร้าง .gitignore ใน folder ของ repository ของเรา แล้วของพิมพ์ลงไปแบบนี้

# Windows thumbnail db
Thumbs.db

# OSX files
.DS_Store

สองไฟล์นี้มักจะถูกสร้างโดย OS ซึ่งเราไม่ต้องการให้มันติดไปกับ git repository ของเราด้วยก็เลยเพิ่มเข้าไป

ในแต่ละบรรทัดในไฟล์ .gitignore คือ pattern ของไฟล์ หรือ folder ที่จะถูก ignore เราสามารถใช้ wildguard characters คือ * หรือ ? ช่วยเขียน pattern ได้เช่น

/*/out
/*/*/build
/*/*/production
*.iws
*.ipr
*~
*.swp

# Android Studio
*.iml
.idea
#.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
.gradle
build/
.navigation
captures/
output.json

หลังจากเราสร้างไฟล์ .gitignore แล้วเราต้อง commit .gitignore เข้าไปด้วย ดังนี้

git add .gitignore

git commit -m "Add gitignore pattern"

ยกเลิกไฟล์ที่ถูกแก้ไข แต่ยังไม่ได้ add ด้วย git checkout --

ในสถาณการณ์ที่เรากำลังทดลองหาวิธีการแก้ปัญหาบางอย่างอยู่ เราอาจจะแก้โค้ดไปหลายๆไฟล์ แล้วตัดสินใจไม่เอาละ เราอาจจะให้กัน Undo ของ Editor แต่ Undo ของ Editor จะจำไว้แค่ตอนเปิดโปรแกรมอยู่ ถ้าเผลอปิด หรือโปรแกรม crash ไปก่อนจนปิดตัวเอง แล้วเราไม่ได้ใช้ version control อย่าง git ก็จะทำให้เราย้อนกลับไปจุดเดิมก่อนแก้ไขได้ยากมากๆ

สำหรับ git ถ้าของที่เคย commit ไว้แล้วทำการแก้ไข มันจะรู้ว่าไฟล์ไหนแก้อะไรไปแล้วบ้าง เราทดลองแก้ index.html ต่อดังนี้

<!doctype html>
<html>
  <head>
    <title>Todo</title>
  </head>
  <body>
    <header><h1>TODO</h1></header>
    <ul>
      <li><input name="newTask"> <input type="submit" value="Add"></li>
    </ul>
  </body>
</html>

หลังจากนั้นสั่ง git status ดูจะได้ดังนี้

On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html

no changes added to commit (use "git add" and/or "git commit -a")

สถานะของ index.html กลับเป็น unstaging modified เมื่อเราต้องการยกเลิกการเปลี่ยนแปลงของไฟล์ที่ยังไม่ได้เพิ่มไปใน staging ให้เราใช้ git checkout -- <file> ดังนี้

git checkout -- index.html

git status ดูอีกครั้งจะได้

On branch master
nothing to commit, working tree clean

ยกเลิกไฟล์ที่ add แล้วกลับมาสถานะกำลังแก้ไขด้วย git reset HEAD

ในกรณีที่เราได้ add file เข้าไปใน staging แล้วอยากเอาออกมาเป็น unstaging อีกครั้ง โดยที่การเปลี่ยนแปลงที่เราทำไปกับไฟล์นั้นยังคงอยู่ไม่ได้หายไปไหนสามารถทำได้โดยใช้ git reset HEAD <file>

ให้เราลองแก้ไข index.html อีกครั้ง

<!doctype html>
<html>
  <head>
    <title>Todo</title>
  </head>
  <body>
    <header><h1>TODO</h1></header>
    <ul>
      <li><input name="newTask"> <input type="submit" value="Add"></li>
    </ul>
  </body>
</html>

ลอง git status ได้

On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html

no changes added to commit (use "git add" and/or "git commit -a")

หลังจากนั้น add index.html เข้า staging

git add index.html

แล้ว git status ดูจะได้

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   index.html

จะเห็นว่า git ก็แนะนำให้เราแล้วเช่นกัน ลองใช้ git reset HEAD <file> ดังนี้

git reset HEAD index.html

แล้ว git status อีกครั้งจะได้

On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html

no changes added to commit (use "git add" and/or "git commit -a")

นั่นคือ index.html กลับมาสถานะ modefied แบบ unstaging เหมือนเดิม

ลบไฟล์ที่ยังไม่ได้ถูก track ทั้งหมดด้วย git clean -f

ในกรณีที่เป็นไฟล์ที่อยู่ในสถาณะ untracked file คือสร้างใหม่ยังไม่เคย add หรือ commit และเราอยากลบให้หมด ถ้ามีหลายไฟล์และอยู่คนละ folder แล้วต้องไล่ลบทีละไฟล์คงจะเป็นเรื่องที่ลำบาก แต่สำหรับ git เราสามารถลบไฟล์ที่เป็น untracked file ออกได้หมดทีเดียวด้วย git clean -f เช่น ให้เราสร้างไฟล์ index.js อีกครั้งแล้วเพิ่มโค้ดไปแบบนี้

alert('Fail')

แล้วสั่ง git status ได้

On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

	index.js

nothing added to commit but untracked files present (use "git add" to track)

แล้วลองลบด้วยวิธี git clean -f ดังนี้

git clean -f

Removing index.js

ถอยกับไป commit ก่อนหน้าด้วย git reset

แน่นอนว่าการใช้ version control อย่าง git ไม่ใช่เพื่อให้เรา commit แล้ว git log ดูได้เท่านั้น แต่สามารถให้เราย้อนกลับไปในกรณีที่ commit ล่าสุดมีบั๊กเกิดขึ้น อยากย้อนกลับไปจุดก่อนที่ยังไม่มีบั๊ก

ให้เราลอง git log ล่าสุดได้แบบนี้

commit 772f7ca0903c0a8e13fdfe7e66e9734b255bfc97 (HEAD -> master)
Author: Weerasak Chongnguluam <[email protected]>
Date:   Wed Dec 20 01:08:02 2017 +0700

    Remove index.js

commit f3918be770c8630e2117b194a12bedd8e5fb7417
Author: Weerasak Chongnguluam <[email protected]>
Date:   Wed Dec 20 00:55:14 2017 +0700

    Add javascript

commit 588f955c902dcd5114531b0e98db46d63e3edc5c
Author: Weerasak Chongnguluam <[email protected]>
Date:   Wed Dec 20 00:54:34 2017 +0700

    Add Todo header

commit 03c0aa4f20132a69bd1bb31f1616a89584aefc5f
Author: Weerasak Chongnguluam <[email protected]>
Date:   Wed Dec 20 00:23:48 2017 +0700

    Add index.html file

เราจะ reset กลับไปที่ f3918be770c8630e2117b194a12bedd8e5fb7417 ให้เราสั่งดังนี้

git reset f3918be770c8630e2117b194a12bedd8e5fb7417

Unstaged changes after reset:
D	index.js

ลองสั่ง git log อีกทีจะได้

commit f3918be770c8630e2117b194a12bedd8e5fb7417 (HEAD -> master)
Author: Weerasak Chongnguluam <[email protected]>
Date:   Wed Dec 20 00:55:14 2017 +0700

    Add javascript

commit 588f955c902dcd5114531b0e98db46d63e3edc5c
Author: Weerasak Chongnguluam <[email protected]>
Date:   Wed Dec 20 00:54:34 2017 +0700

    Add Todo header

commit 03c0aa4f20132a69bd1bb31f1616a89584aefc5f
Author: Weerasak Chongnguluam <[email protected]>
Date:   Wed Dec 20 00:23:48 2017 +0700

    Add index.html file

จะเห็นว่า git ถอยกลับมาที่ f3918be770c8630e2117b194a12bedd8e5fb7417 เป็น commit บนสุด และเมื่อเราสั่ง git status จะได้

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.js

no changes added to commit (use "git add" and/or "git commit -a")

ไฟล์ index.js กลับมาอยู่ในสถานะ unstaged เราสามารถเอาไฟล์กับมาจากการ delete ได้โดยใช้ git checkout -- index.js แบบที่เราได้ลองไปแล้วนั่นเอง

นอกจากนั้น git reset ยังมี option --soft และ --hard โดยที่ --soft จะทำให้ไฟล์ที่เคย commit กลับมาอยู่ในสถานะ staged ส่วน --hard จะทำให้ไฟล์ กลับไปเป็นก่อนที่จะถูกแก้ไขเลย

recover commit เมื่อเผลอ git reset ผิด

ถ้าเราใช้ git reset ผิด สำหรับ git แล้ว commit ที่เราเคยทำไว้ไม่ได้หายไปไหน เพราะ git reset คือการย้ายแค่สถานะของ commit บนสุดของ working directory ของ branch ที่เราทำงานอยู่ ไม่ได้ลบ commit ที่เคยทำไว้ เราสามารถเดินหน้ากลับไป commit เดิมได้ แต่ว่าเราต้องรู้ commit hash id เราสามารถลิสต์ได้โดยใช้ คำสั่ง git reflog เมื่อเราสั่งจะได้ออกมาประมาณนี้

git reflog

f3918be (HEAD -> master) HEAD@{0}: reset: moving to f3918be770c8630e2117b194a12bedd8e5fb7417
772f7ca HEAD@{1}: reset: moving to 772f7ca0903c0a8e13fdfe7e66e9734b255bfc97
f3918be (HEAD -> master) HEAD@{2}: reset: moving to f3918be770c8630e2117b194a12bedd8e5fb7417
772f7ca HEAD@{3}: reset: moving to 772f7ca0903c0a8e13fdfe7e66e9734b255bfc97
f3918be (HEAD -> master) HEAD@{4}: reset: moving to f3918be770c8630e2117b194a12bedd8e5fb7417
772f7ca HEAD@{5}: reset: moving to 772f7ca0903c0a8e13fdfe7e66e9734b255bfc97
588f955 HEAD@{6}: reset: moving to 588f955c902dcd5114531b0e98db46d63e3edc5c
f3918be (HEAD -> master) HEAD@{7}: reset: moving to f3918be770c8630e2117b194a12bedd8e5fb7417
772f7ca HEAD@{8}: reset: moving to 772f7ca0903c0a8e13fdfe7e66e9734b255bfc97
588f955 HEAD@{9}: reset: moving to 588f955c902dcd5114531b0e98db46d63e3edc5c
772f7ca HEAD@{10}: reset: moving to 772f7ca0903c0a8e13fdfe7e66e9734b255bfc97
588f955 HEAD@{11}: reset: moving to 588f955c902dcd5114531b0e98db46d63e3edc5c
772f7ca HEAD@{12}: reset: moving to 772f7ca0903c0a8e13fdfe7e66e9734b255bfc97
f3918be (HEAD -> master) HEAD@{13}: reset: moving to f3918be770c8630e2117b194a12bedd8e5fb7417
772f7ca HEAD@{14}: reset: moving to 772f7ca0903c0a8e13fdfe7e66e9734b255bfc97
588f955 HEAD@{15}: reset: moving to 588f955c902dcd5114531b0e98db46d63e3edc5c
772f7ca HEAD@{16}: reset: moving to 772f7ca0903c0a8e13fdfe7e66e9734b255bfc97
588f955 HEAD@{17}: reset: moving to HEAD
588f955 HEAD@{18}: reset: moving to 588f955c902dcd5114531b0e98db46d63e3edc5c
772f7ca HEAD@{19}: filter-branch: rewrite
cb310d8 (refs/original/refs/heads/master) HEAD@{20}: commit: Remove index.js
8b734af HEAD@{21}: commit: Add javascript
eacdfbd HEAD@{22}: commit: Add Todo header
68191ae HEAD@{23}: commit (initial): Add index.html file

จะเห็นว่าเป็น log การเปลี่ยนแปลงของ HEAD ซึ่งเป็นชื่อแทน commit บนสุด และเห็น hash id ของ commit ในกรณีนี้ผมย้ายไป f3918be ซึ่ง commit ที่ HEAD อ้างอิงก่อนหน้าคือ 772f7ca ผมสามารถกลับไปทีเดิมได้โดยใช้

git reset --hard 772f7ca

Git Branch คืออะไร

ระบบ branch ช่วยให้เราแยกการเปลี่ยนแปลงแก้ไขโค้ดออกเป็นกลุ่ม ในเรื่องที่เกี่ยวข้องกันได้ แล้วเมื่อการแก้ไขภายใน branch นั้นได้รับการทดสอบจนแน่ใจแล้ว จึงค่อยเรามารวมกับ branch หลักแล้วจัดการ deploy ขึ้น production ได้

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

สร้าง branch ใหม่ด้วย git checkout -b branch_name

เราสามารถสร้าง branch ใหม่ด้วยคำสั่ง git checkout -b branch_name หรือใช้ git branch branch_name ก็ได้ ความต่างคือถ้าใช้ git checkout -b branch_name git จะสร้างและย้าย HEAD ไปที branch ใหม่ให้เลย แต่ git branch branch_name จะยังอยู่ branch เดิม เราสามารถย้ายเองได้โดยใช้ git checkout branch_name

ต่อไปเราจะเริ่มพัฒนาความสามารถใหม่ให้กับ Todo App ของเราโดยจะทำส่วนของ layout เบื้องต้น โดยให้เราแยก branch ใหม่จาก master branch ซึ่งเป็น default branch ตอนที่เราสร้าง repository ดังนี้

git checkout -b basic_layout

เมื่อเรา git status ดูจะได้

On branch basic_layout
nothing to commit, working tree clean

ตรง On branch เปลี่ยนเป็น On branch basic_layout แล้ว

ให้เราแก้ไขไฟล์ index.html เพื่อเพิ่มโค้ดจัดการ layout เบื้องต้นดังนี้

<!doctype html>
<html>
  <head>
    <title>Todo</title>
    <style>
     .container {
	 position: relative;
     }
     .container .col {
	 float:left;
	 position:relative;
	 padding: 0 20px;
     }
     .clear {
	 clear:both;
     }
     .col .list {
	 padding-left:1em;
     }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="col">
	<header><h1>TODO</h1></header>
	<ul class="list">
	  <li>สอน Git</li>
	  <li>กินกอกก</li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DOING</h1></header>
	<ul class="list">
	  <li>สอน Git</li>
	  <li>กินกอกก</li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DONE</h1></header>
	<ul class="list">
	  <li>สอน Git</li>
	  <li>กินกอกก</li>
	</ul>
      </div>
      <div class="clear"></div>
    </div>
  </body>
</html>

ทำการ add และ commit code ดังนี้

git add index.html

git commit -m "First draft layout"

การรวมโค้ดจาก branch อื่นด้วย git merge

หลังจากที่เราทำงานใน branch basic_layout จนพอใจแล้ว ถ้าต้องการเอาโค้ดจาก branch basic_layout กลับมารวมกับ branch master ให้เรากลับไปที่ branch master ก่อนแล้วค่อย merge โดยทำดังนี้

git checkout master

git merge basic_layout

git จะแสดงผลลัพธ์ดังนี้

Updating 590fb2d..b2a0519
Fast-forward
 index.html | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

เราสามารถที่จะลบ branch ที่ไม่ได้ใช้แล้วด้วย

git branch -D basic_layout

เราสามารถ ลิสต์ รายชื่อ branch ได้โดยสั่ง git branch เฉยๆ

การแยกหลาย branch จากจุดเดียวกัน ทำคนละฟีเจอร์ แล้วเอากลับมารวมกัน

ต่อไปเป็นสถานการณ์ที่ เราแยกจาก master เป็น branch add_item และ delete_item เสร็จแล้วเราจะ merge สอง branch นี้กลับมารวมที่ master ให้เราสร้าง branch ทั้งสองใหม่ดังนี้ครับ

git checkout master

git branch add_item

git branch delete_item

หลังจากนั้นให้เราเข้าไปที่ branch add_item แล้วแก้ไข index.html ดังนี้

<!doctype html>
<html>
  <head>
    <title>Todo</title>
    <style>
     .container {
	 position: relative;
     }
     .container .col {
	 float:left;
	 position:relative;
	 padding: 0 20px;
     }
     .clear {
	 clear:both;
     }
     .col .list {
	 padding-left:1em;
     }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="col">
	<header><h1>TODO</h1></header>
	<input name="new_item" /> <button id="new_item_btn">Add</button>
	<ul class="list">
	  <li>สอน Git</li>
	  <li>กินกอกก</li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DOING</h1></header>
	<ul class="list">
	  <li>สอน Git</li>
	  <li>กินกอกก</li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DONE</h1></header>
	<ul class="list">
	  <li>สอน Git</li>
	  <li>กินกอกก</li>
	</ul>
      </div>
      <div class="clear"></div>
    </div>
  </body>
</html>

จัดการ add และ commit ให้เรียบร้อยดังนี้

git add index.html
git commit -m "Add add item input and button"

สลับไปที่ branch delete_item จะพบว่าโค้ดที่ index.html กลับไปเปิดหน้าตาแบบเดิมเหมือนใน master ที่เราได้แยกออกมาจาก delete_item ส่วนโค้ดที่อยู่ใน add_item ที่เราเพิ่งเพิ่มเข้าไปก็จะหายไป

ให้เราแก้ไขโค้ดใน index.html เป็นดังนี้

<!doctype html>
<html>
  <head>
    <title>Todo</title>
    <style>
     .container {
	 position: relative;
     }
     .container .col {
	 float:left;
	 position:relative;
	 padding: 0 20px;
     }
     .clear {
	 clear:both;
     }
     .col .list {
	 padding-left:1em;
     }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="col">
	<header><h1>TODO</h1></header>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DOING</h1></header>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DONE</h1></header>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="clear"></div>
    </div>
  </body>
</html>

จัดการ add และ commit ให้เรียบร้อยดังนี้

git add index.html
git commit -m "Add deletebutton"

หลังจากนั้นให้เรากลับไปที่ master แล้วลอง merge ด้วย add_item แล้วตามด้วย delete_item

git checkout master

git merge add_item

git merge delete_item

จะเห็นว่า git จะสร้าง commit ใหม่สำหรับการ merge delete_item แต่ตอน merge add_item ไม่มี เพราะ สอง branch นี้แตกออกไปจาก master ดังนั้นตอนที่ merge add_item จึงสามารถเอา commit มาต่อกันได้เลย แต่หลังจาก merge add_item ไปแล้ว git จะต้องพยายามเอาโค้ดที่เกิดจาก delete_item มาผสมไปกับสิ่งที่เปลี่ยนไปแล้วจาก add_item เอามาต่อตรงๆไม่ได้ ทำให้เกิดมี merge commit เกิดขึ้น ซึ่งถ้าไม่มีการ conflict กันก็จะ merge ได้สำเร็จเป็นปกติ

การแก้ไข conflict เมื่อ merge code

การที่เกิด conflict นั่นคือกรณีที่มีการแก้ไขโค้ดที่จุดเดียวกัน แต่คนละ branch จนทำให้ git merge ไม่สามารถที่จะจัดการรวมให้เราได้เอง เพราะไม่สามารถตัดสินใจได้ว่าจะเลือกการเปลี่ยนแปลงจาก branch ไหนกันแน่

ทดลองทำให้เกิด conflict โดยแยกอีก 2 branch คือ add_placeholder และ add_class

git checkout master
git branch add_placeholder
git branch add_class

เสร็จแล้ว git checkout add_placehodler แล้วแก้โค้ดใน index.html เป็นดังนี้

<!doctype html>
<html>
  <head>
    <title>Todo</title>
    <style>
     .container {
	 position: relative;
     }
     .container .col {
	 float:left;
	 position:relative;
	 padding: 0 20px;
     }
     .clear {
	 clear:both;
     }
     .col .list {
	 padding-left:1em;
     }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="col">
	<header><h1>TODO</h1></header>
	<input placeholder="What you will do?" name="new_item" /> <button id="new_item_btn">Add</button>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DOING</h1></header>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DONE</h1></header>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="clear"></div>
    </div>
  </body>
</html>

แล้วจัดการ add และ commit ดังนี้

git add index.html
git commit -m "Add new TODO placeholder text"

หลังจากนั้นย้ายไปที่ branch add_class แล้วแก้โค้ด index.html เป็นดังนี้

<!doctype html>
<html>
  <head>
    <title>Todo</title>
    <style>
     .container {
	 position: relative;
     }
     .container .col {
	 float:left;
	 position:relative;
	 padding: 0 20px;
     }
     .clear {
	 clear:both;
     }
     .col .list {
	 padding-left:1em;
     }
     .field {
         color: #666666;
     }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="col">
	<header><h1>TODO</h1></header>
	<input class="field" name="new_item" /> <button id="new_item_btn">Add</button>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DOING</h1></header>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DONE</h1></header>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="clear"></div>
    </div>
  </body>
</html>

แล้วจัดการ add และ commit

git add index.html
git commit -m "Add field css class"

หลังจากนั้นให้ไปที่ branch master แล้ว merge ทั้งสอง branch ที่ละ branch เข้า master ดังนี้

git checkout master
git merge add_placehodler
git merge add_class

git จะฟ้องออกมาแบบนี้

$ git merge add_class
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

นั่นคือเกิดกการ conflict ขึ้นระหว่างการ merge เมื่อเราเปิดไฟล์ index.html แล้วโค้ดเราจะโดนแทรกบางอย่างเข้าไป กลายเป็นแบบนี้

<!doctype html>
<html>
  <head>
    <title>Todo</title>
    <style>
     .container {
	 position: relative;
     }
     .container .col {
	 float:left;
	 position:relative;
	 padding: 0 20px;
     }
     .clear {
	 clear:both;
     }
     .col .list {
	 padding-left:1em;
     }
     .field {
         color: #666666;
     }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="col">
	<header><h1>TODO</h1></header>
<<<<<<< HEAD
	<input placeholder="What you will do?" name="new_item" /> <button id="new_item_btn">Add</button>
=======
	<input class="field" name="new_item" /> <button id="new_item_btn">Add</button>
>>>>>>> add_class
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DOING</h1></header>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DONE</h1></header>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="clear"></div>
    </div>
  </body>
</html>

โดยที่โค้ดที่อยู่ระหว่าง <<<<<<< HEAD จนถึง ======= จะเป็นโค้ดที่อยู่ใน branch ปัจจุบันของเรา คือ master

และโค้ดที่อยู่ระหว่าง ======= จนถึง >>>>>>> add_class เป็นโค้ดที่อยู่ใน branch add_class ที่เกิดการ conflict กันนั่นเอง

<<<<<<< HEAD
	<input placeholder="What you will do?" name="new_item" /> <button id="new_item_btn">Add</button>
=======
	<input class="field" name="new_item" /> <button id="new_item_btn">Add</button>
>>>>>>> add_class

การแก้ conflict คือให้เราจัดการโค้ดตรงส่วนนี้ให้เปิดแบบที่เราต้องการ แน่นอน ให้คุยกันก่อนกับเพื่อนร่วมทีมที่เป็นเจ้าของ branch นี้ ถ้าเกิดเป็น branch ที่เราไม่ได้สร้างเอง ว่าโค้ดจริงๆตอนรวมกันจะเป็นยังไง

สำหรับกรณีนี้ให้เราแก้โดยให้โค้ดสุดท้ายที่รวมกันเป็นแบบนี้

<!doctype html>
<html>
  <head>
    <title>Todo</title>
    <style>
     .container {
	 position: relative;
     }
     .container .col {
	 float:left;
	 position:relative;
	 padding: 0 20px;
     }
     .clear {
	 clear:both;
     }
     .col .list {
	 padding-left:1em;
     }
     .field {
         color: #666666;
     }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="col">
	<header><h1>TODO</h1></header>
	<input class="field" placeholder="What you will do?" name="new_item" /> <button id="new_item_btn">Add</button>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DOING</h1></header>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="col">
	<header><h1>DONE</h1></header>
	<ul class="list">
	  <li>สอน Git <button name="delete_btn">x</button></li>
	  <li>กินกอกก <button name="delete_btn">x</button></li>
	</ul>
      </div>
      <div class="clear"></div>
    </div>
  </body>
</html>

หลังจากเราแก้โค้ดที่ conflict กันแล้วให้เราสั่ง git commit แล้ว git จะขึ้น editor โดยมี commit message ว่า Merge branch 'add_class' ให้เราจัดการ save แล้วออกจาก editor

การ rebase code

ตอนที่เราแยก branch ไปจาก branch อื่นๆ เช่นแยก add_class ไปจาก master จะเห็นว่าโค้ดเริ่มต้น จะเหมือนกับโค้ดหน้าตาสุดท้ายของ master

ทีนี้ เมื่อ master มีการเปลี่ยนแปลงไปจากเดิม ไม่เหมือนกับตอนที่เราแยก branch ไปแล้ว เราสามารถทำการ rebase ให้กับ branch ที่เราแยกมาก่อน

เมื่อให้ base โค้ดของ branch เราเป็นแบบใหม่ แล้ว commit ใหม่ที่เราสร้างใน branch ค่อยต่อจาก base ใหม่นั่นอีกที

เราสามารถใช้ git rebase ก่อนที่จะ merge ได้ เพื่อช่วยให้เราแก้ conflict ที่ branch ก่อนที่จะเอามา merge ใส่ master

git branch add_placehodler
git rebase master

git checkout master
git merge add_placehodler

git checkout add_class
git rebase master

ซึ่งจะเกิด conflict ขึ้น ที่ว่ารอบนี้โค้ดที่อยู่ตรงส่วน <<<<<<< HEAD จนถึง ======= จะเป็นโค้ดที่อยู่ใน branch ที่เราเอามา rebase

และโค้ดที่อยู่ระหว่าง ======= จนถึง >>>>>>> add_class เป็นโค้ดที่อยู่ใน branch add_class ที่เกิดการ conflict กันนั่นเอง

หลังจากแก้ conflict เสร็จแล้วให้เราสั่ง git rebase --continue เมื่อให้ git ทำการ rebase ต่อจนเสร็จ

แล้วให้กลับไปที่ master แล้ว merge add_class อีกครั้ง

git rebase --continue

git checkout master
git merge add_class

การใช้ rebase ก่อน จะทำให้ branch master ของเรานั้นไม่มี commit ที่ปะเป็น merge ซึ่งจะทำให้ commit log นั้นต่อเนื่องกันได้เนียนขึ้น

การ tag version

การ tag คล้ายๆกับ branch ต่างกันตรงนี้ branch เรามีเอาไว้แยกเพื่อปรับเปลี่ยนโค้ด แล้วค่อยเอามารวมกัน ส่วน tag เป็นการ mark จุด ระบุ version

เราสามารถใส่ tag ให้กับสถานะล่าสุดของโค้ดใน branch เราได้ดังนี้

git tag v0.0.1

git tag
v0.0.1

ใช้ git stash จำการแก้ไขไว้ชั่วคราวโดยยังไม่ต้อง commit

เราสามารถใช้ git stash เพื่อเก็บโค้ดที่เราแก้ไข เอาไว้ชั่วคราวก่อน ผมมักใช้ในกรณีที่แก้โค้ดไปแล้ว แต่อยากกลับไปสถาณะก่อนแก้ไข โดยที่ยังไม่อยากลบโค้ด หรือว่ายังไม่อยาก commit เก็บไว้ ผมจะใช้ git stash ช่วยเก็บไว้ก่อน เช่นถ้าเราแก้ไข index.html ไป แต่อยากกลับไปสถานะเดิมของ branch ให้เราสั่งดังนี้

git stash

แล้วหลังจากเราทดสอบอะไรบางอย่างจนพอใจ ให้เราสั่ง

git stash pop

เพื่อให้โค้ดที่เราบันทึกไว้กลับมา

เพิ่ม remote repository

สมมติเรามี repository อยู่บน github อยู่แล้ว เราสามารถใช้

git clone <repository_url>

เพื่อให้โค้ดมาอยู่บนเครื่องเรา และ git จะทำการเพิ่ม remote repository ให้เราชื่อว่า origin โดยอัตโนมัติ โดยเราเช็ครายการของ remote repository ได้โดยสั่ง

git remote show

ทีนี้ถ้าเรามีโค้ดอยู่แล้ว แล้วเราไปสร้าง remote repository เช่นบน github เราต้องเพิ่ม remote repository เอง ด้วย git remote add ดังนี้

git remote add <remote_name> <repository_url>

เสร็จแล้วค่อย push ขึ้นไปด้วย git push ซึ่งคำสั่ง git push นั้นต้องระบุ ชื่อ remote name เช่น origin แล้วตามด้วย branch ที่เราต้องการ push ขึ้นไปเช่น master รวมกันเป็น

git push origin master

ในการทำงานร่วมกันบน remote branch เดียวกันนั้น ถ้าเกิดมีคน push ขึ้นไปก่อนเรา เราต้อง pull โค้ดใน remote branch ที่เปลี่ยนไปแล้ว ให้ลงมารวมกับโค้ดในเครื่องเราก่อน จริงๆ pull ก็คือการ merge นั่นเองครับ แต่เป็น merge จาก remote branch มา branch ในเครื่องเรา และ ซึ่งเราสามารถใช้ rebase ได้เช่นกันโดยสั่ง --rebase เป็น option ให้กับ git pull นั่นเอง

ตัวอย่างการใช้ git pull เช่น

git pull orin master

git pull --rebase origin master

ในกรณีที่บน remote branch มี branch ใหม่เกิดขึ้น เราสามารถ checkout branch นั้นให้มาอยู่เครื่องเราได้เช่นกัน แต่ให้เราใช้ git fetch ก่อน เพราะ git fetch จะเป็นการ sync branch แล้วเราถึงจะ git checkout ได้ เช่น

git fetch

git checkout new_remote_branch

การสร้าง pull request

การ Review pull request

Docker คืออะไร

Docker คือเครื่องมือจัดการ container ส่วน container เป็นเทคโนโลยีที่ใช้ฟีเจอร์ของ OS Kernel เช่น Linux ที่ช่วยให้เราสามารถรันโปรแกรมแยกออกจากกัน โดยจำลองสภาพแวดล้อมต่างๆให้พร้อม

Docker Container

การใช้ docker เบื้องต้น

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment