در ابتدا تعریفی از سیستم کنترل نسخه (VCS) داشته باشیم:
سیستمی که امکان دسترسی توسعه دهندگان به تاریخچه ی مجموعه ای از فایل ها را می دهد، این مجموعه فایل می تواند کدهای برنامه نویسی یک پروژه نرم افزاری یا هر نوع فایل دیگری باشد. چنین سیستمی علاوه بر این، می تواند از ساخت نسخه های مختلف از این مجموعه فایل ها پشتیبانی کند. هر نسخه، یک تصویر از فایل ها در یک نقطه زمانی مشخص تهیه می کند و به شما اجازه می دهد تا بین این نسخه ها جا به جا شوید. این نسخه ها در یک محل خاص به نام مخزن ذخیره می گردد.
در ادامه مطلب همراه من باشید.
برای مثال ممکن است شما یک مجموعه از فایل ها را به دو روز قبل برگردانید یا برای ویژیگی های آزمایشی بین نسخه های مختلف فایل هایتان جا به جا شوید. فرآیند ساخت نسخه های مختلف (snapshot) در مخزن در تصویر زیر نشان داده شده است. توجه داشته باشید که تصویر زیر مربوط به Git می باشد و نسخه های دیگر سیستم کنترل نسخه مانند: سیستم نسخه های هم زمان Concurrent Versions System از فایل ها، Snapshot ایجاد نمی کند اما جزئیات فایل را ذخیره میکند.
VCS معمولا برای ردیابی تغییرات در فایل های متنی استفاده می شود. برای مثال این فایل های متنی می توانند کد زبان های برنامه نویسی یا فایل های پیکربندی باشند. البته که سیستم های کنترل نسخه محدود به فایل های متنی نیستند و می توانند انواع دیگر فایل ها را پوشش دهند. برای مثال ممکن است شما از VCS برای ردیابی نسخه های مختلف فایل png استفاده کنید.
سیستم کنترل نسخه محلی
یک سیستم کنترل نسخه محلی، کپی های فایل ها را نگهداری می کند. این روش به سادگی ایجاد کپی دستی از فایل های مربوطه می باشد. به عنوان مثال کاربر فایل ها را به صورت جداگانه در پوشه های مختلف قرار می دهد.
سیستم کنترل نسخه متمرکز
سیستم کنترل نسخه متمرکز یک ابزار نرم افزاری سمت سرور است که نسخه های مختلف از فایل ها را ذخیره و مدیریت می کند. یک توسعه دهنده می تواند یک نسخه مشخص از فایل را از سرور مرکزی به سیستم خودش کپی کند.
هر دو روش محلی و متمرکز یک اشکال دارند و آن اینکه یک نقطه شکست دارند. در یک سیستم کنترل نسخه محلی کامپیوتر شخصی و در سیستم های کنترل نسخه متمرکز، ماشین سرور نقطه شکست می باشد. هر دو سیستم باعث سخت تر شدن کار به صورت موازی روی ویژیگی های مختلف می شود.
سیستم های کنترل نسخه توزیع شده
در یک سیستم کنترل نسخه توزیع شده هر کاربر یک کپی محلی کامل از مخزن روی کامپیوتر شخصی خود دارد. کاربر می تواند یک مخزن موجود را کپی کند. این فرآیند کپی کردن معمولا Cloning نامیده می شود و مخزن حاصل clone نامیده می شود.
هر clone شامل یک تاریخچه کامل از فایل ها می باشد و یک مخزن clone کارایی همانند مخزن اصلی دارد.
هر مخزن می تواند با انتقال تغییرات، نسخه های فایل ها را با دیگر مخازن مبادله کند. این کار معمولا از طریق مخزن اجرا شده روی سرور که بر خلاف ماشین محلی همیشه آنلاین می باشد انجام می شود. معمولا، یک سرور مرکزی برای نگهداری یک مخزن وجود دارد اما هر مخزن clone شده، یک نسخه کپی کامل از مخزن می باشد. تصمیم گیری در مورد این موضوع که کدامیک از کپی ها به عنوان مخزن سرور اصلی در نظر گرفته شوند قراردادی می باشد.
Git چیست؟
Git رایج ترین طرح پیاده سازی شده سیستم کنترل نسخه توزیع شده می باشد.
Git در سال 2005 توسط Linus Torvalds ایجاد شده است که امروزه توسط بسیاری از پروژه های متن باز مانند: تیم های توسعه دهنده اندروید و eclipse و بسیاری از سازمان های تجاری استفاده می شود.
هسته Git با استفاده از زبان برنامه نویسی C ایجاد شده است اما توسط زبان های دیگری همچون Java، Rubby و Python مجددا اجرا شده است.
مخزن (Repository) در Git
مخزن شامل تاریخچه مجموعه فایل هایی که در یک پوشه قرار گرفتند و سیسستم git در آن ایجاد شده است می باشد. در Git دو نوع مخزن داریم:
- مخازن :bare این نوع مخازن در سرور برای اشتراک تغییرات توسعه دهندگان مختلف در نظر گرفته می شود. برخی مخزن ها به کاربر اجازه ویرایش محلی فایل ها و ایجاد نسخه های جدید بر پایه این تغییرات در مخزن را نمی دهند. این مخازن بیشتر در زمانی استفاده می شود که مخزن به صورت از راه دور برای دریافت تغییرات توسعه دهندگان ایجاد شده است.
- مخازن : non-bare این مخازن به شما اجازه می دهند که تغییرات جدید را از طریق ویرایش فایل ها اعمال و نسخه های جدید در مخزن ایجاد کنید. اگر شما در زمان عملیات clone پارامتری را مشخص نکنید به صورت پیش فرض این نوع در نظر گرفته می شود.
درخت کار
در مخازن محلی non-bare درخت کار وجود دارد و شامل تمامی فایل های موجود در پوشه است.
کاربر می تواند در درخت کار، فایل ها را ایجاد یا ویرایش و حذف کند. یک فایل در درخت کار یک مخزن Git می تواند حالت های مختلفی داشته باشد. این حالت ها در زیر شرح داده شده است:
Untracked: فایل توسط مخزن Git ردیابی یا شناخته نشده است. این بدین معنی است که فایل هیچگاه stage یا commit نشده است.
Tracked: فایل commit شده اما stage نشده است.
Staged: قرار است در commit بعدی گنجانده شود.
Dirty/modified: فایل تغییر کرده است اما تغییرات stage نشده است.
اضافه کردن تغییرات به مخزن توسط Stage و Commit کردن تغییرات
پس از ویرایش درخت کاری خود باید دو کار را برای اعمال این تغییرات در مخزن محلی خود انجام دهیم:
- اضافه کردن تغییرات انتخابی با دستور git add به محیط stage (که index هم نامیده می شود).
- commit کردن تغییرات stage به مخزن Git با استفاده از دستور git commit.
این فرآیند در تصویر زیر نمایش داده شده است.
دستور git add یک تصویر از فایل های مشخص شده را در محیط Stage ذخیره می کند. که به ما اجازه می دهد به تدریج فایل ها را ویرایش و آنها را Stage کنیم. ویرایش و Stage کردن تا زمانی که تغییرات مورد انتظار حاصل نشود می تواند ادامه پیدا کند.
یک شی commit بیانگر نسخه تمامی فایل های شناسایی شده مخزن در زمان ایجاد commit می باشد. شی Commit شامل:
- شناسه Commit که با الگوریتم SHA-1 کد شده است.
- شناسه Commit در درخت (Commit ها ساختار درختی دارند).
- ناشر Commit
- Commit کننده
- پیام Commit
مفهوم branch
Git از branching به صورتی که بتوانیم روی نسخه های مختلفی از مجموعه فایل های خود کار کنیم، پشتیبانی می کند. branch ها به ما اجازه می دهد تا بین نسخه های مختلف جا به جا شویم به طوری که بتوان روی تغییرات به صورت کاملا مسقل از هم کار کرد.
برای مثال اگر شما بخواهید یک ویژیگی جدید توسعه دهید، می توانید یک branch جدید ایجاد کنید و تغییرات را در این branch اعمال کنید. این تغییرات هیچ تاثیری در فایل های شما در دیگر branch های مخزن نخواهد داشت. برای مثال شما می توانید روی یکbranch به نام production برای رفع باگ به صورت کاملا مستقل کار کنید و روی یک branch دیگر به نام newfeature برای پیاده سازی ویژیگی های جدید کار کنید.
Git از ترکیب تغییرات از branch های مختلف پشتیبانی می کند.
نصب Git:
سیستم عال لینوکس Ubuntu و Debian:
sudo apt-get install git
سیستم عامل لینوکس CentOS:
yum install git
سیستم عامل ویندوز:
نسخه ویندوز Git در صفحه دانلود Git موجود است.
راه اندازی git:
در ابتدا باید نام کاربری و ایمیل خود را با استفاده از دستور زیر در git پیکربندی کنید.
# configure the user which will be used by Git
# this should be not an acronym but your full name
git config --global user.name "Firstname Lastname"
# configure the email address
git config --global user.email "your.email@example.org"
سپس با استفاده از دستور زیر git را طوری تنظیم می کنیم که در زمان pull کردن تغییرات، commit ها را ادغام نکند.
git config --global branch.autosetuprebase always
در این قسمت توجه داشته باشید که بعضی از دستورات مانند: دستورات کار با فایل و ساخت پوشه مخصوص لینوکس هستند. شما این دستورات را با دستورات سیستم عامل خود جایگزین کنید. comment ها هم که قبل از دستورات با # نشانه گذاری شده اند دستورات را شرح می دهد.
ساخت یک پوشه:
دستورات زیر یک پوشه خالی ایجاد می کند که بعدا شامل درخت کار و مخزن Git خواهد بود.
# switch to the home directory
cd
# create a directory and switch into it
mkdir repo01
cd repo01
# create a new directory
mkdir datafiles
دستور cd: از این دستور در لینوکس برای تغییر پوشه جاری استفاده می شود.
دستور mkdir: از این دستور برای ایجاد پوشه استفاده می شود.
ساخت مخزن Git جدید:
از دستور git init برای ساخت یک مخزن git در پوشه جاری استفاده می کنیم. برای git مهم نیست که پوشه ای که با آن شروع می کنیم خالی است یا شامل فایل است.
هر مخزن git در پوشه .git که مخزن در آن ایجاد شده است ذخیره می شود. این پوشه شامل تاریخچه کامل مخزن و فایل .git/config می باشد.
# you should still be in the repo01 directory
cd ~/repo01
# initialize the Git repository
# for the current directory
git init
همه فایل های داخل پوشه مخزن، به غیر از پوشه .git برای یک مخزن git درخت کاری هستند.
ایجاد محتوای جدید:
از دستورات زیر برای ایجاد فایل و محتوای جدید استفاده می کنیم.
# switch to your Git repository
cd ~/repo01
# create an empty file in a new directory
touch datafiles/data.txt
# create a few files with content
ls > test01
echo "bar" > test02
echo "foo" > test03
دستور touch: برای ایجاد فایل از آن استفاده می شود.
دستور echo: رشته ورودی (که در کد بالا bar و foo می باشد) را در فایل می نویسد.
مشاهده وضعیت جاری مخزن:
دستور git status وضعیت درخت کار موجود را نمایش می دهد. به عنوان مثال نشان می دهد که:
- کدام فایل ها تغییر کرده اند.
- چه فایل هایی با یکدیگر ناسازگاری دارند.
- کدام فایل ها stage شده اند و چه فایل هایی هنوز stage نشده اند.
دستور زیر را اجرا می کنیم.
git status
خروجی این دستور به صورت زیر خواهد بود.
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
datafiles/
test01
test02
test03
nothing added to commit but untracked files present (use "git add" to track)
انتقال تغییرات به محدوده Stage:
پس از انجام تغییرات در فایل ها، باید با استفاده از دستور git add فایل هایی که می خواهیم آنها را به مخزن commit کنیم، به محدوده Stage منتقل کنیم. برای انتقال فایل ها دو گزینه پیش روی ماست. اولی استفاده از گزینه . می باشد که تمامی فایل ها را به محدوده Stage منتقل می کند (gir add .) و دومی با وارد کردن آدرس فایل به صورت منفرد فایل را به محدوده Stage منتقل می کند.
# add all files to the index of the Git repository
git add .
پس از اجرای دستور، برای مشاهده وضعیت جاری درخت کار دستور git status را دوباره اجرا کنید. خروجی به صورت زیر نمایش داده می شود.
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: datafiles/data.txt
new file: test01
new file: test02
new file: test03
تغییر فایل هایی که Stage شده اند:
در مواقعی که شما یکی از فایل های stage شده را قبل از commit تغییر می دهید، باید این تغییرات را جهت commit کردن دوباره به محدوده stage منتقل کنید. چون git یک تصویر از محتوای فایل stage شده ایجاد می کند، همه تغییرات جدید باید دوباره stage شوند.
# append a string to the test03 file
echo "foo2" >> test03
# see the result
git status
دوباره دستور git status را اجرا می کنیم و وضعیت درخت کار یه صورت زیر خواهد بود.
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: datafiles/data.txt
new file: test01
new file: test02
new file: test03
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: test03
ملاحظه می کنید که فایل test03 که به محدوده stage منتقل شده بود و ما در ادامه "foo2" را به آن اضافه کردیم به عنوان فایل Stage نشده در خروجی git status نمایش داده شده است.
اضافه کردن تغییرات جدید به محدوده Stage:
# add all files to the index of the Git repository
git add .
دوباره دستور git status را برای مشاهده وضعیت جاری اجرا می کنیم.
git status
خروجی دستور به شکل زیر خواهد بود.
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: datafiles/data.txt
new file: test01
new file: test02
new file: test03
Commit تغییرات Stage شده به مخزن:
پس از اضافه کردن تغییرات فایل ها به محدوده Stage در Git، می توانید با استفاده از دستور git commit آنها را به مخزن Git خود Commit کنید. این دستور یک شی Commit جدید ایجاد می کند که متشکل از تغییرات Stage شده در مخزن به همراه اشاره گر HEAD جدید که به Commit جدید اشاره می کند می باشد. پارامتر m- به ما اجازه می دهد تا پیام Commit را مشخص کنیم. اگر این پارامتر را در نظر نگیریم، ویرایشگر پیش فرض سیستم اجرا شده و می توانیم در این ویرایشگر پیام مورد نظر را وارد کنیم.
# commit your file to the local repository
git commit -m "Initial commit"
مشاهده تاریخچه Commit در Git:
عملیات های که در git انجام می دهیم در مخزن git محلی در پوشه git ثبت می شود، تمامی فایل ها توسط commit به این مخزن اضافه می شود. با این حال برای مشاهده تاریخچه مخزن می توانیم از دستور git log استفاده کنیم.
# show the Git log for the change
git log
نتیجه دستور بالا به صورت زیر خواهد بود.
commit 30605803fcbd507df36a3108945e02908c823828
Author: Lars Vogel <Lars.Vogel@vogella.com>
Date: Mon Dec 1 10:43:42 2014 +0100
Initial commit
مشاهده تغییرات یک Commit:
از دستور git show برای مشاهده تغییرات یک commit استفاده می شود. اگر اشاره گر یک commit را به عنوان سومین پارامتر برای دستور git show قرار دهیم، تغییرات Commit مورد نظر را نمایش می دهد، در غیر اینصورت (اشره گری را وارد نکنیم) از اشاره گر HEAD استفاده می شود (که به آخرین Commit اشاره می کند).
مرور ساختار پوشه حاصل:
پس از انجام عملیات شرح داده شده ساختار پوشه به شکل زیر خواهد بود.
حذف فایل ها:
در صورتی که یک فایل را از درخت کار خود حذف کنیم، می توانیم با استفاده از دستور . git add، حذف فایل را به محدوده Stage اعلام کنیم.
# remove the "test03" file
rm test03
# add and commit the removal
git add .
# if you use Git version < 2.0 use: git add -A .
git commit -m "Removes the test03 file"
دستور rm: از این دستور برای حذف فایل در لینوکس استفاده می شود.
بازگرداندن تغییرات فایل:
از دستور git checkout برای بازنشانی فایل های ردیابی شده (فایل هایی که stage یا commit شده اند) به آخرین commit یا stage استفاده می شود. این دستور تغییرات فایل در درخت کار را حذف می کند. این دستور نمی تواند به فایل هایی که هنوز stage یا commit نشده اند اعمال شود. در کد زیر ما فایل test02 و unwantedfile.txt را تغییر می دهیم. سپس با استفاده از git status وضعیت مخزن را چک می کنیم. پس از آن با استفاده از دستور git checkout test02 تغییرات اعمال شده در فایل را بر می گردانیم (فایل به صورت قبل از تغییر بر می گردد).
echo "useless data" >> test02
echo "another unwanted file" >> unwantedfile.txt
# see the status
git status
# remove unwanted changes from the working tree
# CAREFUL this deletes the local changes in the tracked file
git checkout test02
# unwantedstaged.txt is not tracked
حال اگر دستور git status را دوباره اجرا کنیم، هیچ تغییری وجود نخواهد داشت.
On branch master
nothing to commit, working directory clean
اصلاح تغییرات commit:
دستور git commit –amend این امکان را به ما می دهد تا تغییرات آخرین commit را دوباره انجام دهیم. این دستور یک commit جدید با تغییرات تنظیم شده ایجاد می کند.
فرض کنید در پیام آخرین commit اشتباهی رخ داده باشد و قصد داشته باشیم تا دوباره پیام را به شکل صحیح وارد کنیم. برای این منظور از دستور git commit --amend به صورت زیر استفاده می کنیم.
# assuming you have something to commit
git commit -m "message with a tpyo here"
# amend the last commit
git commit --amend -m "More changes - now correct"
چشم پوشی git از فایل ها با استفاده از فایل gitignore.:
گاهی نیاز داریم تا تغییرات اعمال شده در درخت کاری ما توسط Git ردیابی نشود. برای این منظور فایل gitignore. را به صورت زیر ایجاد می کنیم.
cd ~/repo01
touch .gitignore
echo ".metadata/" >> .gitignore
echo "doNotTrackFile.txt" >> .gitignore
در کد بالا یک فایل به نام gitignore. در پوشه repo01 ایجاد شده است و دستور چشم پوشی Git از فایل doNotTrackFile به صورت زیر در این فایل قرار گرفته است.
.metadata/
doNotTrackFile.txt
ایده خوبی خواهد بود اگر فایل gitignore. را هم به مخزن Commit کنیم.
# add the .gitignore file to the staging area
git add .gitignore
# commit the change
git commit -m "Adds .gitignore file"
git |