در پانزده سال کار با Git، یک الگو را در همه تیم‌ها دیده‌ام: توسعه‌دهنده‌ای که Git را به‌طور کامل بلد است، ده برابر سریع‌تر از کسی است که فقط چهار دستور پایه را می‌داند. تفاوت در تعداد دستورات نیست؛ در شناخت لحظه‌ای است که هر دستور باید به‌کار بیاید. این مقاله، فهرستی است که اگر امروز بخواهم به یک توسعه‌دهنده تازه‌کار در تیم خودم بدهم، دقیقاً همین خواهد بود — نه همه دستورات Git، بلکه همان‌هایی که هر روز به آن‌ها نیاز پیدا می‌کنید.

چرا تسلط بر دستورات Git تفاوت می‌سازد؟

Git یک سیستم کنترل نسخه توزیع‌شده است که در سال ۲۰۰۵ توسط لینوس توروالدز برای مدیریت هسته لینوکس ساخته شد. برای آشنایی با تاریخچه و مدل داخلی آن، صفحه Git در ویکی‌پدیا نقطه شروع خوبی است. اما آنچه در عمل تفاوت می‌سازد، تسلط بر یک فهرست مشخص از دستورات است که در سه سطح دیده می‌شود.

در سطح اول، توسعه‌دهنده‌ای که فقط چهار دستور پایه را می‌داند، برای هر کار ساده‌ای باید از اینترنت کمک بگیرد. در سطح دوم، کسی که فهرست کامل دستورات ضروری را بلد است، در لحظه می‌داند کدام دستور درست است و چه اثری دارد. و در سطح سوم، توسعه‌دهنده‌ای که مدل ذهنی Git را درک کرده، می‌تواند دستورات را ترکیب کند و سناریوهای جدید را بدون جستجو حل کند. این مقاله شما را از سطح اول به سطح دوم می‌برد.

اگر با مفاهیم پایه Git آشنا نیستید و می‌خواهید از صفر شروع کنید، آموزش گام‌به‌گام Git از commit تا merge نقطه شروع درست است. برای مرجعی که در حال خواندنش هستید، پیش‌فرض این است که با مفاهیمی مثل commit، برنچ و staging area آشنایید.

تفاوت یک توسعه‌دهنده حرفه‌ای با یک تازه‌کار در Git، تعداد دستوراتی که بلد است نیست؛ سرعتی است که در انتخاب دستور درست پیدا می‌کند. این سرعت، از تمرین منظم می‌آید.

دستورات پیکربندی و راه‌اندازی

پیش از هر کاری، Git باید بداند شما چه کسی هستید. این اطلاعات به‌عنوان نویسنده هر commit ثبت می‌شود و در تاریخچه پروژه باقی می‌ماند. سه تنظیم اصلی را باید یک‌بار انجام دهید تا در همه پروژه‌ها اعمال شوند.

git config --global user.name "نام شما"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main

خط سوم در نسخه‌های جدید Git اضافه شده و نام پیش‌فرض برنچ اصلی را از master به main تغییر می‌دهد. برای بررسی اینکه پیکربندی درست اعمال شده است یا نه، از دستور زیر استفاده کنید:

git config --list

سه تنظیم دیگر که در پروژه‌های واقعی مفید هستند: فعال‌سازی رنگ خروجی، تعیین ویرایشگر پیش‌فرض و تنظیم رفتار pull. برای تنظیم ویرایشگر:

git config --global core.editor "code --wait"
git config --global pull.rebase false

خط دوم به Git می‌گوید که هنگام pull، از merge استفاده کند نه rebase. اگر تیم شما از rebase استفاده می‌کند، این را به true تغییر دهید. اگر با مفاهیم rebase و merge آشنا نیستید، برنچ در git این تفاوت‌ها را با جزئیات بررسی کرده است.

دستورات پایه: add، commit، status، log و diff

git init و git clone

برای شروع یک مخزن جدید از صفر، از git init استفاده کنید. این دستور یک پوشه مخفی به نام .git در مسیر جاری می‌سازد که تمام اطلاعات مخزن در آن ذخیره می‌شود. برای کپی کردن یک مخزن موجود از سرور راه دور، از git clone استفاده کنید.

git init
git clone https://github.com/user/repo.git

git add

دستور add، فایل‌ها را از working directory به staging area منتقل می‌کند. staging area یک مفهوم کلیدی در Git است که به شما اجازه می‌دهد تغییرات انتخابی را کامیت کنید. سه شکل رایج این دستور:

git add file.php
git add src/
git add -A

خط اول یک فایل را اضافه می‌کند، خط دوم تمام فایل‌های یک پوشه، و خط سوم تمام تغییرات پروژه را. در پروژه‌های واقعی، من معمولاً از git add -p استفاده می‌کنم که به‌صورت تعاملی اجازه می‌دهد هر بخش از تغییرات را جداگانه stage کنید. این تکنیک، برای ساختن commit‌های معنادار حیاتی است.

git status

دستور status یکی از پرکاربردترین دستورات Git است. این دستور وضعیت فعلی فایل‌ها را نشان می‌دهد: کدام فایل تغییر کرده، کدام stage شده و کدام track نشده است. اگر تازه با Git آشنا می‌شوید، توصیه من این است که این دستور را قبل و بعد از هر عملیات مهم بزنید.

git status
git status -s

خط دوم خروجی فشرده‌تری می‌دهد که در کارهای روزمره سریع‌تر قابل خواندن است.

git commit

دستور commit، تغییرات stage شده را به‌عنوان یک عکس فوری در تاریخچه ثبت می‌کند. هر commit شامل شناسه یکتا، پیام، نویسنده و زمان است. برای نوشتن پیام commit معنادار، از زمان حال امری استفاده کنید و در یک جمله توضیح دهید این commit چه چیزی را تغییر می‌دهد.

git commit -m "افزودن اعتبارسنجی ایمیل به فرم ثبت‌نام"
git commit -am "رفع باگ محاسبه مالیات"
git commit --amend

خط دوم، ترکیبی از add و commit است که فقط روی فایل‌های قبلاً tracked اعمال می‌شود. خط سوم، آخرین commit را با تغییرات جدید بازنویسی می‌کند. Amend را فقط روی commit‌هایی استفاده کنید که push نشده‌اند؛ چون تاریخچه را بازنویسی می‌کند.

git log

دستور log تاریخچه commit‌ها را نمایش می‌دهد. خروجی پیش‌فرض آن خواندنش سخت است، اما گزینه‌های زیادی برای فشرده‌سازی وجود دارد که در کارهای روزمره استفاده می‌کنم:

git log --oneline
git log --oneline --graph --all
git log -p file.php
git log --author="نام نویسنده"

خط دوم یکی از مفیدترین ترکیب‌هاست: نمایش تاریخچه به‌صورت گرافیکی، با تمام برنچ‌ها. برای بررسی تاریخچه تغییرات یک فایل خاص، از خط سوم استفاده کنید. اگر می‌خواهید ببینید چه کسی چه چیزی را تغییر داده، git blame در ادامه توضیح داده شده است.

git diff

دستور diff تفاوت بین دو حالت را نشان می‌دهد. سه شکل پرکاربرد آن:

git diff
git diff --staged
git diff HEAD~1 HEAD

خط اول تفاوت بین working directory و staging را نشان می‌دهد. خط دوم تفاوت بین staging و آخرین commit. خط سوم تفاوت بین دو commit مشخص را نمایش می‌دهد. قبل از هر commit، عادت کنید git diff --staged بزنید تا مطمئن شوید همان چیزی را کامیت می‌کنید که می‌خواهید.

دستورکاربرد اصلیمخاطب هدف
git addاضافه به stagingهمه سطوح
git commitثبت تغییرات در تاریخچههمه سطوح
git statusبررسی وضعیت فایل‌هاهمه سطوح
git logمرور تاریخچههمه سطوح
git diffمقایسه تغییراتسطح متوسط به بالا

دستورات برنچ و جابه‌جایی

برنچ در Git یکی از سبک‌ترین ساختارهای موجود است؛ فقط یک اشاره‌گر به یک commit. به همین دلیل، ساخت و حذف برنچ چند میلی‌ثانیه بیشتر طول نمی‌کشد. چهار دستور اصلی برنچ که هر توسعه‌دهنده باید بلد باشد:

git branch

این دستور برای لیست کردن، ساختن یا حذف برنچ‌ها استفاده می‌شود. سه شکل پرکاربرد:

git branch
git branch feature-login
git branch -d feature-login
git branch -D feature-login

خط اول برنچ‌های محلی را نشان می‌دهد. خط دوم یک برنچ جدید می‌سازد، بدون اینکه به آن سوئیچ کند. خط سوم برنچ را در صورت ادغام‌شده بودن حذف می‌کند و خط چهارم حتی اگر ادغام نشده باشد. از -D با احتیاط استفاده کنید؛ چون ممکن است کار از دست برود.

git switch و git checkout

در نسخه‌های قدیمی Git، git checkout هم برای جابه‌جایی برنچ و هم برای بازگردانی فایل استفاده می‌شد. از نسخه ۲.۲۳، Git دو دستور جداگانه معرفی کرده:

git switch main
git switch -c feature-login
git switch -

خط اول شما را به برنچ main منتقل می‌کند. خط دوم یک برنچ جدید می‌سازد و بلافاصله به آن سوئیچ می‌کند. خط سوم شما را به برنچ قبلی برمی‌گرداند. اگر با نسخه‌های قدیمی Git کار می‌کنید و می‌خواهید با خطاهای مربوط به checkout آشنا شوید، رفع خطاهای رایج git این سناریوها را بررسی کرده است.

git merge

دستور merge، تغییرات یک برنچ را به برنچ جاری اضافه می‌کند. قبل از merge، همیشه مطمئن شوید روی برنچ درست هستید:

git switch main
git merge feature-login
git merge --no-ff feature-login

خط سوم با پرچم --no-ff حتی در حالتی که fast-forward ممکن است، یک merge commit می‌سازد که در تاریخچه پروژه واضح‌تر است. برای پروژه‌هایی که چند توسعه‌دهنده دارند، این رویکرد شفافیت بیشتری می‌دهد. اگر با انواع merge آشنا نیستید، مرج در git این تفاوت‌ها را با جزئیات بررسی کرده است.

merge، rebase و حل تعارض

merge و rebase دو ابزار متفاوت برای یک هدف مشترک هستند: انتقال تغییرات از یک برنچ به برنچ دیگر. تفاوت اصلی در این است که merge تاریخچه را حفظ می‌کند اما rebase آن را بازنویسی می‌کند.

git rebase

rebase، commit‌های برنچ فعلی را برمی‌دارد و روی یک پایه جدید اعمال می‌کند. نتیجه، تاریخچه خطی و تمیز است، بدون merge commit‌های اضافه:

git switch feature-login
git rebase main
git rebase -i HEAD~3

خط دوم، برنچ فیچر را روی آخرین commit برنچ main اعمال می‌کند. خط سوم، سه commit آخر را به‌صورت تعاملی برای ترکیب، ویرایش یا حذف باز می‌کند. قاعده‌ای که در همه پروژه‌ها تکرار می‌کنم: هرگز برنچی که push شده را rebase نکنید؛ چون همکارانتان را در حل تعارض‌های غیرضروری گیر می‌اندازد.

git cherry-pick

اگر می‌خواهید فقط یک commit خاص را از یک برنچ به برنچ دیگر منتقل کنید، از cherry-pick استفاده کنید. این دستور در سناریوهای Hotfix بسیار مفید است:

git cherry-pick a1b2c3d

خروجی این دستور، یک commit جدید روی برنچ جاری می‌سازد که همان تغییرات را اعمال می‌کند. تفاوت آن با merge این است که فقط یک commit را منتقل می‌کند نه همه تغییرات یک برنچ.

حل تعارض

هر بار که merge یا rebase با تعارض مواجه شود، Git در فایل‌های درگیر نشانگرهایی می‌گذارد که دو نسخه متضاد را مشخص می‌کنند. سه گام برای حل:

git status
# ویرایش فایل‌های درگیر
git add path/to/conflicted-file
git commit -m "حل تعارض در فایل پرداخت"

اگر تعارض پیچیده است و وقت تصمیم ندارید، git merge --abort تمام عملیات را لغو می‌کند. این دستور شما را به حالت قبل از merge برمی‌گرداند و می‌توانید از ابتدا تصمیم بگیرید. برای سناریوهای پیشرفته‌تر، حل تعارض در git را ببینید که روش‌های مختلف را با مثال بررسی کرده است.

در حل تعارض، بزرگ‌ترین اشتباه انتخاب سریع یکی از دو طرف است. همیشه اول بفهمید چرا هر طرف این تغییر را داده و بعد تصمیم بگیرید. سرعت بدون درک، فقط بدهی فنی می‌سازد.

دستورات مخزن راه دور: clone، fetch، pull و push

git remote

دستور remote برای مدیریت مخازن راه دور استفاده می‌شود. سه شکل پرکاربرد:

git remote -v
git remote add origin git@github.com:user/repo.git
git remote set-url origin git@github.com:user/new-repo.git

خط اول لیست remote‌های موجود را نشان می‌دهد. خط دوم یک remote جدید اضافه می‌کند. خط سوم آدرس یک remote موجود را تغییر می‌دهد؛ این مورد زمانی لازم می‌شود که مخزن را منتقل کرده‌اید یا آدرس SSH را تغییر داده‌اید.

git fetch

دستور fetch، آخرین تغییرات را از مخزن راه دور می‌گیرد اما روی برنچ محلی اعمال نمی‌کند. این دستور برای بررسی امن تغییرات دیگران مفید است:

git fetch origin
git fetch --all
git fetch --prune

خط سوم برنچ‌هایی که در سرور حذف شده‌اند را از مخزن محلی هم پاک می‌کند. بدون این گزینه، برنچ‌های حذف‌شده همچنان در مخزن محلی شما باقی می‌مانند و ترتیب را به‌هم می‌زنند.

git pull

دستور pull ترکیبی از fetch و merge است. معمولاً وقتی روی یک برنچ مشترک کار می‌کنید، این دستور کافی است:

git pull
git pull --rebase
git pull origin main

خط دوم با پرچم --rebase، تغییرات را از سرور می‌گیرد و به‌جای merge، برنچ محلی را rebase می‌کند. در تیم‌هایی که تاریخچه خطی را ترجیح می‌دهند، این گزینه رایج است.

git push

دستور push، commit‌های محلی را به مخزن راه دور ارسال می‌کند. چهار شکل پرکاربرد:

git push
git push -u origin main
git push --tags
git push --force-with-lease

خط دوم یک برنچ جدید را برای بار اول push می‌کند و آن را به سرور متصل می‌کند. خط سوم تگ‌های محلی را هم push می‌کند. خط چهارم یک force push امن است که اگر کسی دیگر تغییرات مشابه را push کرده باشد، عملیات را متوقف می‌کند. از --force خالی استفاده نکنید؛ چون می‌تواند کار دیگران را از بین ببرد.

دستورات بازیابی: restore، reset، revert و reflog

بیشتر ترس تازه‌کارها از Git ناشی از نبود آشنایی با دستورات بازیابی است. در واقع، Git یکی از ابزارهایی است که به‌سختی چیزی را از دست می‌دهد، اگر بدانید کدام دستور کجاست.

git restore

این دستور برای برگرداندن تغییرات فایل‌های working directory یا staging به حالت قبلی استفاده می‌شود:

git restore file.php
git restore --staged file.php
git restore --source=HEAD~1 file.php

خط اول تغییرات فایل را از working directory پاک می‌کند. خط دوم فایل را از staging خارج می‌کند اما تغییرات را نگه می‌دارد. خط سوم فایل را به نسخه‌ای که در یک commit قبلی داشته، برمی‌گرداند. توجه: خط اول تغییرات را برای همیشه از دست می‌دهد؛ قبل از زدن آن، مطمئن شوید که نمی‌خواهید تغییرات را نگه دارید.

git reset

دستور reset برای برگرداندن برنچ جاری به یک commit قبلی استفاده می‌شود. سه حالت دارد که تفاوتشان در میزان تأثیرگذاری روی working directory و staging است:

git reset --soft HEAD~1
git reset --mixed HEAD~1
git reset --hard HEAD~1

حالت --soft commit آخر را حذف می‌کند اما تغییرات را در staging نگه می‌دارد. حالت --mixed که پیش‌فرض است، تغییرات را در working directory نگه می‌دارد. حالت --hard تمام تغییرات را پاک می‌کند. از --hard فقط وقتی استفاده کنید که مطمئن هستید می‌خواهید همه تغییرات محلی را از دست بدهید.

git revert

برخلاف reset که تاریخچه را بازنویسی می‌کند، revert یک commit جدید می‌سازد که تغییرات commit قبلی را معکوس می‌کند. این رویکرد برای بازگرداندن commit‌هایی که push شده‌اند امن‌تر است:

git revert a1b2c3d
git revert --no-commit a1b2c3d

خط دوم تغییرات را معکوس می‌کند اما به‌طور خودکار commit نمی‌زند. این گزینه برای بازگرداندن چند commit پشت سر هم مفید است؛ می‌توانید چند revert بزنید و سپس همه را در یک commit ادغام کنید.

git reflog

این دستور، تاریخچه تمام تغییرات HEAD را نشان می‌دهد، حتی تغییراتی که از تاریخچه رسمی حذف شده‌اند. reflog بیمه‌نامه شما در Git است:

git reflog
git reset --hard HEAD@{2}

یک تجربه واقعی: در پروژه‌ای، یکی از توسعه‌دهنده‌ها به‌اشتباه یک برنچ مهم را با git branch -D حذف کرد. به‌نظر می‌رسید کار از دست رفته است. اما با git reflog، commit آخر آن برنچ را پیدا کردیم و با یک دستور ساده برنچ را بازیابی کردیم. از آن روز، reflog یکی از دستوراتی است که در هر پروژه‌ای به تیم معرفی می‌کنم.

stash، tag و دستورات مدیریتی

git stash

stash یک انبار موقت برای تغییرات نیمه‌کاره است. اگر وسط کار روی یک فیچر هستید و باید سریعاً به کار دیگری بروید، stash به شما امکان می‌دهد تغییرات را کنار بگذارید:

git stash
git stash push -m "تغییرات فرم لاگین"
git stash list
git stash pop
git stash apply stash@{2}
git stash drop stash@{0}

خط اول یک stash معمولی می‌سازد. خط دوم با پیام مشخص، برای یافتن آسان‌تر در آینده. خط سوم لیست stash‌های موجود را نشان می‌دهد. خط چهارم آخرین stash را اعمال و از لیست حذف می‌کند. خط پنجم یک stash خاص را اعمال می‌کند اما در لیست نگه می‌دارد. خط ششم یک stash را حذف می‌کند.

git tag

tag برای علامت‌گذاری نقاط مهم در تاریخچه استفاده می‌شود، معمولاً برای نسخه‌های انتشار. دو نوع tag وجود دارد: lightweight و annotated. برای پروژه‌های جدی، از annotated استفاده کنید:

git tag v1.0.0
git tag -a v1.1.0 -m "انتشار نسخه پایدار"
git tag
git push origin v1.1.0

توجه کنید که tag‌ها به‌طور خودکار با push منتقل نمی‌شوند. برای ارسال یک tag به سرور، باید آن را به‌طور مشخص push کنید یا از git push --tags استفاده کنید.

git clean

دستور clean فایل‌های track نشده را از working directory حذف می‌کند. این دستور برای پاکسازی پروژه از فایل‌های موقت مفید است اما باید با احتیاط استفاده شود:

git clean -n
git clean -f
git clean -fd

خط اول یک پیش‌نمایش نشان می‌دهد که چه فایل‌هایی حذف خواهند شد، بدون اینکه واقعاً حذف کند. خط دوم فایل‌های track نشده را حذف می‌کند. خط سوم پوشه‌های track نشده را هم حذف می‌کند. همیشه اول با -n پیش‌نمایش بگیرید.

دستورات پیشرفته: cherry-pick، bisect و blame

git cherry-pick

همان‌طور که پیش‌تر اشاره شد، cherry-pick برای انتقال یک commit خاص بین برنچ‌ها استفاده می‌شود. این دستور در سناریوهای Hotfix بسیار مفید است: وقتی یک باگ حیاتی روی main رفع شده و شما می‌خواهید همان رفع را به برنچ release هم منتقل کنید.

git cherry-pick a1b2c3d
git cherry-pick a1b2c3d..b2c3d4e

خط دوم یک بازه از commit‌ها را cherry-pick می‌کند. این گزینه وقتی مفید است که می‌خواهید چند commit پشت سر هم را منتقل کنید.

git bisect

bisect یکی از قدرتمندترین ابزارهای Git برای پیدا کردن commit مسئول یک باگ است. با جستجو دودویی، در چند مرحله بین یک نقطه سالم و یک نقطه خراب، commit معیوب را پیدا می‌کند:

git bisect start
git bisect bad
git bisect good a1b2c3d
# Git شما را به یک commit میانی می‌برد
# تست کنید و بگویید
git bisect good  # یا
git bisect bad
git bisect reset

در پروژه‌ای با بیش از هزار commit بین نسخه سالم و نسخه خراب، bisect مسئول باگ را در کمتر از ده مرحله پیدا کرد. این ابزار به‌خصوص در پروژه‌های بزرگ که بازبینی دستی تاریخچه غیرممکن است، بی‌رقیب است.

git blame

blame برای هر خط از یک فایل، نشان می‌دهد آخرین commit و آخرین فردی که آن خط را تغییر داده کی بوده:

git blame file.php
git blame -L 100,150 file.php

خط دوم فقط محدوده خطوط ۱۰۰ تا ۱۵۰ را بررسی می‌کند. از blame برای پیدا کردن تاریخچه یک باگ خاص یا درک تصمیم‌های کد استفاده کنید؛ اما هرگز از آن برای سرزنش افراد استفاده نکنید. این ابزار نامش بد است اما کاربردش صرفاً فنی است.

git worktree

یک ابزار کمتر شناخته شده اما بسیار مفید: worktree اجازه می‌دهد چند برنچ را همزمان در پوشه‌های مختلف باز کنید. این ابزار در سناریوهایی که باید سریعاً بین دو برنچ جابه‌جا شوید، بی‌نظیر است:

git worktree add ../project-hotfix hotfix-branch
git worktree list
git worktree remove ../project-hotfix

خط اول یک پوشه جدید در مسیر مشخص می‌سازد که روی برنچ hotfix-branch است. خط دوم لیست worktree‌های موجود را نشان می‌دهد و خط سوم یکی را حذف می‌کند. این قابلیت در توسعه‌دهنده‌های تک‌نفره که روی چند فیچر هم‌زمان کار می‌کنند، ساعت‌ها صرفه‌جویی می‌کند.

ترکیب‌های روزمره که بهره‌وری را بالا می‌برند

Aliases: میان‌بُرهای شخصی

Git امکان تعریف میان‌بُر برای دستورات پرکاربرد را دارد. این میان‌بُرها در فایل پیکربندی Git ذخیره می‌شوند و در همه پروژه‌ها در دسترس هستند:

git config --global alias.st "status -s"
git config --global alias.co "checkout"
git config --global alias.lg "log --oneline --graph --all"
git config --global alias.unstage "restore --staged"

پس از تعریف این میان‌بُرها، به‌جای git status -s می‌توانید git st بزنید. این کار در پروژه‌های روزمره، چند ثانیه در هر بار صرفه‌جویی می‌کند که در طول یک سال، مجموع قابل توجهی می‌شود.

Git hooks

hooks به شما اجازه می‌دهند اسکریپت‌هایی را در نقاط مختلف چرخه Git اجرا کنید. یک hook معروف، pre-commit است که قبل از هر commit یک بررسی انجام می‌دهد:

#!/bin/sh
npm run lint || exit 1
npm test || exit 1

این اسکریپت در مسیر .git/hooks/pre-commit قرار می‌گیرد و قبل از هر commit، lint و تست را اجرا می‌کند. اگر بررسی‌ها شکست بخورند، commit رد می‌شود. ابزارهایی مثل husky این فرآیند را ساده‌تر می‌کنند. برای اتوماسیون بالاتر، GitHub Actions را ببینید که همین منطق را در سطح CI/CD پیاده می‌کند.

Git برای پروژه‌های وردپرسی

در پروژه‌های وردپرسی، مدیریت فایل‌های هسته، افزونه‌ها و قالب‌ها نیازمند رویکرد متفاوتی است. معمولاً هسته وردپرس و افزونه‌های عمومی را در مخزن نگه نمی‌دارند، اما قالب و افزونه سفارشی مدیریت می‌شوند. اگر روی قالب یا افزونه سفارشی کار می‌کنید، گیت در وردپرس نکات اختصاصی این سناریو را توضیح داده است.

اتصال به GitHub

پس از تمرین دستورات محلی، گام طبیعی بعدی، کار با مخزن راه دور است. بیشتر پروژه‌های مدرن روی GitHub یا GitLab میزبانی می‌شوند. تفاوت این دو پلتفرم در مقایسه GitHub و GitLab بررسی شده است. برای شروع کار با GitHub، آموزش github نقطه شروع مناسبی است.

اشتباهات رایج در استفاده از دستورات Git

  • git push --force بدون احتیاط: این دستور می‌تواند تاریخچه مخزن راه دور را بازنویسی کند و کار دیگران را از بین ببرد. همیشه از --force-with-lease استفاده کنید.
  • کامیت کردن همه چیز با یک پیام مبهم: کامیت‌های بزرگ با پیام‌های مثل fix یا update، در بازبینی و بازگشت دردسر می‌سازند. هر کامیت باید یک تغییر منطقی را نشان دهد.
  • rebasing روی برنچ مشترک: قاعده طلایی: برنچی که با دیگران به اشتراک گذاشته شده را rebase نکنید. این کار باعث می‌شود همکارانتان نتوانند به‌درستی pull کنند.
  • استفاده از git reset --hard بدون بکاپ: این دستور تغییرات محلی را برای همیشه از بین می‌برد. قبل از زدن آن، یک stash یا بکاپ موقت بگیرید.
  • نگه‌داشتن برنچ‌های قدیمی: برنچ‌هایی که چند ماه از ادغام‌شان گذشته، فقط شلوغی می‌سازند. بعد از هر ادغام موفق، برنچ محلی و راه دور را حذف کنید.
  • نداشتن .gitignore: بدون این فایل، فایل‌های موقت و پوشه‌های وابستگی به مخزن اضافه می‌شوند. اولین کاری که در هر پروژه جدید باید بکنید، ساخت .gitignore است.
  • استفاده از git add . بدون بررسی: این دستور همه تغییرات را stage می‌کند، شامل فایل‌هایی که قصد کامیت کردنشان را ندارید. همیشه اول git status یا git add -p بزنید.
  • نادیده گرفتن git reflog: بسیاری از توسعه‌دهندگان نمی‌دانند که Git تقریباً هیچ‌چیز را از دست نمی‌دهد. در هر موقعیت بازیابی، اول reflog را بررسی کنید.
  • commit کردن فایل‌های حساس: فایل‌های .env، کلیدهای SSH و رمزها هرگز نباید کامیت شوند. قبل از هر commit، git diff --staged بزنید.
  • پاک کردن مستقیم فایل با rm به‌جای git rm: اگر فایلی را با rm حذف کنید، Git متوجه نمی‌شود. همیشه از git rm file.php استفاده کنید یا پس از rm، git add -A بزنید.

اگر در استفاده روزمره با پیام‌های خطای Git مواجه شده‌اید، رفع خطاهای رایج git مجموعه‌ای از خطاهای رایج و راه‌حل‌شان را کنار هم گذاشته است.

در Git، هر دستور یک قصه دارد. اگر دستورات را بدون درک مدل ذهنی حفظ کنید، در موقعیت‌های پیچیده سرگردان می‌شوید. اگر مدل را بفهمید، دستورات از دل موقعیت بیرون می‌آیند.

پرسش‌های پرتکرار درباره دستورات Git

چند دستور Git برای شروع کافی است؟

برای کارهای روزمره، حدود پانزده دستور پایه کافی است: config، init، clone، add، commit، status، log، diff، branch، switch، merge، pull، push، fetch و reflog. تسلط بر همین پانزده دستور، شما را در سطح متوسط قرار می‌دهد. اگر می‌خواهید از صفر با مفاهیم اصلی شروع کنید، آموزش git از صفر نقطه شروع مناسبی است.

تفاوت git fetch و git pull چیست؟

fetch تغییرات را از سرور می‌گیرد اما روی برنچ محلی اعمال نمی‌کند. pull ترکیبی از fetch و merge است که هر دو کار را انجام می‌دهد. تجربه من این است که در پروژه‌های تیمی، عادت به fetch سپس merge آگاهانه، از pull کورکورانه امن‌تر است.

چه زمانی از git reset و چه زمانی از git revert استفاده کنم؟

اگر commit هنوز push نشده، از reset استفاده کنید. اگر push شده، از revert استفاده کنید چون revert تاریخچه را بازنویسی نمی‌کند و همکارانتان مشکلی پیدا نمی‌کنند. قاعده ساده: هر چیزی که با دیگران به اشتراک گذاشته شده را با revert بازگردانید، نه با reset.

آیا git commit --amend امن است؟

Amend فقط روی آخرین commit کار می‌کند و آن را با یک commit جدید بازنویسی می‌کند. اگر commit هنوز push نشده، امن است. اگر push شده باشد، باید پس از amend، از git push --force-with-lease استفاده کنید. توصیه من این است که قبل از amend، همیشه از git log -1 برای بررسی commit فعلی استفاده کنید.

چطور می‌توانم چند commit را در یک commit ترکیب کنم؟

از git rebase -i HEAD~3 استفاده کنید و در ویرایشگر تعاملی، دستور pick را برای commit‌های بعدی به squash تغییر دهید. این کار commit‌ها را در commit اول ادغام می‌کند و یک پیام commit جدید به شما اجازه می‌دهد بنویسید. این تکنیک در تمیز کردن تاریخچه قبل از Pull Request بسیار مفید است.

تفاوت git switch و git checkout چیست؟

تاریخی: در نسخه‌های قدیمی Git، git checkout هم برای جابه‌جایی برنچ و هم برای بازگردانی فایل استفاده می‌شد. این ابهام باعث خطاهای ناخواسته می‌شد. از نسخه ۲.۲۳، Git دو دستور git switch برای جابه‌جایی برنچ و git restore برای بازگردانی فایل معرفی کرده است. استفاده از این دستورات جدید، کد شما را واضح‌تر و امن‌تر می‌کند.

چطور از یک stash اشتباه بازیابی کنم؟

stash‌ها حتی پس از drop در reflog ذخیره می‌شوند. با git fsck --unreachable می‌توانید commit‌های unreachable را پیدا کنید و با git stash apply <commit-hash> آن‌ها را بازیابی کنید. این تکنیک پیشرفته است اما در شرایط اضطراری ارزش دانستن دارد.

git cherry-pick چه زمانی مفید است؟

وقتی یک رفع باگ خاص روی برنچ main انجام شده و می‌خواهید همان تغییر را به برنچ release هم منتقل کنید، بدون اینکه تمام تغییرات دیگر main را بردارید. این سناریو در تیم‌هایی که چند برنچ نسخه‌بندی دارند، روزمره است.

چند بار در روز باید git fetch بزنم؟

در پروژه‌های تیمی فعال، حداقل یک بار در ابتدای روز و یک بار قبل از هر push. این عادت ساده، از تعارض‌های بزرگ در انتهای هفته جلوگیری می‌کند. تجربه من این است که تیم‌هایی که fetch منظم دارند، تعارض‌های کمتری تجربه می‌کنند.

اگر تاریخچه پروژه شلوغ شده، چطور تمیزش کنم؟

از ترکیب git rebase -i و git commit --amend برای تمیز کردن commit‌های محلی استفاده کنید. برای تاریخچه‌ای که push شده، معمولاً نیازی به تمیز کردن نیست چون ریسک آن بیشتر از سودش است. اگر پروژه شما به مرحله‌ای رسیده که تاریخچه دست‌وپاگیر شده، بهتر است تیم روی جریان کاری بهتری توافق کند تا تاریخچه را بازنویسی کند.

از یادگیری دستور به تسلط بر جریان

یادگیری دستورات Git شبیه یادگیری یک زبان است. اول با کلمات ساده شروع می‌کنید، بعد جمله می‌سازید، و در نهایت می‌توانید درباره هر موضوعی صحبت کنید. تفاوت کسی که فقط دستورات را حفظ کرده با کسی که Git را می‌فهمد، در لحظه‌های غیرمنتظره آشکار می‌شود: وقتی تعارض پیچیده‌ای رخ می‌دهد، وقتی یک commit اشتباه به سرور منتقل شده، وقتی می‌خواهید یک باگ را در تاریخچه هزار commit پیدا کنید.

نکته‌ای که در طول سال‌ها یاد گرفته‌ام: هیچ‌کدام از دستورات Git خطرناک نیست، به شرط آنکه بدانید چه می‌کنند. بزرگ‌ترین اشتباه تازه‌کارها این است که از ترس، به سراغ دستورات پیشرفته نمی‌روند و در سطح دستورات پایه گیر می‌کنند. اما همان‌طور که reflog می‌تواند تقریباً هر اشتباهی را برگرداند، Git ابزارهای خودش را دارد که می‌تواند شما را از هر وضعیتی نجات دهد.

اگر در استفاده روزمره از دستورات Git به موقعیتی برخورده‌اید که برایتان چالش‌برانگیز بوده — یک rebase پیچیده، یک force push که مشکل ساخت، یا یک بازیابی از reflog که نجات‌تان داد — خوشحال می‌شوم تجربه‌تان را در دیدگاه‌ها بخوانم. برای خواننده بعدی، جزئیات یک موقعیت واقعی، از هر مستند رسمی ارزشمندتر است. 🔧