دستورات ضروری Git
۲۷ تیر ۱۳۹۹
مطمعنا هنگام استفاده از git، مشکلها و سوالهای متعددی برایتان پیش آمده است. بههمین منظور میخواهیم در این مقاله دستورهای کاربردی این ابزار که به رفع مشکل شما کمک میکنند را مورد بررسی قرار دهیم.
مشکلها را در زمان خودشان رفعکنید، چون شانس دومی ندارید. برای استفاده از گیت منابع بسیار خوبی در سطح اینترنت قرار دارد، ولی هیچکدام از آنها به رفع مشکلهای شما کمک نمیکنند.
اگر کسی میگوید در استفاده از گیت، مشکلی برایش رخ نداده است، به او اعتماد نکنید. مگر اینکه آنفرد، لینوس توروالدز (Linus Torvalds) یا جفدین (Jeff Dean) باشد.
گیت، کابوس همه توسعهدهندگان تازهکار در یک گروه است. مخصوصا وقتی که با افراد با تجربه سروکار داشته باشند، این موضوع وحشتناکتر است.
- اگر شما اشتباهی انجامدهید، مثلا فایل
.git
را از پوشهاصلی پاک کنید و وانمود کنید هیچ اتفاقی رخ نداده است. - وقتی آنها از خطای شما مطلع میشوند به این فکر نمیکنند شما یک تازهکار یا یک احمق هستید، اما خودتان مدام به این موضوع فکر میکنید. برای افرادی مثل من ناگهان مغز، تمام کارهای شرمآور را که حتی در دوران کودکی رخ دادهاست، به یاد میآورد.
دو نکته فوق باعث میشود، همه قبل از انجام هرگونه Commit
و push
به ریموت، عصبی شوند. اما این مراقبتها به ما کمک نمیکنند و باعث میشوند زودتر یککار احمقانه انجامدهیم. پس بدیهی است که ما، جستجو در گوگل را آغازکنیم.
در واقع این مقاله دو بخش از کل دستورهای git را پوشش میدهد زیرا نمیخواهیم با اطلاعات زیاد شما را خستهکنیم. در قسمت اول تمرکز خود را برروی دستورهای مفیدی که در پوشه کاری local میگذاریم و در قسمت دوم مسائل مربوط به ریمورت ریپازیتوریها مانند reverting, deleting, ویرایش Commit و … میپردازیم. پس خوب دقت کنید و در ادامه مقاله با ما همراه باشید.
در این قسمت میپردازیم به:
- فایلهایی که به صورت اتفاقی در حالت staged قرار گرفتهاند.
- دنبالنکردن فایلهایی که نمیخواهیم دیگر track شوند.
- چگونگیِ پاک کردن فایلهای un-tracked و ignored.
- revert کردن تغییرهایی که هنوز commit نشدهاند.
پس بیاید به دستورهایی که، کار ما را به خطر میاندازند، نگاهی بیندازیم.
فایلهایی که به صورت اتفاقی در حالت staged قرار گرفتهاند
آیا تاکنون دستور زیر را اجرا کردهاید و میخواهید آنها را بیاثر کنید؟
git add .
git add *
git add -A
git add -u
با این لینک میتوانید همهچیز را درمورد دستورهای بالا یادبگیرید.
دستورهایی که در این زمان میتوانند به شما کمک کنند:
git reset <filename>
یاgit reset HEAD <filename>
git rm --cached <filename>
git restore --staged <filename>
— در v2.23 (اوت 2019) به گیت اضافهشده است.
این سه دستور هنگام اضافه کردن فایلها به حالت stage، توسط خود گیت به شما توصیه میشود. اگر شما از گیت ورژن 2.23 (اتصال به semantic versioning) استفادهکنید،
git restore --staged <filename>
بجای
git reset HEAD <filename>
به شما توصیه میشود.
دستور
git restore --staged <filename>
به طور شفافی کاراییش معلوم است. پس بیاید دو دستور دیگر را بررسیکنیم.
:git reset HEAD <filename>
این دستور برای بازنشانی INDEX یا STAGING AREA مورد استفاده قرار میگیرد.
git rm --cached <filename>:
این دستور کاملا فایل را از حالت INDEX یا STAGING AREA خارج میکند، همچنین اگر شما یک فایل موجود در ریپازیتوری را پاک کنید، با اجرای این دستور، آنفایل از INDEX، STAGING AREA و همچنین از commit
های دیگر پاک خواهدشد. اما هنگامی که از این دستور بر روی فایل جدید استفاده کنید، فقط آن را از حالت staged بیرون میآورد.
چرا گیت دو دستور مختلف را برای اینکار توصیه میکند؟
برای اجرای موفقیتآمیز دستور
git reset HEAD <filename>
یا
git restore --staged <filename>
باید حداقل یک commit
وجود داشتهباشد. به ایندلیل که دستور
git reset HEAD
فایل درون HEAD را بازگردانی میکند ولی قبل از انجام اولین commit
هیچگونه HEAD ی موجود نیست (به ایندلیل که HEAD در زمان اولین commit ساخته میشود.).
راهحل این مشکل هم اجرای آنT به استثنای HEAD است، به مثال زیر توجه کنید:
یادداشت: من از git revert
بجای git revert Head
استفاده میکنم. در لینکهای زیر میتوانید در اینمورد بیشتر بخوانید.
دفعه بعد که از گیت استفاده میکنید، هنگامی که هنوز commit
ی موجود نباشد، گیت دستور
git rm --cached <filename>
را به شما پیشنهاد میکند در غیر اینصورت
git reset Head و git restore --staged
را مشاهده خواهیدکرد.
در ادامه با نحوه استفاده از ایندستورها هنگامی که یک مشکل بوجود میآید، آشنا خواهیم شد.
git reset
git reset HEAD <filename>:
اگر شما فرد تنبلی باشید، تمام commit
های خود را در پایان روز انجام میدهید.
در تمامروز به اضافهکردن و ویرایش فایلهایتان مشغول بودهاید، حال شما میخواهید همگی آنها با همدیگر در یک commit
به گیت بیفزایید و به صورت اتفاقی از دستور git add .
استفاده میکنید.
حال شما میخواهید فایل پیکربندی دیتابیس را از فایلهای دیگر جدا و به صورت جداگانه آن را commit
کنید.
با توجه به تصویر بالا، حال شما میتوانید اینکار را انجام دهید.
git rm –cached
حال شما متوجه این موضوع شدهاید، گیت زمانی این دستور را به شما توصیه میکند که هنوز commit
ی رخ ندادهاست. نکته حائز اهمیت این است که از این دستور تا زمانی که آن را کاملا نمیشناسید، استفاده نکنید.
دوباره تکرار میکنم، دستورهای
git rm --cached و git reset
تا زمانی یکسان عمل میکنند که commit
ی انجام نشدهباشد. در قدم اول خروجی دستور
git rm --cached
را هنگامی که commit
انجام شده، بررسی میکنیم.
با نگاهکردن به عکس بالا متوجه اتفاقاتی که رخ دادهاست، میشوید؟ اگر متوجه نشدهاید، نگران این موضوع نباشید در ادامه کاملا توضیح میدهیم.
این دستور فایلها را از INDEX و STAGING AREA پاک میکند، ولی این فایلها با تمام اطلاعاتشان هنوز در سیستم شما موجود هستند اما گیت آنفایل را به حالت un-tracked درآوردهاست. سادهتر بگوییم، با اجرای دستور git rm --cached
به نظر میرسد شما، تازه یک فایل را در پوشهتان کپی کردهاید.
یکی دیگر از اتفاقاتی که در اجرای ایندستور رخ میدهد، پاک شدن فایل از ریپازیتوری است. اگر شما دستور:
git rm --cached <file> && git push
را اجرا کنید، <file>
از گیت پاک میشود، زیرا این فایل فقط در سیستم شما موجود است و به حالت un-tracked در آمده.
برای رویارویی با زمانی که شما تمام فایلهایتان را در ریموتسرور push
کردهاید، مثلا شما همراه پروژه node خود پوشه node_modules را به ریمورت فرستادهاید، میتوانید:
- فایلی با پسوند
.gitignore
در کنار فایلهایتان اضاف کنید و بعد از آن دستورrm -r node_modules && git add . && git commit && git push && npm start
را اجرا کنید. - یا
.gitignore
را بسازید سپس دستورهایgit rm --cached -r node_modules && git commit && git push
را اجرا کنید.
گزینه دوم بهتر و کوتاهتر است. هنگامی که شما از
git rm --cached -r
استفاده میکنید (-r مخفف بازگشی – recursive)، این دستور پوشه node_modules را از INDEX یا STAGING AREA پاک میکند و همچنین آنپوشه به حالت un-tracked در میآید. ولی به این نکته توجه داشته باشید از فایلهای سیستمی شما پاک نمیشود.
هنگامی که شما دستور git add .
را اجرا میکنید، اول فایل .gitignore
چک میشود و دیگر شما پوشه node_modules را در git status
نمیبینید زیرا به یک پوشه un-tracked در آمدهاست.
خلاصه:
همیشه از دستورهای git reset <filename>
برای unstage کردن یک فایل بخصوص یا از git reset .
برای unstage کردن تمام فایلها استفاده کنید. این دستورها حتی اگر commit
هم رخ نداده باشد کار میکنند.
از دستور git rm --cached
هم زمانی که میخواهید فایلی را از ریپازیتوری حذف و آن را در سیستم خود نگهدارید، استفاده کنید. کارایی این دستور را با git reset
اشتباه نکنید.
اگر میخواهید بیشتر بدانید، آدرس زیر را دنبال کنید.
به طور تصادفی فایلها را ردیابی میکنید یا دیگر نمیخواهید یک فایل را track کنید؟
در این قسمت فایده دستور git rm --cached
نمایان میشود. همانطور که قبلا در این مقاله خواندید ایندستور فایل را از INDEX و STAGING AREA و همچنین ریپازیتوری پاک میکند. بنابراین، git push
فایل را از ریپازیتوری حذف و در قدم بعد git pull
آن را از فایلهای سیستم گیت پاک میکند (فایلها در سیستم شما باقی میمانند).
- برای un-track و پاککردن همه چیز:
git rm --cached .
- برای un-track و پاککردن یک فایل بخصوص:
git rm --cached <fillename>
- و در آخر برای un-track و پاککردن یک پوشه:
git rm --cached -r <directoryname>
توجه داشتهباشید دستور git rm
با git rm --cached
متفاوت است. git rm
نیز فایل را از سیستم شما، ریپازیتوری و هرجای دیگر سیستم پاک میکند. پس --cached
را فراموش نکنید.
میخواهید فایلهای un-tracked و ignore شده را حذف کنید؟ در ادامه با ما همراه باشید.
در مقابل شما دو راهحل وجود دارد. با دستور rm file1 file2 file3 ...
اینکار را انجامدهید. ولی اگر فایلها زیاد باشند، این کار منطقی نیست پس یک راه دیگر پاک کردن فایلهای درون .gitignore
است. اینکار با دستور git clean
انجام میشود.
راهنمای (man) ایندستور:
Cleans the working tree by recursively removing files that are not under version control, starting from the current directory.
Normally, only files unknown to Git are removed, but if the -x option is specified, ignored files are also removed. This can, for example, be useful to
remove all build products.
همانطور که در متن بالا گفته شد، با این دستور به صورت بازگشتی (recursive) فایلها از دایرکتوری فعلی که دستور در آن اجرا شده پاک میشوند.
- برای حذف un-tracked فایلها:
git clean -f
- برای حذف un-tracked و ignored فایلها:
git clean -xf
- برای حذف دایرکتوری و un-tracked فایلها:
git clean -fd
- برای حذف دایرکتوری و un-tracked, ignored فایلهای :
git clean -xfd
ولی چرا از ویژگی -f یا –force استفاده میکنیم؟ در پیکربندی گیت، متغییر clean.requireForce برابر با true قرار داده شدهاست. اگر از -f، -n، -i استفاده نکنیم دستور ما با موفقیت به پایان نمیرسد.
این دستور فایل و پوشهها را به صورت فیزیکی حذف میکند. پس امیدوارم در هنگام اجرای این دستور اشتباه نکرده باشید. برای رفع این مشکل میتوانید از دستور git clean -fi
استفاده کنید.
شما میتوانید از گزینه شماره 4 استفاده کنید و گیت قبل از حذف هر فایل، از شما میپرسد از فایل حذف شود یا خیر؟
راهنمای (man) ایندستور:
آیا می خواهید تغییرها را به حالت un-committed برگردانید؟
شما دستور git commit
را اجرا و پس از آن به ویرایش فایلهای پروژهتان میپردازید. چندساعت بعد تصمیم میگیرید، تغییرهای ایجاد شده را به حالت قبل برگردانید.
راهحل، استفاده از دستور git checkout
است. بله درست شنیدید، ولی هنگام استفاده از این دستور، مراقب باشید. استفاده نادرست این دستور باعث تخریب میشود. اجرای این دستور باعث حذف کارهای انجامشده بر روی دایرکتوری که در آن قرار دارید میشود و آن را به commit قبلی خود بازمیگرداند.
راهنمای این دستور:
git-checkout — Switch branches or restore working tree files
Updates files in the working tree to match the version in the index or the specified tree. If no paths are given, git checkout will also update HEAD to set
the specified branch as the current branch.
پینوشت: شاید در تصویر بالا شما دستور git restore <filename>
را ببینید (این بخاطر استفاده از ورژن 2.25.0 گیت است). با توجه به راهنما، از این دستور استفاده نکنید.
در ادامه، میبایست به این موضوع اشاره کرد با دستور git checkout .
میتوانید فقط فایلهای تغییر دادهشده را به stage قبل (نه commit قبل) برگردانید. در تصویر بالا staging version قبل، خالی است. پس با دستور git checkout .
محتوای first message to commit، خالی میشود.
گیت تاریخچه INDEX و STAGING AREA را نگهداری نمیکند. دو چییزی که گیت به شما نشان میدهد:
- چهچیزی در INDEX است؟
- چهچیزی در INDEX نیست؟
با اجرای دستور git add
، گیت محتوای درون INDEX را اضافه یا با مقدار جدید جایگزین میکند. بنابراین شما به تاریخچه INDEX مانند COMMIT دسترسی ندارید و نمیتوانید آن را بازگردانی کنید.
از آنجا که هیچ INDEX versions دیگری باقی نمانده است، گیت کپی از commit قبلی که somedbconfigfile1 خالی است دریافت می کند.
دستور git checkout <filename>
را فقط میتوان روی فایلهای stage نشده اجرا کرد. به همین دلیل از git reset .
برای un-stage کردن فایل در تصویر بالا استفاده شده است.