Categories
Git

การใช้ไฟล์ .gitignore กับโปรเจคเก่า ๆ

บางครั้งเรามีโปรเจคเก่าที่ใช้ Git อยู่แล้ว แต่เรา ignore ไฟล์ไม่ครบ อาจมีไฟล์ที่เราไม่ต้องการ ถูก track เข้าไปด้วย เช่น ไฟล์จาก OS หรือ ไฟล์จาก IDE เป็นต้น

เราสามารถแก้ไขได้ง่าย ๆ ด้วยคำสั่งเพียงไม่กี่คำสั่ง แต่ก่อนอื่นผมขอแนะนำสำหรับคนที่ไม่รู้ว่าจะ Ignore ไฟล์อะไรดี สามารถเข้าไปดูได้ที่ https://github.com/github/gitignore ซึ่งรวบรวมไฟล์และโฟลเดอร์ที่เราควร ignore ไว้ครบถ้วน (ผมแนะนำให้ดูในโฟล์เดอร์ Global ด้วย เพราะมีคำแนะนำการ ignore ไฟล์ของ IDE และ OS เพิ่มเติม)

สมมุติว่าผมเขียน Java ด้วย Eclipse บน macOS ผมจะสามารถสร้างไฟล์ .gitignore ได้ประมาณนี้

# General
*.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

#Eclipse
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders

# External tool builders
.externalToolBuilders/

# Locally stored "Eclipse launch configurations"
*.launch

# PyDev specific (Python IDE for Eclipse)
*.pydevproject

# CDT-specific (C/C++ Development Tooling)
.cproject

# Java annotation processor (APT)
.factorypath

# PDT-specific (PHP Development Tools)
.buildpath

# sbteclipse plugin
.target

# Tern plugin
.tern-project

# TeXlipse plugin
.texlipse

# STS (Spring Tool Suite)
.springBeans

# Code Recommenders
.recommenders/

# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet

#Java
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

เมื่อสร้างไฟล์ .gitignore ก่อนที่จะทำขั้นตอนต่อไปให้ทำการ commit การเปลี่ยนแปลงทั้งหมดก่อน

แล้วใช้คำสั่งนี้เพื่อเคลียร์ index ของ git

$ git rm -r --cached .

แล้วใช้คำสั่ง

$ git add .

และ commit

$ git commit -m ".gitignore is now working"

เพียงเท่านี้เราก็สามารถ ignore ไฟล์และโฟลเดอร์ที่เราไม่ต้องการได้แล้วครับ

Categories
Git

การใช้งาน Git Submodules

หลังจากที่ผมได้รู้จัก Git Submodules มาซักพักหนึ่ง ผมก็พยายามใช้ในงานต่าง ๆ ซึ่งช่วยให้ผมจัดการ Source code สะดวกขึ้นมาก แต่เนื่องจากได้ใช้คำสั่งพวกนี้ในช่วงเริ่มโปรเจคซะเป็นส่วนใหญ่เลยทำให้มีอาการหลงลืมคำสั่งไปบ้าง ก็เลยมาบันทึกไว้หน่อยจะได้ไม่ต้องไปหาข้อมูลใหม่อีก

การเพิ่ม Submodules เข้ามาใน Git Repository

ใช้คำสั่งดังนี้

$ git submodule add https://github.com/golfz/module1 lib/module1
Initialized empty Git repository in ~/a_project/lib/module1/.git/
remote: Counting objects: 1006, done.

remote: Compressing objects: 100% (978/978), done.

remote: Total 1006 (delta 631), reused 0 (delta 0)

Receiving objects: 100% (1006/1006), 408.22 KiB, done.

Resolving deltas: 100% (631/631), done.

แต่ละส่วนของคำสั่งมีรายละเอียดดังนี้

git submodule add เป็นคำสั่ง git เพื่อเพิ่ม Submodules

https://github.com/golfz/module1 คือ git repository ภายนอกที่เราต้องการเพิ่มเข้ามาเป็น submodule ซึ่งคุณต้องมั่นใจว่าคุณมีสิทธิ clone repository นี้

lib/module1 คือ path ของ submodules ใน repository หลัก

ลองตรวจสอบ repository ดูด้วย git status
$ git status
# On branch master
# Changes to be committed:

# (use "git reset HEAD <file>..." to unstage)

#

# new file: .gitmodules

# new file: lib/module1

#

ถ้าเราลองตรวจสอบ .gitmodules ที่เพิ่มเข้ามาใหม่ จะพบข้อมูลดังนี้

$ cat .gitmodules
[submodule "lib/module1"]
path = lib/module1

url = https://github.com/golfz/module1

การใช้งาน Submodules

ถ้าเราเพิ่ม clone repository ลงมา เราจะพบว่าโฟลเดอร์ที่เป็น submodule จะว่างเปล่า ดังนั้นเราต้อง initial submodules ก่อน ดังนี้

$ git submodule init
Submodule 'lib/module1' (https://github.com/golfz/module1) registered for path 'lib/module1'

ขั้นตอนต่อไปเราจำเป็นต้อง pull files ลงมา

$ git submodule update
Initialized empty Git repository in ~/a_project/lib/module1/.git/
remote: Counting objects: 26, done.

remote: Compressing objects: 100% (22/22), done.

remote: Total 26 (delta 5), reused 0 (delta 0)

Receiving objects: 100% (26/26), 17.37 KiB, done.

Resolving deltas: 100% (5/5), done.

Submodule path 'lib/module1': checked out '1c407cb2315z0847facb57d79d680f88ca004332'

ตอนนี้ถ้าเราเข้าไปดูใน lib/module1 เราจะพบว่ามีไฟล์อยู่อย่างถูกต้องแล้ว

การลบ Submodules

ขั้นตอนในการลบ Submodules จะมีความซับซ้อนเล็กน้อย ดังนี้

1. เข้าไปลบข้อมูล submodules ในไฟล์ .gitmodules ให้ลบข้อมูลออกไปดังนี้
[submodule "lib/module1"] path = lib/module1
url = https://github.com/golfz/module1

2. เข้าไปลบข้อมูล submodule entry ในไฟล์ .git/config ขั้นตอนนี้ไม่จำเป็นต้องทำก็ได้ แต่เพื่อป้องกันปัญหาในอนาคตหากเราใช้คำสั่ง “git submodule init” ผมแนะนำว่าทำก็ดีครับ โดยให้ลบข้อมูลออกไปดังนี้
[submodule "lib/module1"] url = https://github.com/golfz/module1

3. ลบ path ของ Submodules ด้วยคำสั่ง
$ git rm --cached lib/module1
rm 'lib/module1'

การอัพเดต Submodules

นี่เป็นอย่างหนึ่งที่เราจะค่อนข้างสับสนเมื่อใช้งาน Submodules เพราะเมื่อเราเพิ่ม submodules เข้ามา เราจะได้รับ commit ล่าสุดของ repository ของ submodule นั้น

หากหลังจากนั้น Repository ของ submodule มีการอัพเดตแล้วเรา clone โปรเจคหลักไปที่อื่น แล้วใช้คำสั่ง

$ git submodule init

ต่อด้วย

$ git submodule update

เราจะพบว่าเราจะไม่ได้โค้ดล่าสุดของ submodule ซึ่งมักสร้างความสับสนอยู่บ่อยครั้ง

แต่หากคิดดูดี ๆ ก็จะพบว่ากลไกนี้มีความเหมาะสมแล้ว เนื่องจาก code ใน repository หลักของเราได้ถูกทดสอบกับ submodules เวอร์ชั่นใด เมื่อ clone repository หลักไปใช้ก็ควรได้ submodule เวอร์ชั่นเดิมที่เคยทดสอบแล้ว ไม่ใช่เวอร์ชั่นใหม่ล่าสุดที่เราไม่เคยทดสอบ

แต่หากเราต้องการ repository ของ submodule ใหม่ล่าสุด สามารถทำได้ดังนี้

1. เข้าไปที่โฟลเดอร์ของ submodule

$ cd lib/module1

2. checkout ไปที่ master

$ git checkout master
Previous HEAD position was b8ff8f6... re-ordering
Switched to branch 'master'

Your branch is behind 'origin/master' by 8 commits, and can be fast-forwarded.

3. ดึงอัพเดตล่าสุดลงมา

$ git pull
remote: Counting objects: 31, done.
remote: Compressing objects: 100% (24/24), done.

remote: Total 24 (delta 15), reused 0 (delta 0)

Unpacking objects: 100% (24/24), done.

From https://github.com/golfz/module1

b8ff8f6..5cab93f master -> origin/master

* [new tag] 1.2.28 -> 1.2.28

From https://github.com/golfz/module1

* [new tag] 1.2.26 -> 1.2.26

* [new tag] 1.2.27 -> 1.2.27

Updating c547e0d..5cab93f

Fast-forward

index.php | 109 ++++++++++++++-

css/admin.css | 26 ++++

js/admin.js | 17 +++

3 files changed, 51 insertions(+), 4 deletions(-)

create mode 100644 css/admin.css

create mode 100644 js/admin.js

4. กลับไปที่ repository หลัก แล้ว

$ git add lib/module1
$ git status
# On branch master
# Changes to be committed:

# (use "git reset HEAD ..." to unstage)

#

# modified: lib/module1

#

Categories
Git

การใช้งาน git กับโปรเจคที่มีอยู่แล้ว

  1. สร้าง Repository ใหม่
  2. $ cd /path/of/your/local/project
  3. $ git init
  4. $ git add .
    # Adds the files in the local repository and stages them for commit
  5. $ git commit -m ‘First commit’
    # Commits the tracked changes and prepares them to be pushed to a remote repository
  6. copy the remote repository URL.
  7. $ git remote add origin <remote repository URL>
    # Sets the new remote
    $ git remote -v
    # Verifies the new remote URL
  8. $ git push origin master
    # Pushes the changes in your local repository up to the remote repository you specified as the origin