2012/09/13

Git + Subversion = 247

Өнөөдөр энэ хоёрыг хэрэглэдэггүй програм хөгжүүлдэг байгууллага гэж байхгүй байхаа. Ихэнх дунд болон том албан байгууллагууд голдуу Subversion дээр бичсэн програмаа засаж хянадаг шиг санагддаг юм. Тэдэнд шинэ гарсан програмыг шууд хэрэгжүүлэх зорилго болон хүсэл байдаггүй. Тэдний нэг нь миний ажлын газар. Олон жил програм бичиж байгаа зарим нөхдүүд бол Git ийг ерөөсөө сонирхохгүй, харин дассан сурсан Subversion дээрээ л ажлаа хийж мөнгөө авч байвал болох нь тэр :) Зарим нь Git ийн төвлөрсөн сервергүй тархсан зохион байгуулалт нь бүр таалагддаггүй тул нэг сервер дээр төвлөрсөн Subversion ийг илүүд үзэх нь ч бий. Git ийг мэдээж нэг сервер дээр төвлөрсөн мэт зохион байгуулж болох боловч clone гэсэн тушаал нь зарим дарга нарт ерөөсөө таалагддаггүй байх. Гэвч би удаан хугацааны туршид ажил дээрээ бараг ганцаараа git хэрэглэж байгаа нэгэн. Нэгэнт ажлынхнаас хэн нь ч тоохгүй байгаа учраас тусгай сервер гаргуулах тухай санах ч хэрэггүй тул өөрийнхөө машин дээрээ л дотоод судал үүсгэж болсон бүтээгдэхүүнээ экспортлож Subversion сервер лүү нийлүүлсээр өдий хүрсэн юм. Git ийн хамгийн чухал давуу тал бол өөртөө хуулбарласан (clone) судал дээрээ дурын салбар нээж хэдэн ч төрлийн хэлбэрээр туршилт хийж болох бөгөөд тэр болгоныг дээш сервер лүү илгээх шаардлагаггүй тул програм бичиж байгаа хүндээ харьцангуй эрх чөлөөтэй байгаа юм шиг санагддаг. За гэтэл саяхан нэг сервер хариуцдаг нөхөр надад git сервер тохируулж өгье гэв. Дандаа дотоод машин дээрээ судлуудаа удирдаж байх нь эрсдэл ихтэй тул бөөн баяр болоод эхний ээлжинд ssh холболтоор судлаа хуулбарладаг болгоё гэж хэлэв. Гэтэл бусад хэрэглэе гэсэн хүн болгон тэр сервер лүү хандах 22 дугаар портыг нээлгэх шаардлагатай бөгөөд томоохон байгууллага дээр firewall хариуцсан нөхдүүд сервер лүү тэр болгон порт нээлгэх тийм дуртай биш, тэгэхээр байсан ч хөөрхөн дамжлага дамждаг болохоор бүтэхгүй болов. Онгорхой байдаг хоёр порт нь 80, 443 хоёр бөгөөд энүүн дээр дуртай хүн болгон хуулбарлаад байдаггүй бас хэн нь ямар судлыг хуулбарлаж болох болохгүй гэсэн тохиргоотой болгох гэдэг бас амархан эд биш юм байна. Тэгээд ч өнөөх админ нөхөр маань тэр болгоныг тохируулж арчлаад байх хүсэлгүй шинжтэй болоод явчихав. Ингэж байтал уржигдар интернэтээр хэсэж байгаад миний гачлантай яг адилхан зовлонг амар шийдлээр туулж давсан нэгний блогийг олж харлаа. Git гаргасан газраас Subversion тай зохицож болох git-svn модуль байдаг бөгөөд Subversion дээрх кодыг svn хэрэглэгч мэт татаж аваад дотоод машин дээрээ git судал болгож ажиллаад, буцааж сервер лүүгээ svn судал болгож нийлүүлдэг юм байна. Ингээд ажиллах дараалал нэг иймэрхүү байх юм:

Судлаа тохируулах

Эхлээд Subversion судлаас кодоо татаж авна:

git svn clone -s http://серверийн_хаяг/миний_subversion_судал дотоод_сан

-s гэсэн дагаварыг, хэрэв таны код subversion-ий стандар сангуудаас (trun/, branches/ мөн tags/) бүтсэн бол өгөх ёстой. Хэрэв тийм зохион байгуулалтгүй бол уг дагаваргүйгээр тушаалаа өгөх хэрэгтэй. Тушаалын үр дүнд нь таны дотоод_сан гэсэн өөрийн дотоод git судал үүссэн байх юм. Энд зарим зүйлийг дурдах нь зүйтэй. Эхлээд, Subversion судал дээр байгаа хоосон сан болгоныг git судал дээр харуулдаггүй. Git бол файлын бүтцийн өөрчлөлтийг хянадаг болохоос файлыг хянадаггүй юм. Дараагийн зүйл бол, svn:ignore тушаалаар алгасах ёстой файлуудыг git алгасдаггүй. Алгасах файлын жагсаалтыг үүсгэхдээ судлынхаа эхэнд очиж байгаад дараах тушаалыг өгнө:

git svn show-ignore > .gitignore

Үүнтэй ижил үр дүнд хүргэдэг 'git svn show-ignore >> .git/info/exclude' тушаалыг та хэрэглэдэг байж магадгүй. Ялгаа нь юундаа байдаг вэ гэхээр, өмнөх аргаар алгасах файлуудаа судал дээрээ хянаад яваад байж болдогт байдаг байна. Нэг ёсондоо Subversion руу буцааж нийлүүлэх үед алгасах файлын жагсаалт хамт нийлүүлэгдэх бөгөөд дараа нь өөр хэрэглэгч судал татаж авсаны дараа ийм тушаал өгөх шаардлагаггүй болж байгаа юм.

Салбар үүсгэх


Git ийн хамгийн сайн чанар бол буулгаж авсан судал дээрээ дурын салбарууд үүсгэж өөрчлөлт хийж болох бөгөөд үүнийг сервер дээрх судалд нөлөөлөхгүй хийж болдогт байдаг. Ингээд дараах тушаалаар татаж авсан судлаасаа юмуу эсвэл үүсчихсэн байгаа салбараас салбар үүсгэж болдог:

git checkout -b шинэ-салбарын-нэр [хуучин-салбарын-нэр]

хэрэв салбараас дахин салбарлах гээгүй бол хуучин-салбарын-нэрийг бичихгүй байх хэрэгтэй. Үүсгэсэн салбаруудын жагсаалтыг git branch тушаалаар харна. Гэхдээ Subversion сервер дээрх салбаруудыг харуулахгүй байвал битгий гайхаарай. Өмнөх тушаал бол зөвхөн дотоод салбаруудыг харуулдаг юм. Сервер болон дотоод бүх салбарлалтуудыг харуулахдаа git branch -a гэх бөгөөд энэ жагсалтанд Subversion сервер дээрх branch болоон tag ууд бүгд ордог.

Файл засварлах, өөрчлөлт хийх


Ингээд салбар үүсгэчихсэн бол дараах ажиллагаанууд бараг Subversion-тай адилхан. Шинээр файл үүсгээд тэрийгээ хянахаар бол git add <шинэ-файл> гэх бөгөөд файл устгахаар бол git rm <файлын-нэр> гэх ёстой. Энд git add тушаал нь угсраа үйлчилгээтэй гэдгийг анхаарах хэрэгтэй. Жишээ нь git add . гэсэн тохиолдолд тушаал өгсөн санд байгаа бүх файл болон сангуудыг доторх файл сантай нь нэмдэг. git rm тушаал нь бас адилхан угсраа үйлчилгээтэй хийдэг бөгөөд ингэхийн тулд -r гэсэн дагавар нэмэх хэрэгтэй. Аль хэдийн судалд нэмэгдчихсэн файлыг та git add тушаалаар гарсан өөрчлөлтийг нь оруулах зориулалтаар хэрэглэж бас болно. Жишээ нь нэг файлын өөрчлөлтийг оруулахдаа git add <файлын-нэр> гэх юмуу git add . гэж бүх файлуудад гарсан өөрчлөлтүүдийг нэмдэг. Гэхдээ өөрчлөлтөө оруулж болдог бас нэг нарийн арга байдаг юм байна:

cnixon$ git add --patch
diff --git a/config/environment.rb b/config/environment.rb
index f3a3319..34ece3a 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -19,6 +19,8 @@ Rails::Initializer.run do |config|
# Only load the plugins named here, in the order given. By default, all plugins in vendor/plugins are loaded in alphabetical order.
# :all can be used as a placeholder for all plugins not explicitly named.
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
+
+ config.gem 'chronic'
# Add additional load paths for your own custom dirs
# config.load_paths += %W( #{RAILS_ROOT}/extras )
Stage this hunk [y/n/a/d/?]? y
<stdin>:9: trailing whitespace.
warning: 1 line adds whitespace errors.


Та хэрэв git add --patch тушаал өгөх юм бол файлуудад хийгдсэн өөрчлөлт бүрийг танаас нэмэх үү үгүй юу гэж асуудаг байна. Ингэснээр танд өөрчлөлт бүрийг нэмэх нэмэхгүйгээ шийдэх сайхан боломж үүсдэг байх юм. Энэ тушаалаар файл хийсэн өөрчлөлтүүд дарааллаараа харагдах тул хэрхэн өөрчлөгдсөнийг харах сайхан боломж үүсдэг байна.

Өөрчлөлтөө буцаах


Subversion дээр бараг хамгийн түрүүнд миний сурсан тушаал бол git revert. Git дээр арай өөр. Хэрэв файлын өөрчлөлтөө салбар луугаа нийлүүлээгүй байгаа тохиолдолд:

git checkout <файлын-нэр>

Ингэснээр файлыг анх салбарласан юмуу судлаас татаж авсан орчинд буцаадаг. Хэрэв та файлынхаа өөрчлөлтийг салбар луугаа нийлүүлчихсэн хойноо буцаахыг хүсэх юм бол:

git reset HEAD <файлын-нэр>

Өөрчлөлтөө салбарлуугаа нийлүүлэх


Хийсэн өөрчлөлтөө жижиг тайлбар тексттэй нэмэхийн тулд git commit -m "Тайлбар текст" гэж тушаана. Хэрэв олон файл нэмэхээр бол git commit -am "Тайлбар текст" гэх хэрэгтэй.

Салбараа эх судал (master)-тайгаа нийлүүлэх


За ингээд та нэг салбар үүсгээд тэрэндээ гайхамшигтэй үр дүнд хүрчихсэн гэж бодъё. Одоо үүнийгээ эх судал master луугаа нийлүүлэх хэрэгтэй:

git checkout master
git merge <салбарын-нэр>


Эхний тушаалаар master судал руугаа очдог бөгөөд тэндээсээ хоёр дахь тушаалаар салбарыг master луугаа нийлүүлдэг. Үр дүнд нь conflict гэж хэлэгддэг нэг файлын нэг байрлал дээр хоёр хувилбарын өөр өөр өөрчлөлтүүд байгаа мөргөлдөөн үүсэж магадгүй. Энэ тохиолдолд та мөргөлдсөн газар болгон дээр гараар засварлаж янзлаад git add тушаалаар өөрчлөлтөө нэмж git commit тушаалаар master судал руугаа нийлүүлэх хэрэгтэй. Энэ нийлүүлэлтийн үр дүнд салбар дээр хийгдсэн бүх өөрчлөлтийн тэмдэглэлүүд master луу давхар нийлүүлэгддэг. Өмнө дурдаж байснаар, git дээр та төв сервер лүү хандалгүйгээр хэд л бол хэдэн удаа файл нэмж commit тушаалаар нийлүүлэлт хийх гэх мэт өөрчлөлтүүдийг хийж болох бөгөөд энэ болгонд тэмдэглэл хийгдсэн байдаг юм. Энэ бүх тэмдэглэлүүдийг оруулахгүйгээр master дээр зөвхөн нэг л удаагийн том өөрчлөлт хийж нийлүүлж байгаа юм шиг нийлүүлье гэвэл --squash дагаварыг нэмж өгөх хэрэгтэй.

git merge --squash <салбарын-нэр>

Төв сервер дээрх өөрчлөлтийг татаж авах, өөрийн өөрчлөлтөө Subversion руу нийлүүлэх


Ингээд энэ бүх өөрчлөлтөө төв Subversion сервер лүү илгээхээс өмнө сервер дээр гарсан байж болох өөрчлөлтүүдийг эхлээд заавал татах хэрэгтэй:

git svn rebase

Энэ тушаалаар төв сервер дээр гарсан байж болзошгүй бүх өөрчлөлтүүдийг таны дотоод судал дээр нийлүүлээд дараа нь таны дотоод судал дээрх өөрчлөлтүүдийг оруулдаг. Өөрөөр хэлбэл таны өмнө татаж авсан орчин дээр нь гарсан өөрчлөлтүүдийг нэмчихээд дараа нь таны хийсэн өөрчлөлтүүдийг нэмж оруулдаг юм. Ингээд бүх зүйл зүгээр бол төв сервер лүүгээ дараах тушаалаар илгээнэ:

git svn dcommit

Git ийн маш олон тушаалууд байдгаас өдөр тутам хэрэглэгддэг цөөхнийг нь энд дэлгэлээ. Миний дуурайж хялбаршуулж бичсэн эх сурвалжийн нөхөр бас өөр хүмүүсээс хялбарчилсан аргачлалуудын жагсаалт гаргасан бас нэг блог хуудас бичсэн байдаг бөгөөд тэндээс та мэдлэгээ цааш нь үргэлжлүүлээрэй.

No comments:

Post a Comment