ติดตั้ง SVN (SubVerSion), แนวคิดเบื้องต้นและการนำไปใช้ สำหรับ web application บน Ubuntu

เกริ่นนำหลังจากหายไป 3-4 ปีเลยมั้ง user ผมยังใช้ได้แฮะ นึกว่าหายไปจากฐานข้อมูลเว็บเสียแล้ว ผมเป็นสมาชิกคนต้นๆ ของเว็บเลยก็ว่าได้ และเคยเขียนบทความ ตอบกระทู้อยู่สักพักแล้วก็หายยาว เนื่องจากวิถีชีวิตเปลี่ยน ตอนนี้ชีวิตก็ยังผจญภัยอยู่เหมือนเดิม ยังไม่นิ่งเท่าที่ควร แต่ก็ยังวนเวียนอยู่กับเรื่องของการเขียนโปรแกรมอยู่นั่นแหละจะไปไหนได้ ถ้าชีวิตยังทำเป็นอยู่แค่เรื่องเดียว เข้าเรื่องดีกว่า

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

ทำไมผมถึงใช้ SVN เหตุเพราะว่าหนนี้ผมมีเว็บแอพพลิเคชั่น เป็นโปรเจ็กต์ส่วนตัว ที่ได้มีร่วมพัฒนามากกว่า 1 คน (2 คน ;) แล้ว และอยู่ต่างสถานที่กัน จึงเห็นความจำเป็นที่จะต้องมี software ที่ช่วยจัดการตรงนี้

SVN คืออะไร ? SVN เป็น software ที่เป็นตัวกลางช่วยจัดการบริหาร source code จากที่ๆเดียว สำหรับการพัฒนาโปรแกรมที่มีผู้พัฒนาหลายคน (ถ้าทำคนเดียวอาจไม่ต้องมีก็ได้) มีความสามารถป้องกันการแก้ไข code ชนกัน, แสดงสถานะให้ทุกคนทราบว่าตอนนี้ software ที่พัฒนาไปถึงไหนแล้ว ใครทำอะไรลงไปบ้าง, ย้อนเวลา, กู้ไฟล์กลับไปได้เรื่อยๆ เวลาเกิดปัญหา เป็นต้น

SVN concept chart

จากรูปศูนย์กลางอยู่ที่ Server กลาง เราเรียกตัวรวมศูนย์ตัวนี้ว่า Repository เรียกย่อๆ ว่า repo คือแหล่งที่เก็บ source code, 1 repo ต่อ 1 โปรเจ็กต์ เราจะเรียกการใช้งาน อ่าน เขียน ได้ตามสิทธิของ client แต่ละคน ภายใน repo จะมีการบันทึกไฟล์เป็นไปตามรูปแบบของ SVN เอง ฉะนั้นอย่าไปเสียเวลาหาไฟล์ source code ของเราว่าไปเก็บอยู่ที่ไหนซะให้เมื่อย เนื่องจากลองไปหาเองมาแล้ว (โง่)

วิธีการติดตั้ง SVN Server

ขั้นตอนนี้ควรมี server เป็นของตัวเองหรือ VPS เชื่อได้ว่า share hosting อาจทำไม่ได้หรือทำได้ลำบาก หรือลองทดสอบเล่นบนเครื่องตัวเองก่อนก็ย่อมได้ svn สามารถติดต่อได้หลายทางไม่ว่าจะเป็น svn protocol, svn+ssh, http สำหรับ how to นี้ เราจะลงแบบใช้ protocol http ผ่าน apache

1. ลงโปรแกรมที่จำเป็นดังนี้

$ sudo aptitude install subversion
$ sudo aptitude install apache2 libapache2-svn

2. เปิดไฟล์ /etc/apache2/mods-enabled/dav_svn.conf

$ sudo vim /etc/apache2/mods-enabled/dav_svn.conf

เปิดมาจะเห็นดังนี้ ให้แก้ไขเอา comment ออกตามด้านล่างหรือตามชอบ

<Location /svn>
   DAV svn
   # ให้เลือกเอาอย่างใดอย่างหนึ่งว่าจะให้เป็น svn parent path หรือ svn path ไปเลย
   # svn parent path สามารถใช้งานได้หลายๆ repository
   # svn path เป็นการระบุให้สามารถใช้งานได้เพียง repository เดียว
   #SVNPath /var/lib/svn
   # ผมเปลี่ยนค่า default จากเดิมเป็น /home/svn โดยสร้าง directory svn ใน home
   SVNParentPath /home/svn
  
   # หากต้องการใช้ตรวจสอบผู้ใช้งาน
   AuthType Basic
   AuthName "Subversion Repository"
   AuthUserFile /etc/subversion/dav_svn.passwd
 
   # หากต้องการ ควบคุมการเช้าถึงของ user
   AuthzSVNAccessFile /etc/subversion/dav_svn.authz

   Require valid-user
</Location>

3. เพิ่ม user สำหรับคนที่ต้องการจะให้เข้ามาใช้งาน ในที่นี้สร้างไว้สองคน คือ tee กับ pond ในการสั่งครั้งแรกต้อง มี -c เนื่องจากต้องสร้างไฟล์ขึ้นใหม่

$ sudo htpasswd -cm /etc/subversion/dav_svn.passwd tee
$ sudo htpasswd -m /etc/subversion/dav_svn.passwd pond

4. สร้างไฟล์เพื่อกำหนดสิทธิการใช้งาน

$ sudo vim /etc/subversion/dav_svn.authz

ใส่เนื้อหาตามตัวอย่างด้านล่าง

#บ่งบอกว่า กลุ่ม developer มี tee กับ pond เป็นสมาชิก
[groups]
developer = tee, pond

#กำหนดให้ กลุ่ม developer ด้านบน สามารถอ่านและเขียนข้อมูลใน repo ที่ชื่อ ramique.com ได้ และอ่านอย่างเดียวสำหรับ ผู้ใช้งานที่ชื่อ testuser
[ramique.com:/]
@developer = rw
testuser = r

#เหมือนด้านบนเพียงแต่กำหนดสำหรับ folder /doc เท่านั้น โดยให้ใครก็ตามสามารถอ่าน folder นี้ได้ กำหนดโดย * = r
[ramique.com:/doc]
@developer = rw
testuser = rw
* = r

5. สร้าง folder ที่เก็บ repo ตามตำแหน่งใน /etc/apache2/mods-enabled/dav_svn.conf

$ sudo mkdir /home/svn/

6. สร้าง repo ชื่อ ramique.com

$ sudo svnadmin create /home/svn/ramique.com

7. เปลี่ยนชื่อเจ้าของไฟล์ใน repo ให้เป็นของ apache

$ sudo chown -R www-data: /home/svn/ramique.com

8. restart apache สักครั้ง

$ sudo /etc/init.d/apache2 restart

9. ทดสอบแสดงผลภายใน repo ผลจะออกมาไม่เจออะไรเพราะยังไม่มีอะไรใน repo

$ svn ls http://localhost/svn/ramique.com

การ setup ฝั่ง SVN Server

1. สร้าง directory ใน SVN Server ตามมาตรฐานชาวบ้านเขาดังนี้ trunk (ลำต้น) เก็บ source code ที่เป็นสายหลักของการพัฒนา source code ล่าสุดอยู่ที่นี่, branches (กิ่ง) เก็บ source code ที่เป็นส่วนของการแตกกิ่งออกไปพัฒนาเฉพาะด้านเองต่างหาก โดยไม่ต้องยุ่งเกี่ยวกับส่วนลำต้น, tags เก็บ source code ที่เป็นเหมือนบันทึกสถานะอาจจะอยู่ในรูปของเลข version แล้วไม่มีการเปลี่ยนแปลงแก้ไขอะไรอีก

$ svn mkdir http://localhost/svn/ramique.com/trunk -m "Create initial trunk directory"
$ svn mkdir http://localhost/svn/ramique.com/branches -m "Create initial branches directory"
$ svn mkdir http://localhost/svn/ramique.com/tags -m "Create initial tags directory"

2. Import โปรเจ็กต์เข้าสู่ SVN Server เป็นการส่งไฟล์งานของเราครั้งแรกไปเก็บไว้ใน repo ถ้า project ยังไม่มีไฟล์อะไรเลยข้ามส่วนนี้ไปได้ พอดีว่าผมมีไฟล์เริ่มต้นของโปรเจ็กต์ไปบ้างแล้ว จึงต้อง import เข้าไปครั้งแรกก่อน โดย import เข้าไปในลำต้นหรือ trunk (หากต้องการแตกกิ่ง branches หรือ tags ให้ใช้คำสั่ง svn copy เป็นการทำสำเนาไปยังตำแหน่งที่ต้องการ)

$ svn import /tmp/ramique.com http://localhost/svn/ramique.com/trunk -m "Create project initial import"

3. ดึงไฟล์โปรเจ็กต์จาก svn ไปยังตำแหน่งที่เว็บไซต์ใช้งานจริงอยู่ เรียกว่า checkout ตำแหน่งที่นำไฟล์มาลงเรียกว่า working copy คือ /home/tee/domains/ramique.com/trunk อย่าลืม chown working copy เป็น www-data ก่อน checkout

$ sudo svn checkout file:///home/svn/ramique.com/trunk /home/tee/domains/ramique.com/trunk

4. เปลี่ยนชื่อเจ้าของไฟล์ให้เป็นของ apache เพื่อให้ apache สามารถ update ไฟล์แบบอัตโนมัติได้

$ sudo chown -R www-data: /home/tee/domains/ramique.com/trunk

5. ทำ auto update ให้กับ working copy บน server หลังจากที่ใครก็ตามเปลี่ยนแปลงแก้ไขไฟล์บน svn หรือที่เรียกว่า commit เพื่อที่เราจะได้ดูผลของการแก้ไขบน browser ได้ทันที เปรียบเหมือนกับ upload ผ่าน ftp เสร็จแล้วก็สามารถกด refresh บน browser ดูผลได้ทันที

$ sudo cp /home/svn/ramique.com/hooks/post-commit.tmpl /home/svn/ramique.com/hooks/post-commit
$ sudo chmod +x /home/svn/ramique.com/hooks/post-commit

6. แก้ไข post-commit เป็น shell script ไฟล์นี้จะทำงานหลังจากที่มีการ commit ใดๆ ใส่ คำสั่ง /usr/bin/svn update /home/tee/domains/ramique.com/trunk เข้าไปที่ด้านล่างของไฟล์ กรณีนี้สั่งให้ทำ auto update เฉพาะใน trunk เท่านั้น ภายในยังมีตัวอย่าง script อยู่บรรทัดนึงเป็นคำสั่งส่งเมล์กรณีที่มีการ commit ผม uncomment มันออกไป

$ sudo vim /home/svn/ramique.com/hooks/post-commit

7. หลังจาก checkout แล้ว ทุกๆ folder ที่อยู่ใน working copy จะมี folder ซ่อน ที่ชื่อ .svn สำหรับการ log ค่าต่างๆ เอาไว้ เนื่องจากไม่จำเป็นต้องให้บุคคลภายนอกที่เข้าถึงผ่าน http มองเห็น เราจึงควรจะซ่อนเอาไว้ โดยใส่ config ด้านล่างที่ /etc/apache2/httpd.conf หรือ ใส่ไว้ในไฟล์ที่เรา config virtual host อย่างเช่น /etc/apache2/sites-available/default

# Disallow browsing of Subversion working copy administrative dirs.
<DirectoryMatch "^/.*/\.svn/">
  Order deny,allow
  Deny from all
</DirectoryMatch>

* -m ที่ใส่หลัง svn เป็นการใส่ comment หรือ log ถ้าไม่ใส่ shell ก็จะขึ้นให้ใส่ภายหลังจากสั่งอยู่ดี

การ setup ฝั่ง SVN Client

1. ดึงไฟล์โปรเจ็กต์มาลงเครื่อง client หรือเครื่องของตัวเองที่ใช้ในการพัฒนา โดยการ checkout ที่อยู่ปลายทางที่ /home/vsites/ramique.com/trunk ให้เป็น working copy บนเครื่องตัวเอง

$ svn checkout http://[ตรงนี้ใส่ ip หรือ host name ของ server]/svn/ramique.com/trunk/ /home/vsites/ramique.com/trunk

การใช้งานฝั่ง client

ไหนๆ ก็ใช้ CLI (command line interface) กันมาตลอดแล้วก็จะขอแนะนำการใช้งาน client แบบ CLI กันต่อนะครับ สำหรับเครื่องมืออำนวยความสะดวกที่เป็น GUI มีให้ใช้อยู่แล้วในโปรแกรม กระต่าย http://rapidsvn.tigris.org/ (RapidSVN เป็น GUI สำหรับหลาย Platform) กับ เต่า http://tortoisesvn.tigris.org/ (TortoisSVN GUI สำหรับ Windows) บางครั้งผมก็ใช้ CLI กับ GUI ควบคู่กันไปแล้วแต่การใช้งานว่าอย่างไหนสะดวกกว่ากัน ด้านล่างจะแสดงเฉพาะคำสั่งที่ใช้บ่อยๆ เท่านั้น

svn add /path/to/file - เปลี่ยนสถานะไฟล์เป็น added รอการเพิ่มไฟล์เข้าสู่ reo
svn delete /path/to/file - เปลี่ยนสถานะไฟล์เป็น deleted รอการลบไฟล์จาก repo
svn update [/path/to/file] - update version ของไฟล์บน client ให้เป็นเหมือน server เปรียบเหมือน ftp download หากสั่ง update เฉยๆ โดยไม่ใส่ตำแหน่งไฟล์ จะเป็นการ update ไฟล์ใหม่ทั้งหมด
svn commit [/path/to/file] - update version ของไฟล์บน server ให้เหมือนบน client เปรียบเหมือน ftp upload หากสั่ง commit เฉยๆ โดยไม่ใส่ตำแหน่งไฟล์ จะเป็นการ update ไฟล์ทั้งหมด
svn status - ใช้ดูสถานะไฟล์ใน working copy

* ในบางครั้งการใช้คำสั่ง svn ถ้าหากเป็น user เดียวกับที่เรา login จะถาม password แต่ถ้าไม่ใช่ เมื่อเคาะ enter ผ่านไปจะถาม user สำหรับ svn ให้ใส่ให้ถูกต้อง
* สามารถเปลี่ยน localhost เป็น ชื่อ หรือ ip ของเครื่อง server ก็จะเรียกใช้งานคำสั่งได้จากทุกที่ใน how to นี้
* เรียนรู้คำสั่งเพิ่มเติมได้ที่ http://cbbp.thep.lu.se/~jari/documents/subversion_guidelines/subversion_... อันนี้ค่อนข้างเป็น Manual ฉบับย่อที่ค่อนข้างครบถ้วนการใช้งานเลยทีเดียวมีแค่ 20 หน้า

เรียบเรียงจาก
http://debianclub.org/node/435
http://www.ploysics.com/svn-subversion/
http://www.tod4yis.net/post/Branching-and-Merging-with-Subversion.aspx
http://marcgrabanski.com/article/svn-authentication-and-auto-update

ที่มา
http://www.numthang.org/content/4882/1/

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

Comments

chaow's picture

<p>เคยทำอยู่ครับแต่ไม่สำเร็จซักที ไว้ลองแล้วจะรายงานผลละกัน</p>

=========================
My website Porkaew.net
My new e-mail chaow at porkaew.net

ascii.z's picture

<p>น่าสนใจครับ จะลองเล่นอยู่พักหนึ่งตอนจะลอง symfony ได้แค่เริ่มๆ แล้วก็ไม่มีเวลามาดูอีกเลย</p><p>มาทำ guide .ให้แบบนี้เยี่ยมเลยครับ</p>
livedev's picture

<P><A href="mailto:root@LiveServ">root@LiveServ</A>:~# svn ls <A href="http://localhost/svn/arisecorp.com">http://localhost/svn/arisecorp.com</A><BR>svn: Server sent unexpected return value (403 Forbidden) in response to OPTIONS request for 'http://localhost/svn/arisecorp.com'</P> <P>มันขึ้นแบบนี้ครับ ต้องแก้ไขยังไงครับ</P>
tee's picture

<p>อ่าว ไป comment ที่เว็บผมด้วยแหะ ผมตอบที่นี่แล้วกัน จะได้ถูกที่ ถูกทาง</p><p>กำหนดสิทธิสำหรับ user แล้วยังครับที่ $ sudo vim /etc/subversion/dav_svn.authz<br><br>ถ้ากำหนดแล้วขอดูเนื้อหาในไฟล์หน่อยครับ ว่ากำหนดอย่างไร</p><pre><code><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 0, 187);"></span><span style="color: rgb(0, 0, 187);"><br><br></span></span></code></pre>
songyote's picture

ผมลองทุกวิธีแล้วก็ยังแก้ไขไม่ได้ ครับ ยังขึ้น Error แบบเดิมครับ รบกวนช่วยวิเคราะห์ให้ด้วยครับ ขอบคุณครับ ================= error ====================================== root@coe05:/home# svn ls http://localhost/svn/ramique.com svn: Server sent unexpected return value (403 Forbidden) in response to OPTIONS request for 'http://localhost/svn/ramique.com' ============================================================
tee's picture

http://localhost/svn/ramique.com << ตรงนี้แก้ชื่อ ramique.com เป็น svn folder ของตัวเองสะกดให้ถูกต้องนะครับ
livedev's picture

<P><BR>[groups]<BR>developer = pichit,eve,aery,sommai</P> <P>[arisecorp.com:/]<BR>@developer = rw<BR>testuser = r</P> <P>[arisecorp.com:/doc]<BR>@developer = rw</P> <P>ตามนี้เลยครับ ปล.เว็ปคุณ T อะไรครับจะได้ไปขอคำปรึกษาครับ ขอบคุณครับ</P>
tee's picture

<p>อย่าลืมสั่ง restart apache นะครับ<br><br>สร้าง password สำหรับ SVN แล้วยังครับ ลองสั่ง $ cat /etc/subversion/dav_svn.passwd ดู ถ้ามี user pichit แล้ว ลองสั่ง<br><br>$ svn ls http://localhost/svn/arisecorp.com --username=pichit<br><br>เสร็จแล้วจะให้ใส่ password ที่ตั้งไว้ตอนสร้าง pichit สำหรับ SVN นะครับ ไม่ใช่ password ของ user ระบบนะครับ มันคนละตัวกัน<br><br>อีกกรณี สร้าง $ sudo svnadmin create /home/svn/arisecorp.com ให้ตรวจดูว่า มี repo อยู่ใน svn ให้แน่ใจมีอยู่แล้วจริง หลังจากนั้นลอง $ sudo chown -R www-data: /home/svn/arisecorp.com<br><br>ถ้าไม่ได้ต้องลองตรวจสอบทุกขั้นตอนดูใหม่อีกครั้งนะครับ</p><p>ปล. เว็บผมก็ตาม link ที่มาน่ะครับ</p>
SilliCon's picture

<p>ผมทำตาม tutorial จนใช้งานปกติได้แล้ว แต่ยังเซ็ต post-commit ไม่สำเร็จครับ</p><p>ช่วยบอกวิธีทำแบบละเอียดหน่อยได้ไหมครับ</p><p>/usr/bin/svn update /home/tee/domains/ramique.com/trunk</p><p>.ในโดเมน /home/tee/domains/ramique.com จำเป็นที่ต้องเซ็ต svn ด้วยไหมครับ</p><p>และเวลากำหนด SVNParentPath /home/svn แสดงว่าโดเมนที่จะทำ svn ต้องอยู่ภายใต้ path /home/svn เท่านั้นหรือเปล่าครับ</p><p>&nbsp;</p>
tee's picture

<blockquote>.ในโดเมน /home/tee/domains/ramique.com จำเป็นที่ต้องเซ็ต svn ด้วยไหมครับ</blockquote> ต้อง checkout เหมือนกับดึงมาลงเครื่องตัวเองนั่นแหละครับตรงคำสั่ง $ sudo svn checkout file:///home/svn/ramique.com/trunk /home/tee/domains/ramique.com/trunk แต่อันนีี้เป็นการดึงจาก svn ในเครื่อง server มาลงอีกตำแหน่งใน server เดียวกันนะครับ <blockquote>และเวลากำหนด SVNParentPath /home/svn แสดงว่าโดเมนที่จะทำ svn ต้องอยู่ภายใต้ path /home/svn เท่านั้นหรือเปล่าครับ</blockquote> ใช่ครับ SVNParentPath หมายถึง มีได้หลาย project ภายใต้ folder นี้ครับ เช่น /home/svn/project1 ก็เป็น svn สำหรับ project1 และ /home/svn/project2 ก็เป็น svn สำหรับ project2 เป็นต้น * อย่าสับสนตรงนี้นะครับว่าเวลาในการใช้งานเราต้องใช้ไฟล์ที่ checkout จาก svn เท่านั้นนะครับ ไฟล์ใน svn ไม่สามารถนำมาใช้การได้โดยตรงต้อง checkout ออกมาก่อน
tee's picture

/home/tee/domains/ramique.com/trunk อันนี้เป็น working copy ธรรมดาครับ
iistii_pingpong's picture

จะเป็นอะไรมั้ยครับ ถ้าเราใช้ SVN Clients เป็น Linux ร่วมกับ SVN Server ที่เป็น Windows น่ะครับ (เพิ่งหัดใช้งาน Ubuntu น่ะครับ )
tee's picture

ไม่น่ามีปัญหานะฮะ