Git
Chapters ▾ 2nd Edition

2.2 پایه‌های گیت - ثبت تغییرات یک مخزن

ثبت تغییرات یک مخزن

در این بخش، شما باید یک مخزن واقعی گیت بر روی سیستم لوکال داشته باشید و یک چک‌اوت یا ـ‌کپی کاری‌ـ تمام فایل‌های موجود مقابل شما باشد. معمولا شما می‌خواهید شروع به تغییر دادن کنید و اسنپ‌شات‌ها را در مخزن کامیت کنید، هر بار که پروژه به وضعتی رسید که شما می‌خواهید آن را ثبت کنید.

یادتون باشه که هر فایلی در پوشه کاری شما به طور کلی دو وضعیت دارد: tracked(دنبال شده/ترکت)ـ یا _untracked(دنبال نشده/آن‌ترکت). ترکت فایلی هستید که در اخرین اسنپ‌شات شما بوده‌اند؛ آن‌ها می‌توانند وضعتی مثل ـ‌unmodified(تغییر نکرده/آن‌مودیفاید)ـ، ـmodified(تغییر کرده/مودی‌فاید)ـ، یا _staged(ظاهر شده/استیجد) داشته باشند. به طور خلاصه، ترکت فایل‌ها آنهایی هستند که گیت آن‌ها را می‌شناسد.

آن‌ترکت فایل‌ها بقیه هستند — هر فایلی در اسنپ‌شات آخر شما نبوده باشد و شما را آن را ـadd(همان عمل استیج است/اَد)ـ نکرده باشید. وقتی اول مخزنی را کلون می‌کنید، همه‌ی فایل‌ها ترکت شده و آن‌مودیفاید هستند زیرا گیت قبلا بررسی کرده است و هنوز شما تغییراتی را اعمال نکرده‌اید. به محض تغییر فایل‌ها، گیت وضعیت‌ آن‌ها را به مودیفاید تغییر می‌دهد، چون شما آن را نسبت به کامیت آخر تغییر داده‌اید. همانطور که کار می‌کنید، شما فایل‌های مودیفاید شده را انتخاب و اَد می‌کنید و سپس همه‌ی آن را کامیت می‌کنید، و این چرخه ادامه دارد.

چرخه عمر وضعیت فایل‌های شما image::images/lifecycle.png[چرخه عمر وضعیت یک فایل]

بررسی وضعیت فایل‌ها

ابزار اصلی‌ای که شما برای تعیین وضعیت فایل‌ها استفاده می‌کنید، دستور git status است. اگر شما دستور را مستقیماً بعد از کلون اجرا کنید،‌ چیزی شبیه به این خواهی دید:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

این بدین معنی است که پوشه کاری شما تمیز است — به زبان دیگر، هیچ کدام از فایل‌های ترکت شده تغییر داده نشده یا وضعیت مودیفاید ندارند. همچنین گیت هیچ فایل دنبال نشده یا آن‌ترکت را نمی‌بینید. در آخر، این دستور به شما می‌گوید که بر روی کدام برنچ هستید و شما از اختلافات بین برنچ شما و برنچ روی سرور مطلع می‌سازد. فعلا، آن برنچ همیشه ``master`` است که به صورت پیش فرض ساخته شده؛ نگران نباشید در بخشی [_git_branching] درباره این موضوع با جزئیات بحث خواهد شد. بیایید یه فایل جدید به پروژه اضافه کنیم، یک فایل README ساده. اگر از قبل وجود نداشته باشد، می‌توانید با اجرای دستور git status ببنید که فایل به وضعیت آن‌ترکت درآمده است:

$ echo 'My Project' > README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    README

nothing added to commit but untracked files present (use "git add" to track)

می‌توانید فایل README جدید که ساختید را در حالت آن‌ترکت ببینید، چون خروجی وضعیت فایل در زیر تیتر ``Untracked files`` است. آن‌ترکت به طوری کلی به این معنی است که گیت آن را در آخرین اسنپ‌شات(کامیت) ندیده است. گیت به هیچ عنوان آن را در اسنپ‌شات‌های(کامیت‌ها) بعدی ثبت نمی‌کند تا زمانی که شما آن را اَد کنید و به روی استیج بیارید و کامیت کنید. پس گیت به این صورت کار میکنه در نتیجه شما‌ نمی‌توانید به صورت تصادفی شروع به اضافه کردن فایلی دودویی در یک فایل دیگر کنید که منظورتان آن فایل نبوده است. خب شما می‌خواهید شروع به اضافه کردن فایل README کنید، پس بیایید به گیت این موضوع را اعلام کنیم و آن را به حالت tracked در بیاوریم.

‍ ==== دنبال کردن یک فایل جدید به این ترتیب برای قرار دادن یک فایل در حالت tracked و اینکه گیت بتواند آن را در اسنپ‌شات‌ها بعدی را شامل کند باید از دستور git add استفاده کنید. برای اضافه کردن فایل README، باید دستور زیر را وارد کنید:

$ git add README

اگر دستور git status را وارد کنید، می‌توانید ببیند فایل README حالا در حال ترکت و استیج شده و فعل کامیت است:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)

    new file:   README

به این وضعیت، اصطلاحا استیج می‌گویند چون فایل در زیر تیتر ``Changes to be committed`` و منتظر انجام فعل کامیت است. شما احتمالا زمانی که دستور git init را اجرا کرده بودید نیز یکبار دستور git add {files} را نیز اجرا کرده باشید-- آن دستور برای مورد دنبال قرار گرفتن فایل‌ها در درون پوشه بود. دستور git add یا نام یک فایل را اضافه می‌کند یا نام یک پوشه را؛ اگر یک پوشه باشد، دستور به صورت بازگشتی تمامی فایل‌های و زیرپوشه‌ها را اضافه می‌کند.

اضافه کردن فایل‌های تغییر یافته

حالا بیایید فایلی که در حال حاضر ترکت شده را تغییر دهیم. اگر فایل قبلی که اضافه کردیم به نام CONTRIBUTING.md تغییر دهیم و دوباره دستور git status را اجرا کنیم، چیزی شبیه به نتیجه زیر را می‌بینید:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README

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:   CONTRIBUTING.md

فایل CONTROBUTING.md در زیر بخشی به نام ``Changes not staged for commit`` ظاهر خواهد شد — به معنی است که یک فایلی دچار تغییر شده بود حالا ترکت شده اما هنوز آن را استیجد نکرده‌ایم، برای انجام استیج می‌بایست دستور git add را اجرا کنیم. دستور git add چند منظوره است — برای ترک کردن فایل‌های جدید، برای استیج کردن فایل‌های تغییر یافته و برای انجام دیگر کارها مثل مشخص کردن مرج-کانفلیکت‌ فایل‌ها به عنوان کاری که انجام شده. بیایید دستور git add را اجرا کنیم تا فایل CONTRIBUTING.md را استیج کنیم، و بعد دستور git status را دوباره وارد کنیم.

$ git add CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

هر دو فایل استیج شده‌اند و به کامیت بعدی شما اضافه خواهند شد. در این لحظه، فرض کنید که یادتان می‌یاد یک تغییر کوچک دیگر در فایل CONTRIBUTING.md می‌خواهید انجام دهید، قبل از اینکه کامیت کنید. فایل را دوباهر باز می‌کنید و تغییرات را اعمال می‌کنید، حالا اماده کامیت است. حالا، بیایید دوباره دستور git status را اجرا کنیم:

$ vim CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

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:   CONTRIBUTING.md

چطور ممکنه؟!!! فایل CONTRIBUTING.md هم به عنوان فایلی استیج شده و ـ‌همچنین‌ـ استیج نشده لیست شده است. چطور امکان دارد؟ خب این موضوع بر‌میگردد به گیت، وقتی دستور git add را اجرا می‌کنید و فایلی را استیج می‌کنید، گیت دقیقا همان تغییرات آماده کامیت می‌کند و شما اگر واقعا کامیت کنید، نسخه‌ای جدید از فایل پروژه ایجاد خواهد شد و وقتی که قبل از کامیت دوباره تغییر بدید درحالی که آن را یکبار استیج کرده‌اید؛ گیت تغییرات جدیدی را ثبت می‌کند و به شما می‌گوید تغییرات جدید را در کامیت جاری اعمال نمی‌کند مگر اینکه دوباره آن را استیج کنید.

$ git add CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

وضعیت‌های کوتاه

خروجی git status خیلی توصیفی و لغوی است؛ در حالی که گیت دارای یه سری اعلام‌ وضعیت‌های کوتاه نیز می‌باشد، که می‌توانید وضعیت تغییرات را خیلی کوتاه و خلاصه‌تر ببینید. اگر دستور git status -s یا git status --short را وارد کنید، یک خروجی بسیار ساده شده به شما خواهد داد:

$ git status -s
 M README
MM Rakefile
A  lib/git.rb
M  lib/simplegit.rb
?? LICENSE.txt

فایل‌های جدیدی که هنوز ترکت نشده‌اند علامت ?? مقابل آنان است، فایل‌های جدیدی که استیج شده‌اند علامت A دارند، فایل‌های تغییر یافته علامت M دارند و بقیه نیز به همین ترتیب. خروجی حروفی که می‌بینید عملا دو ستون است، ستون سمت چپ نشان‌دهنده وضعیت استیج است و ستون سمت راست نشان‌دهنده وضعیت درخت کاری است. برای مثال-- در خروجی بالا، فایل README در پوشه کاری تغییر یافته است اما هنوز آن را استیج نکرده‌اند، در حالی که فایل lib/simplegit.rb تغییر یافته و استیج شده است. فایل Rakefile تغییر یافته و استیج شده بود و بعد دوباره به حالت تغییر یافته درآمده، به همین دلیل هر دو ستون آن پر است و MM یعنی استیج شده و استیج نشده.

نادیده گرفتن فایل‌ها

گاهی مجموعه‌ای از فایل‌ها هستند که ما نمی‌خواهیم گیت به صورت خودکار آن add یا آن‌ها را دنبال کند. به صورت کلی فایل‌هایی وجود دارد که به صورت اتوماتیک ساخته می‌شود مثل لاگ فایل‌ها و…​ در این گونه موارد، می‌توانید لیستی از نام فایل‌ها بسازید و آن‌ها در فایلی به نام gitingore. قرار بدید؛ در اینجا مثالی برای فایل gitignore. داریم:

$ cat .gitignore
*.[oa]
*~

خط اول به گیت می‌گوید که هر فایلی که با ``o.`` یا ``a.`` تمام ‌می‌شود را نادیده بگیرد. خط دوم به گیت می‌گوید که همه‌ی فایل‌های که نام‌شان با علامت تیلد(~) است ناده بگیرد، از این علامت اکثر ویرایشگران متن مثل ایمکس استفاده می‌کنند تا فایل‌های موقت خود را ذخیره کنند. شاید شما پوشه‌های tmp, log , pid را هم اضافه کنید؛ یاد گرفتن کار با فایل gitignore. ضروری است، چرا باید فایلی را کامیت کنید که نمی‌خواهید واقعا در مخزن شما وجود داشته باشد.

قوانین و الگو‌هایی که می‌توانید در فایل gitignore. قرار بدید تا فایل مورد نظر شما در کامیت‌های بعدی حضور نداشته باشد.

  • خط‌هایی که با # شروع شوند نادیده گرفته می‌شوند.

  • الگو‌‌های استاندارد کار می‌کنند و به صورت بازگشتی بر روی درخت کاری شما تاثیر می‌گذارند.

  • می‌توانید الگو‌ها را با علامت اسلش رو به جلو (/) از حالت بازگشتی خارج کنید.

  • می‌توانید از اسلش رو به جلو (/) پوشه‌ای مشخص را تعیین کنید.

  • می‌توانید با اضافه کردن علامت تعجب (!) منظور جمله را برعکس کنید.

الگو‌های استاندارد که می‌توان استفاده که به سادگی با کد‌‌های Regex(Regural expretions) نوشته می‌شود که شل هم استفاده می‌کند. علامت ستاره (*) یک یا چند کارکتر را پیدا می‌کند؛ [abc] هر حرفی که داخل براکت([]) باشد را پیدا می‌کند( در این مورد a, b ,c هستند). علامت سوال (?) یک کارکتر را پیدا می‌کند و علامت براکت به همراه دو کارکتر که با - از هم جدا شده باشند، آنهایی که در آن مجموعه وجود داشته باشند را پیدا می‌کند([9-0] در این مورد هر عددی که بین ۰ تا ۹ باشد). و همچنین می‌توانید از دو ستاره ** برای پیدا کردن پوشه‌های تو در تو استفاده کنید به این صورت a/**/z که نتیجه‌ی آن می‌تواند a/z, a/b/z, a/b/c/z, و به همین ترتیب باشد.

در این مثال دیگری برای فایل `gitignore.`داریم:

# ignore all .a files
*.a

# but do track lib.a, even though you're ignoring .a files above
!lib.a

# only ignore the TODO file in the current directory, not subdir/TODO
/TODO

# ignore all files in any directory named build
build/

# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt

# ignore all .pdf files in the doc/ directory and any of its subdirectories
doc/**/*.pdf
Tip

در صفحه گیت‌هاب لیست قابل ملاحظه‌ای برای فایل gitignore. فراهم شده است که مملوع از مثال‌های مختلف برای زبان‌ها و شرایط مختلف است. https://github.com/github/gitignore

Note

در یک مورد ساده، یک مخزن شاید یک فایل gitignore. در پوشه اصلی داشته باشد، که به صورت بازگشتی تمام موجودیت‌های پروژه را شامل می‌شود. با این حال، این امکان وجود دارد که در زیر پوشه‌های خود باز هم فایل gitignore. داشته باشد. قوانین و الگوها در این فایل‌های gitignore. تو در تو فقط موجودیت‌های زیرپوشه‌‌های خود را نادیده می‌گیرند. (مخزن اصلی سورس هسته لیوکس در فایل gitignore. خود ۲۰۶ فایل را نادیده می‌گیرد.) این موضوع فراتر از بخش این کتاب است که درباره جزئیات چندین فایل gitignore. بگوییم. اگر به دنبال جزئیات بیشتری هستید دستور man gitignore را در ترمینال وارد کنید.

نمایش وضعیت استیج شده‌ها و تغییرات استیج نشده

اگر دستور git status کمی برایتان مبهم است — میخواهید بفهمید دقیقا چه چیزی را تغییر داده‌اید!، نه فقط چه فایل‌هایی تغییر کرده است (منظور جزئیات بیشتر در تغییرات اعمال شده است) — می‌توانید از دستور git diff استفاده کنید. درباره دستور git diff و جزئیات آن بعد می‌گوییم، اما احتما شما از این دستور برای پاسخ به دو سوال استفاده کنید:

چه چیزی تغییر کرده است که هنوز استیج نشده است؟ و چه چیزی را استیج کرده‌اید و منتظر کامیت شدن است؟ با اینکه دستور git status جواب آن سوالات را به صورت خیلی کلی به وسطه لیست کردن نام‌های فایل‌ها خواهد داد، اما git diff جزئیات کار را با دقت تغییر در هر خط نشان می‌دهد که چه خطی اضافه یا حذف شده است.

فرض کنیم که شما فایل README را تغییر داده‌اید و دوباره استیج کرده‌اید و سپس فایل CONTRIBUTING.md را تغییر داده و استیج نکرده‌اید. اگر دستور ‍git status را اجرا کنید، به یکباره چیزی شبیه به خروجی پایین را می‌بینید:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   README

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:   CONTRIBUTING.md

برای دیدن تغییراتی که انجام دادید ولی هنوز استیج نکرده ایده، دستور git diff را بدون هیچ آرگومان دیگری وارد کنید:

$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
 Please include a nice description of your changes when you submit your PR;
 if we have to read the whole diff to figure out why you're contributing
 in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your patch is
+longer than a dozen lines.

 If you are starting to work on a particular area, feel free to submit a PR
 that highlights your work in progress (and note in the PR title that it's

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

اگر شما بخواهید ببینید چه چیزی را استیج کرده‌اید که در کامیت بعدی شما باشد، با اجرا دستور git diff --staged نمایش را ببینید. این دستور آخرین کامیت را با تغییرات استیج مقایسه می‌کند:

$ git diff --staged
diff --git a/README b/README
new file mode 100644
index 0000000..03902a1
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+My Project

خیلی مهم است که دقت کنید که git diff خودش به تنهایی تمام تغییر ایجاد شده را از آخرین تغییرات نشان نمی‌دهد. — فقط تغییراتی که هنوز استیج نشده‌اند. اگر شما تغییراتی را به استیج کنید، git diff خروجی‌ای به شما نمی‌دهد.

برای مثالی دیگر، اگر شما فایل CONTRIBUTING.md را استیج کنید و سپس آن را تغییر دهید، می‌توانید از دستور git diff استفاده کنید و تغییرات ایجاد شده درون فایل که استیج شده‌اند و تغییراتی که استیج نشده‌اند. اگر محیط ما شبیه پایین باشد:

$ git add CONTRIBUTING.md
$ echo '# test line' >> CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   CONTRIBUTING.md

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:   CONTRIBUTING.md

حال می‌توانید از دستور git diff برای دیدن فایل‌هایی که هنوز استیج نشده‌اند استفاده کنید:

$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 643e24f..87f08c8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -119,3 +119,4 @@ at the
 ## Starter Projects

 See our [projects list](https://github.com/libgit2/libgit2/blob/development/PROJECTS.md).
+# test line

و دستور git diff --cached برای دیدن اینکه چه چیزی را اخیرا استیج کرده‌اید (staged-- و cached-- مترادف هستند.)

$ git diff --cached
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
 Please include a nice description of your changes when you submit your PR;
 if we have to read the whole diff to figure out why you're contributing
 in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your patch is
+longer than a dozen lines.

 If you are starting to work on a particular area, feel free to submit a PR
 that highlights your work in progress (and note in the PR title that it's
Note
دستور git diff یک ابزار خارجی است.

ما در آینده از دستور git diff در سراسر این کتاب با موضوعات گوناگونی استفاده خواهیم کرد. راه دیگری وجود دارد که این چنین تغییرات را ببینید یا شاد ترجیح می‌هید که از ابزارهای گرافیکی یا از ابزارهای خارجی نمایش پیشرفت کار استفاده کنید. اگر شما دستور git difftool را به جای دستور git diff اجرا کنید،‌ می‌توانید هرگونه از این تغییرات را در نرم‌افزاری مثل emerge, vimdiff یا هر مورد دیگری ببینید(به علاوه محصولات تجاری دیگر). دستور git difftool --tool-help را اجرا کنید تا ببنید که چه نرم‌افزار بر روی سیستم شما موجود است.

کامیت کردن تغییرات

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

The simplest way to commit is to type git commit:

$ git commit

دستور بالا ادیتو متنی را باز می‌کند. (این ادیتور متن به واسه مقداری در متغییر EDITOR برای محیط شل خود نوشته‌اید اجرا می‌شود — معمولا vim یا emacs, با این حال شما می‌تواند آن را با هر ادیتور که می‌خواهید پیکربندی کنید. با وارد کردن دستور git config --global core.editor همانطور که در بخش Getting Started دیدید.)

ادیتور متن زیر را تغییر می‌دهد (این مثال با ادیتور ویم است.)

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Your branch is up-to-date with 'origin/master'.
#
# Changes to be committed:
#	new file:   README
#	modified:   CONTRIBUTING.md
#
~
~
~
".git/COMMIT_EDITMSG" 9L, 283C

می‌توانید ببینید که پیام کامیت پیش فرض شامل آخرین خروجی دستور git status است و یک خط خالی در بالای آن. شما می‌توانید تمام این پیام‌ها را حذف کنید و پیام خودتان را بنویسید، یا می‌توانید همانطور رها کنید تا بعدا به شما کمک کند تا دقیقا چیزی که کامیت کرده بودید را به یاد آورید. برای بیشتر واضح بود یادآور چیزی که تغییر دادید، می‌توانید از آپشن v- برای دستور git commit استفاده کنید. این کار همچنین تفاوت تغییرات داخل ادیتور را قرار می‌دهد، پس می‌توانید ببینید دقیقا چه تغییراتی را کامیت می‌کنید. وقتی از ادیتور خارج می‌شوید، گیت کامیت مورد نظر شما را با پیام کامیتی که نوشته‌اید می‌سازد(همراه توضیحات و تفاوت‌‌ها به صورت خطی)

از سویی دیگر، شما می‌توانید پیام کامیت خود را به صورت یک همراه با دستور git commit با آپشن m- بنویسید،‌ مانند مثال زیر:

$ git commit -m "Story 182: fix benchmarks for speed"
[master 463dc4f] Story 182: fix benchmarks for speed
 2 files changed, 2 insertions(+)
 create mode 100644 README

حالا شما اولین کامیت خود را ساختید! می‌توانید ببینید که کامیتی که ساختید چند خروجی درباره خودش به شما می‌دهد: بر روی کدام برنچ کامیت انجام شده است (master)، کد هش SHA-1 خودش (463dc4f)، چه مقدار از فایل‌ها تغییر کرده‌اند و آمارهایی درباره خط‌هایی که اضافه یا حذف شده‌اند در همان کامیت جاری.

به یاد داشته باشید که آن کامیت اسنپ‌شاتی را ثبت می‌کند شما در موقعیت استیج آماده سازی کرده‌اید. هر چیزی که شما استیج نکرده‌اید همچنان با عنوان فایل تغییر یافته باقی مانده‌ است؛ شما می‌توانید کامیت دیگری بسازید و آن را به تاریخچه‌ی تغییرات خود اضافه کنید. هر زمانی که یک کامیت جدید ایفا می‌کنید، شما اسنپ‌شاتی از پروژه خود می‌سازید که در هر زمان می‌توانید پروژه را به همان اسنپ‌شات برگردانید یا مقایسه کنید.

رد کردن موقعیت استیج

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

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
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:   CONTRIBUTING.md

no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m 'Add new benchmarks'
[master 83e38c7] Add new benchmarks
 1 file changed, 5 insertions(+), 0 deletions(-)

دقت کنید که چرا نباید دستور git add برای فایل CONTRIBUTING.md در این مورد اجرا کنید قبل از اینکه کامیت کنید. به این دلیل است که آپشن a- تمام فایل‌‌هایی است که تغییر کرده‌اند. این گزینه‌ی راحتی است اما مراقب باشید؛ بعضی وقت‌‌ها باعث می‌شود که شما تغییراتی که نمی‌خواهید را شامل کنید.

حذف‌ کردن فایل

برای حذف یک فایل از گیت،‌ باید آن را از حالت ترکت حذف کنید(درست‌تر بگوییم، آن را از موقعیت استیج حذف کنید) و بعد کامیت کنید. دستور git rm این کار را می‌کند و همچنین فایل را از پوشه کاریتان حذف می‌کند پس شما آن را به عنوان یک فایل آن‌ترکت شده نخواهید دید.

اگر به سادگی فایل را از پوشه کاریتان حذف کنید،‌ نام فایل را زیر تیتر ``Changed but not updated`` می‌بینید و در خروجی git status شما به (آن وضعیت unstaged) می‌گوید.

$ rm PROJECTS.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    PROJECTS.md

no changes added to commit (use "git add" and/or "git commit -a")

سپس، اگر دستور git rm را اجرا کنید، گیت فایل را با عنوان فایل حذف شده آن را استیج می‌کند:

$ git rm PROJECTS.md
rm 'PROJECTS.md'
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    PROJECTS.md

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

امکان مفید دیگری شاید بخواهید انجام دهید برای نگه‌داشتن فایل در پوشه کاریتان، اما آن را از محیط استیج حذف کرده‌اید. در زبانی دیگر، شاید بخوایید آن را در حافظه سخت خود نگه‌دارید ولی نمی‌‌خواهید گیت آن را به هیچ عنوان دنبال کند. این یک دستور به شدت به درد بخور است چرا اگه فراموش کرده‌اید چیزی را به gitignore. اضافه کنید و تصادفا آن را استیج کرده‌اید، مانند یک فایل لاگ بزرگ یا کلی فایل ‍a. کامپایل شده. به راحتی از آپشن cached-- استفاده کنید:

$ git rm --cached README

شما می‌توانید از الگو‌های پوشه‌ها، فایل‌ها و فایل‌های اصلی در دستور git rm استفاده کنید. که به این معنی است شمامی‌توانید اینگونه عمل کنید:

$ git rm log/\*.log

به بک‌اسلش(‍\) در مقابل * دقت کنید. این کار لازم است چون گیت این کار را به علاوه فایل‌های توسعه خودش بر روی فایل‌های توسعه شما هم اعمال می‌کند. این دستور تمام فایل‌های توسعه که با پسوند log. هستند درون پوشته /log را حذف می‌کند. یا شما می‌توانید چیزی شبیه به دستور زیر را اجرا کنید:

$ git rm \*~

این دستور تمام فایل‌هایی که نام آن‌ها با یک ~ تمام می‌شود را حذف می‌کند.

جابه‌جایی فایل‌ها

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

بنابراین شاید یکم گیج کننده باشد که گیت دستوری به نام mv دارد. اگر بخواهید نام یک فایل را در گیت تغییر دهید، می‌توانید دستوری شبیه به زیر را اجرا کنید:

$ git mv file_from file_to

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

$ git mv README.md README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README

با این حال، این معادل اجرا کردن دستوری شبیه زیر است:

$ mv README.md README
$ git rm README.md
$ git add README

گیت فهمید که یک تغییر نام ضمنی است، پس اصلامهم نیست که شما فایلی را با دستور mv تغییر نام دهید. تنها تفاوت اصلی این است که git mv یک دستور است به جای سه دستور — صرفا یک تابع برای آسودگی کار است. مهم‌تر از هر چیزی این است که شما می‌توانید از هر ابزاری برای تغییر نام یک فایل استفاده کنید.