svn 概念, 初階使用
UPDATE: 2011-01-09 SVN merge
UPDATE: 2010-04-13 images added
ORG: 2009-06-13
svn 是一個管理源碼的工具
它提供一個容許多人協作的平台, 幫助一個多人開發的團隊管理代碼
同時提供一個保存多版本的功能 (version-ing)
而我因為多數都自己一個開發, 主要為了 versioning 而使用 svn
但因為有多個開發機器
為了保持代碼在多個機器中同步, 都會使用 svn
我在 windows 機是使用 TortoiseSVN GUI client
ubuntu 上使用 nautilussvn
使用上, 介面上都很類似, 都很好用
先談一下 svn 的概念
svn server 是指在 remote 上的server
大家都將大家的code 上傳 (commit) 到這個中央的server
而開發機則是 client端 (當然, 他們其實可以在同一部機器上)
而 head 是指最新的一組檔案的集合, 統稱 head version
trunk 一般指 server 上的 head.
從日常使用次數最多的功能開始介紹
checkout
從server 上下載源碼(即 server 上己經建立好, 設定好)
在本機(即開發機上)建立一個拷貝
是在開發機上開始建立一個新的 project 的方法
完成便可以開始改動源碼, 開發的工作了
可以從 code.google.com 隨便選一個 project 使可以checkout了 (source tab 便可以找到 svn url, 例)
commit / add
commit 是指將本機的源碼上載到 svn server 上(要已經checkout 過的檔案)
例如已經checkout 過的 project,
在改動源碼之後, 資料夾上使會有一個紅色的X, 代表需要 commit
而如果你有權力 commit, 便可以上載到 svn server 上了
而每一個commit 都儲存到 server 上, 之後的任何時候都可以調用, 還原等等 (就算commit 再覆寫過都可以)
而 add 則是新增一個沒有 svn 的檔案到 svn server.
commit 的策略是, 每午飯之前, 下班之前都commit, 原因在討論 update 之後再研究
update
如果我 checkout 了一個 project, 但 project code 在svn server 上有其他人 commit 了中
我應該如何更新我的 code 令自己和svn server 同步?
答案是 update.
svn 會幫我們從 server 上下載, 而且萬一需要覆寫一個我們正在修改的檔案(即一個衝突 conflict 發生了),
svn 會嘗試幫我們合併, 確保同事做的修改和我們的修改都正確的保存
如果開發團隊同意了午飯前, 下班前commit 當日的源碼,
update 的策略便是 上班的第一件事, 和午飯後的第一件事了.
change log, diff
每一次的commit 都會留下記錄在 server 上 (change log)
並有一個唯一的 版本(version) id
我們任何時候都可以將任何兩個 commit 比較
並還原, 合併任何兩個檔案
svn 在處理 conflict 的時候, 不一定能自動合併
這時 svn 會要求我們做手動合併, diff 工具都會協助我們分析兩個衝突檔案的內容的
tag / branch
這是一個進階使用者的題目, 請先確保你試過, 用過上面的功能再繼續
head 便是一個等殊tag, 這個tag 是會隨著commit 而移動
而我可以因應需求tag 一個 2009-06-08 tag
標記這些便是 09年 6月 8日 的源碼, 主要是為了方便日後的調用 (稱為日期tag)
而branch 其實和 tag 類似, 但 checkout 了 branch 的話, 你的 commit 會指定為 commit 到這個 branch,
而不是一般的主線
這樣, 你就可以將你的重大更新, refactoring 開一個 branch, 完成再 merge
令自己的重大更新的開發代碼不會干擾其他同事的開發
指令上在 GUI 都好簡單, checkout/update 了以後, 直接在資料夾上右鍵->tag/branch 便可以了
安裝 svn server @ubuntu
首先安裝 SVN
sudo apt-get install subversion
安裝 svn 在 Apache 使用的套件
sudo apt-get install libapache2-svn
進階的權限便自己 google 一下了
Project setup
安裝完便要建立一個 trunk,
而一般的資料夾習慣是:
SVN-ROOT
-PROJECT-NAME1
--trunk
--tags
--branches
-PROJECT-NAME2
--trunk
--tags
--branches
建立 SVN-ROOT 到 /home/svn:
sudo svnadmin create /home/svn
建立 PROJECT-NAME1:
GUI:
在開發資料夾 (例 /var/www) checkout file:///home/svn
checkout 後建立 trunk, branches, tags 三個資料夾
commit 三個資料夾
再 del 三個資料夾, 然後 checkout trunk
便可以開始 add了
conclusion
會使用 svn 工具絕對是其中一個進階程序員的指標 (包括 tag/branch)
工具看似複雜, 但其實真正做起來只是很簡單的概念, 但用文字真的比較難以表達
找一個人教一教, 十分鐘便什麼都懂了.
version control 的工具其實還有 cvs, git 等, 概念有一點不同
但一般的操作反而很類似, 舉一反三就是了
但svn 都不是萬能
sql server 中設定很多的 cms (drupal 便是一個明顯例子) 如何做 version control?
mysqldump + commit?
有高手能解答嗎?
Attachment | Size |
---|---|
checkout.png | 6.97 KB |
commit.png | 9.68 KB |
update.png | 10.21 KB |
在icdsoft 使用 codeigniter 的clean url
在icdsoft中使用 clean url
http://example.com/index.php/abc -> http://example.com/abc
出現錯誤, return 404
clean url CI doc:
http://codeigniter.com/user_guide/general/urls.html
solved by Google, CI wiki:
http://codeigniter.com/wiki/Dreamhost_.htaccess/ (solution1)
RewriteEngine on
RewriteCond $1 !^(index\.php|public|user_guide|robots\.txt)
RewriteRule ^(.*)$ /index.php?/$1 [L]
Note the question mark after index.php
D6 regions, regions vs panels
有別於 Drupal 5 中在 template.php 定義region 的方式,
Drupal 6.x 的region 定義在 [theme].info 之內: (用Drupal 5.x 一篇的例子)
regions[left] = Left sidebar
regions[right] = Right sidebar
regions[content] = Content
regions[header] = Header
regions[footer] = Footer
regions[bottom_left] = Bottom left
regions[bottom_center] = Bottom center
regions[bottom_right] = Bottom right
regions[] array 之內用underscore, 右面可以用 space 空格
$bottom_right, $bottom_left, $bottom_center 等的變數就會出現在page*.tpl.php 之內
你可以將它們放到自定的位置, div 之內
//page.tpl.php
<?php
if ( $bottom_left || $bottom_center || $bottom_right || $feed_icons ):
endif;
?>
到 admin->site building->blocks 就會看到有'bottom left' 等等的選項了
ref: http://drupal.org/node/171224
而region vs panels 都是做很相似的工作,
便是提供一個分割頁面的方法
我的經驗是, 像我這個block, 每一頁的頁底都需要三個分割
用region 比較好
而特定的頁面的分割, 則使用panels 比較方便
而且, 要記得, regions 的variable 只會在 page*.tpl.php 中出現
Drupal multi site single sign on
EDIT: 2010-04-11 settings.php 的位置
同一個domain 之下使用多個 Drupal multi site 的時候,
可以共用同一組的user 是很簡單了
但login 了一個site 之後, 登入的狀態卻不能夠一直在不同的subdomain 使用
但服用以下之後就可以了: (在你的 sites/[folder]/settings.php 內, 原本注釋了的)
<?php
//settings.php
$cookie_domain = '.example.com';
?>
implement hook_block()
hook_block() 是一個給 Drupal 提供block 的方法
假如你發覺自己在 add block 的時候用了 input method 使用了php
那你其實應該建立一個 module, 使用 hook_block()
原因: "module" vs "add block"
- php 的 syntax error 不會因為寫進了 DB 而做成修正的極大麻煩 vs 要直接修改 DB record
- File 方便 version control vs DB record 的 version control 和沒有做差無幾..
- customization 集中方便修改 vs 源碼分散
- File deployment vs DB deployment
所以, 不要懶了, 而且建立hook_block() 也很簡單
假設 module 名為 joe
<?php
function joe_block($op = 'list', $delta = 0, $edit = array()) {
//在 admin/building/block 時設定用
if ($op == 'list') {
//$blocks 為array, 即一個module 可以提供多個block
$blocks[0] = array('info' => t('Mymodule block #1 shows ...'),
'weight' => 0, 'status' => 1, 'region' => 'left');
//第二個block
$blocks[1] = array('info' => t('Mymodule block #2 describes ...'));
// $op為list 時返回 block[]
return $blocks;
}
//$op 為 view 則 真正輸出使用
else if ($op == 'view') {
switch($delta) {
//第一block, $delta 為 0
case 0:
$block = array('subject' => t('Title of block #1'),
//content 可以在另一個function 內定義
'content' => joe_display_block_1());
break;
//$delta == 1
case 1:
$block = array('subject' => t('Title of block #2'),
'content' => joe_display_block_2());
break;
}
return $block;
}
}
function joe_display_block_1() {
//直接貼原本在php content 內的代碼就可以了
return $return;
}
function joe_display_block_2() {
return $return;
}
?>
ref:
http://api.drupal.org/api/function/hook_block/6
建立一個新 module:
http://www.joetsuihk.com/module_development_introduction_moduleinfo
台灣的朋友的詢問:
http://drupaltaiwan.org/forum/20100205/4016#comment-13542