Wednesday, February 04, 2009

การใช้งาน git กับ host ที่ไม่ support git

วันก่อนเจอคำถามถึงว่า ต้องการทำ version control กับ web application project
โดยทำกับ directory ที่ live อยู่บน host ที่ไม่ support git จะมีวิธีไหนทำได้บ้าง?

วิธีแรกก็คือใช้ sshfs ในการ mount remote file system แล้วก็สร้าง git repository บน live directory นั้นเลย

sshfs pune.ingres.co.th:/srv/www/htdocs/test /mnt -o workaround=rename
cd /mnt
git init
git add .
git commit -m 'init project'

Note: workaround=rename เป็นการหลีกเลี่ยง bug ของ git กรณีที่ทำงานกับ sshfs

วิธีที่สองก็คือ หลีกเลี่ยงการเก็บ ตัว repository (directory .git) ไว้บน server โดยการ สร้าง repository ไว้บน local ของเรา
จากนั้นก็ใช้ environment variable GIT_DIR กับ GIT_WORK_TREE ในการ config directory ที่ถูกต้อง

sshfs pune.ingres.co.th:/srv/www/htdocs/test /mnt
cd /mnt
export GIT_DIR=/mylocalgit
export GIT_WORK_TREE=/mnt
git init
git add .
git commit -m 'init project'


วิธีที่สามก็คือ แยก repository และ working tree ที่เราทำงาน ออกจาก live directory
แล้วใช้ technic reset --hard ในการ sync ข้อมูลแทน

#สร้าง git repository

mkdir myproject
cd myproject
git init
...
git commit -m 'my project'

#เมื่อต้องการ sync project กับ remote file บน host

sshfs pune.ingres.co.th:/srv/www/htdocs/test /mnt
cd /mnt
GIT_DIR=/myproject/.git git --work-tree=. reset --hard


วิธีที่ 1-3 workflow ไม่ค่อยเป็นทางการเท่าไร ถ้าต้องการ workflow ดูดีๆหน่อย ก็ต้องประมาณนี้

auto <<sshfs mount dir>>
+-------------+ update +==============+
! bare repo. !------->! working tree !
+-------------+ +--------------+
! ^
pull ! ! pull
v !
+--------------+
! Developer !
! working tree !
+--------------+

เริ่มด้วยการสร้าง bare repository สำหรับเก็บข้อมูลที่จะ publish ก่อน

GIT_DIR=mygit git init

สร้าง hook script ที่ชื่อ post-receive
#!/bin/sh 
WEBROOT_DIR=/srv/www/htdocs/test
GIT_WORK_TREE=${GIT_WORK_TREE-$WEBROOT_DIR}
if [ "$GIT_DIR" = "." ]; then
GIT_DIR=`pwd`
fi
while read oldrev newrev ref ; do
if [ "$ref" = "refs/heads/master" ]; then
echo "Updating $GIT_WORK_TREE"
echo "Using $ref, now at $newrev"
if [ ! -d "$GIT_WORK_TREE" ]; then
mkdir "$GIT_WORK_TREE"
fi
cd $GIT_WORK_TREE
git --work-tree=$GIT_WORK_TREE reset --hard $ref
fi
done

Note: ตัว script ลอกมาจาก presentation ของ Jon Loeliger

จากนั้นในฝั่ง working copy ของเรา ก็ระบุ remote branch ไว้ด้วย
เมื่อไรก็ตามที่ต้องการ publish content ก็ให้ push ไปที่ remote branch นั้น

mkdir myproject
cd myproject
git init
git add .
git commit -m 'bla bla'

# add bare repo to remote list
git remote add origin /path/to/bare/repo

# เมื่อเราสั่ง push
# directory ที่กำหนดไว้ใน WEBROOT_DIR ก็จะ update ให้โดยอัตโนมัติ

Related link from Roti