diff --git a/book/08-customizing-git/sections/attributes.asc b/book/08-customizing-git/sections/attributes.asc index 965cbbed..42fb5dc5 100644 --- a/book/08-customizing-git/sections/attributes.asc +++ b/book/08-customizing-git/sections/attributes.asc @@ -1,45 +1,53 @@ -=== Git Attributes +=== Git Attributes (ویژگی‌های گیت) (((attributes))) -Some of these settings can also be specified for a path, so that Git applies those settings only for a subdirectory or subset of files. -These path-specific settings are called Git attributes and are set either in a `.gitattributes` file in one of your directories (normally the root of your project) or in the `.git/info/attributes` file if you don't want the attributes file committed with your project. +برخی از این تنظیمات را می‌توان برای یک مسیر خاص نیز مشخص کرد، به‌طوری که گیت این تنظیمات را فقط برای یک زیرپوشه یا مجموعه‌ای از فایل‌ها اعمال کند. این تنظیمات خاص مسیر به عنوان ویژگی‌های گیت شناخته می‌شوند و یا در یک فایل `.gitattributes` در یکی از پوشه‌های شما (معمولاً ریشه پروژه‌تان) تنظیم می‌شوند، یا در فایل `.git/info/attributes` اگر نمی‌خواهید فایل ویژگی‌ها همراه با پروژه‌تان در مخزن ثبت (commit) شود. -Using attributes, you can do things like specify separate merge strategies for individual files or directories in your project, tell Git how to diff non-text files, or have Git filter content before you check it into or out of Git. -In this section, you'll learn about some of the attributes you can set on your paths in your Git project and see a few examples of using this feature in practice. - -==== Binary Files +با استفاده از ویژگی‌ها، می‌توانید کارهایی مانند مشخص کردن استراتژی‌های ادغام (merge) جداگانه برای فایل‌ها یا پوشه‌های خاص در پروژه‌تان انجام دهید، به گیت بگویید چگونه فایل‌های غیرمتنی را مقایسه (diff) کند، یا گیت را وادار کنید که محتوا را قبل از ثبت کردن یا بیرون کشیدن از مخزن فیلتر کند. در این بخش، درباره برخی از ویژگی‌هایی که می‌توانید روی مسیرهای پروژه گیت خود تنظیم کنید یاد خواهید گرفت و چند مثال عملی از استفاده از این قابلیت را خواهید دید. +==== فایل‌های باینری (((binary files))) -One cool trick for which you can use Git attributes is telling Git which files are binary (in cases it otherwise may not be able to figure out) and giving Git special instructions about how to handle those files. -For instance, some text files may be machine generated and not diffable, whereas some binary files can be diffed. -You'll see how to tell Git which is which. -===== Identifying Binary Files +یک ترفند جالب که می‌توانید از ویژگی‌های گیت برای آن استفاده کنید، این است که به گیت بگویید کدام فایل‌ها باینری هستند (در مواردی که ممکن است خودش نتواند تشخیص دهد) و دستورالعمل‌های خاصی برای نحوه برخورد با آن فایل‌ها به گیت بدهید. + +برای مثال، برخی فایل‌های متنی ممکن است توسط ماشین تولید شده باشند و قابل مقایسه (diff) نباشند، در حالی که بعضی فایل‌های باینری می‌توانند مقایسه شوند. + +در اینجا خواهید دید که چگونه به گیت بگویید کدام فایل از کدام نوع است. + +===== Identifying Binary Files (شناسایی فایل‌های باینری) + +برخی فایل‌ها به نظر می‌رسند که فایل‌های متنی هستند، اما از هر نظر باید به‌عنوان داده‌های باینری در نظر گرفته شوند. + +برای مثال، پروژه‌های Xcode در macOS شامل فایلی هستند که به `.pbxproj` ختم می‌شود. این فایل در واقع یک مجموعه داده JSON (فرمت داده جاوااسکریپت متنی ساده) است که توسط محیط توسعه (IDE) روی دیسک نوشته شده و تنظیمات ساخت پروژه و موارد مشابه را ثبت می‌کند. + +اگرچه از نظر فنی یک فایل متنی است (چون تماماً UTF-8 است)، اما نمی‌خواهید آن را به‌عنوان فایل متنی معمولی در نظر بگیرید، زیرا در واقع یک پایگاه داده سبک است – اگر دو نفر آن را تغییر دهند، نمی‌توانید محتوای آن را ادغام (merge) کنید و مقایسه‌ها (diff) معمولاً مفید نیستند. -Some files look like text files but for all intents and purposes are to be treated as binary data. -For instance, Xcode projects on macOS contain a file that ends in `.pbxproj`, which is basically a JSON (plain-text JavaScript data format) dataset written out to disk by the IDE, which records your build settings and so on. -Although it's technically a text file (because it's all UTF-8), you don't want to treat it as such because it's really a lightweight database – you can't merge the contents if two people change it, and diffs generally aren't helpful. -The file is meant to be consumed by a machine. -In essence, you want to treat it like a binary file. +این فایل برای استفاده توسط ماشین طراحی شده است. -To tell Git to treat all `pbxproj` files as binary data, add the following line to your `.gitattributes` file: +در حقیقت، شما می‌خواهید آن را مثل یک فایل باینری behand کنید. + +برای اینکه به گیت بگویید همه فایل‌های `pbxproj` را به‌عنوان داده‌های باینری در نظر بگیرد، خط زیر را به فایل `.gitattributes` خود اضافه کنید: [source,ini] ---- *.pbxproj binary ---- -Now, Git won't try to convert or fix CRLF issues; nor will it try to compute or print a diff for changes in this file when you run `git show` or `git diff` on your project. +حالا گیت دیگر سعی نمی‌کند مسائل مربوط به CRLF را تبدیل یا اصلاح کند؛ همچنین هنگام اجرای `git show` یا `git diff` در پروژه‌تان، برای تغییرات این فایل، مقایسه‌ای (diff) محاسبه یا چاپ نخواهد کرد. + +===== Diffing Binary Files (مقایسه فایل‌های باینری) + +شما همچنین می‌توانید از قابلیت ویژگی‌های گیت برای مقایسه مؤثر فایل‌های باینری استفاده کنید. -===== Diffing Binary Files +این کار را با گفتن به گیت انجام می‌دهید که چگونه داده‌های باینری شما را به یک فرمت متنی تبدیل کند که بتوان آن را از طریق مقایسه معمولی (diff) بررسی کرد. -You can also use the Git attributes functionality to effectively diff binary files. -You do this by telling Git how to convert your binary data to a text format that can be compared via the normal diff. +ابتدا، از این تکنیک برای حل یکی از آزاردهنده‌ترین مشکلات شناخته‌شده برای بشریت استفاده خواهید کرد: کنترل نسخه اسناد مایکروسافت ورد. -First, you'll use this technique to solve one of the most annoying problems known to humanity: version-controlling Microsoft Word documents. -Everyone knows that Word is the most horrific editor around, but oddly, everyone still uses it. -If you want to version-control Word documents, you can stick them in a Git repository and commit every once in a while; but what good does that do? -If you run `git diff` normally, you only see something like this: +همه می‌دانند که ورد وحشتناک‌ترین ویرایشگر موجود است، اما عجیب اینکه هنوز همه از آن استفاده می‌کنند. + +اگر بخواهید اسناد ورد را کنترل نسخه کنید، می‌توانید آن‌ها را در یک مخزن گیت قرار دهید و هر از گاهی آن‌ها را ثبت (commit) کنید؛ اما این چه فایده‌ای دارد؟ + +اگر به‌طور عادی `git diff` را اجرا کنید، فقط چیزی شبیه این خواهید دید: [source,console] ---- @@ -48,25 +56,30 @@ diff --git a/chapter1.docx b/chapter1.docx index 88839c4..4afcb7c 100644 Binary files a/chapter1.docx and b/chapter1.docx differ ---- +شما نمی‌توانید مستقیماً دو نسخه را مقایسه کنید، مگر اینکه آن‌ها را بیرون بکشید و به‌صورت دستی بررسی کنید، درست است؟ -You can't directly compare two versions unless you check them out and scan them manually, right? -It turns out you can do this fairly well using Git attributes. -Put the following line in your `.gitattributes` file: +معلوم می‌شود که با استفاده از ویژگی‌های گیت می‌توانید این کار را به‌خوبی انجام دهید. +خط زیر را در فایل `.gitattributes` خود قرار دهید: [source,ini] ---- *.docx diff=word ---- -This tells Git that any file that matches this pattern (`.docx`) should use the ``word'' filter when you try to view a diff that contains changes. -What is the ``word'' filter? -You have to set it up. -Here you'll configure Git to use the `docx2txt` program to convert Word documents into readable text files, which it will then diff properly. +این به گیت می‌گوید که هر فایلی که با این الگو مطابقت دارد (`.docx`) باید از فیلتر "word" استفاده + کند زمانی که شما سعی می‌کنید تفاوت‌هایی را مشاهده کنید که شامل تغییرات است. + فیلتر "word" چیست؟ + شما باید آن را تنظیم کنید. + در اینجا شما گیت را پیکربندی می‌کنید تا از برنامه `docx2txt` برای تبدیل اسناد Word به فایل‌های متنی + قابل خواندن استفاده کند، که سپس به درستی مقایسه می‌شوند. + +ابتدا، باید `docx2txt` را نصب کنید؛ می‌توانید آن را از https://sourceforge.net/projects/docx2txt[] دانلود کنید. -First, you'll need to install `docx2txt`; you can download it from https://sourceforge.net/projects/docx2txt[]. -Follow the instructions in the `INSTALL` file to put it somewhere your shell can find it. -Next, you'll write a wrapper script to convert output to the format Git expects. -Create a file that's somewhere in your path called `docx2txt`, and add these contents: +دستورالعمل‌های موجود در فایل `INSTALL` را دنبال کنید تا آن را در جایی قرار دهید که شِل شما بتواند آن را پیدا کند. + +سپس، یک اسکریپت پوششی (wrapper script) خواهید نوشت تا خروجی را به فرمتی که گیت انتظار دارد تبدیل کند. + +فایلی به نام `docx2txt` در جایی از مسیر خود ایجاد کنید و این محتوا را به آن اضافه کنید: [source,console] ---- @@ -74,20 +87,23 @@ Create a file that's somewhere in your path called `docx2txt`, and add these con docx2txt.pl "$1" - ---- -Don't forget to `chmod a+x` that file. -Finally, you can configure Git to use this script: +فراموش نکنید که به آن فایل `chmod a+x` بدهید. + در نهایت، می‌توانید گیت را پیکربندی کنید تا از این اسکریپت استفاده کند: [source,console] ---- $ git config diff.word.textconv docx2txt ---- -Now Git knows that if it tries to do a diff between two snapshots, and any of the files end in `.docx`, it should run those files through the ``word'' filter, which is defined as the `docx2txt` program. -This effectively makes nice text-based versions of your Word files before attempting to diff them. +حالا گیت می‌داند که اگر بخواهد بین دو نسخه (snapshot) مقایسه‌ای (diff) انجام دهد و برخی از فایل‌ها به `.docx` ختم شوند، باید آن فایل‌ها را از طریق فیلتر ``word'' اجرا کند، که به‌عنوان برنامه `docx2txt` تعریف شده است. + +این کار به‌طور مؤثری نسخه‌های متنی خوبی از فایل‌های ورد شما ایجاد می‌کند قبل از اینکه بخواهد آن‌ها را مقایسه (diff) کند. + +اینجا یک مثال آورده شده است: فصل اول این کتاب به فرمت ورد تبدیل شده و در یک مخزن گیت ثبت (commit) شده است. -Here's an example: Chapter 1 of this book was converted to Word format and committed in a Git repository. -Then a new paragraph was added. -Here's what `git diff` shows: +سپس یک پاراگراف جدید به آن اضافه شد. + +این چیزی است که `git diff` نشان می‌دهد: [source,console] ---- @@ -97,36 +113,39 @@ index 0b013ca..ba25db5 100644 --- a/chapter1.docx +++ b/chapter1.docx @@ -2,6 +2,7 @@ - This chapter will be about getting started with Git. We will begin at the beginning by explaining some background on version control tools, then move on to how to get Git running on your system and finally how to get it setup to start working with. At the end of this chapter you should understand why Git is around, why you should use it and you should be all setup to do so. - 1.1. About Version Control - What is "version control", and why should you care? Version control is a system that records changes to a file or set of files over time so that you can recall specific versions later. For the examples in this book you will use software source code as the files being version controlled, though in reality you can do this with nearly any type of file on a computer. -+Testing: 1, 2, 3. - If you are a graphic or web designer and want to keep every version of an image or layout (which you would most certainly want to), a Version Control System (VCS) is a very wise thing to use. It allows you to revert files back to a previous state, revert the entire project back to a previous state, compare changes over time, see who last modified something that might be causing a problem, who introduced an issue and when, and more. Using a VCS also generally means that if you screw things up or lose files, you can easily recover. In addition, you get all this for very little overhead. - 1.1.1. Local Version Control Systems - Many people's version-control method of choice is to copy files into another directory (perhaps a time-stamped directory, if they're clever). This approach is very common because it is so simple, but it is also incredibly error prone. It is easy to forget which directory you're in and accidentally write to the wrong file or copy over files you don't mean to. + این فصل درباره شروع به کار با گیت خواهد بود. ما با توضیح برخی از زمینه‌ها در مورد ابزارهای کنترل نسخه شروع خواهیم کرد، سپس به نحوه راه‌اندازی گیت در سیستم شما و در نهایت نحوه تنظیم آن برای شروع کار خواهیم پرداخت. در پایان این فصل شما باید درک کنید که چرا گیت وجود دارد، چرا باید از آن استفاده کنید و باید به طور کامل آماده باشید تا این کار را انجام دهید. + 1.1. درباره کنترل نسخه + کنترل نسخه چیست و چرا باید به آن اهمیت دهید؟ کنترل نسخه سیستمی است که تغییرات را در یک فایل یا مجموعه‌ای از فایل‌ها در طول زمان ثبت می‌کند تا بتوانید نسخه‌های خاصی را بعداً به یاد بیاورید. برای مثال‌ها در این کتاب، شما از کد منبع نرم‌افزار به عنوان فایل‌های تحت کنترل نسخه استفاده خواهید کرد، اگرچه در واقع می‌توانید این کار را با تقریباً هر نوع فایلی در یک کامپیوتر انجام دهید. ++آزمایش: 1، 2، 3. + اگر شما یک طراح گرافیک یا وب هستید و می‌خواهید هر نسخه از یک تصویر یا طرح را نگه دارید (که قطعاً می‌خواهید)، استفاده از یک سیستم کنترل نسخه (VCS) بسیار عاقلانه است. این به شما اجازه می‌دهد تا فایل‌ها را به حالت قبلی برگردانید، کل پروژه را به حالت قبلی برگردانید، تغییرات را در طول زمان مقایسه کنید، ببینید چه کسی آخرین بار چیزی را تغییر داده که ممکن است باعث ایجاد مشکل شود، چه کسی یک مشکل را معرفی کرده و چه زمانی، و بیشتر. استفاده از یک VCS همچنین به طور کلی به این معنی است که اگر چیزها را خراب کنید یا فایل‌ها را گم کنید، می‌توانید به راحتی آن‌ها را بازیابی کنید. علاوه بر این، شما تمام این‌ها را با هزینه بسیار کمی دریافت می‌کنید. + 1.1.1. سیستم‌های کنترل نسخه محلی + روش کنترل نسخه انتخابی بسیاری از مردم این است که فایل‌ها را به یک دایرکتوری دیگر کپی کنند (شاید یک دایرکتوری با زمان‌مهر، اگر آن‌ها باهوش باشند). این رویکرد بسیار رایج است زیرا بسیار ساده است، اما همچنین به شدت مستعد خطاست. به راحتی می‌توان فراموش کرد که در کدام دایرکتوری هستید و به طور تصادفی به فایل اشتباهی بنویسید یا فایل‌هایی را که نمی‌خواهید کپی کنید. ---- -Git successfully and succinctly tells us that we added the string ``Testing: 1, 2, 3.'', which is correct. -It's not perfect – formatting changes wouldn't show up here – but it certainly works. +گیت به طور موفقیت‌آمیز و مختصر به ما می‌گوید که رشته "آزمایش: 1، 2، 3." را اضافه کرده‌ایم، که درست است. + این کامل نیست – تغییرات فرمت در اینجا نشان داده نمی‌شوند – اما قطعاً کار می‌کند. -Another interesting problem you can solve this way involves diffing image files. -One way to do this is to run image files through a filter that extracts their EXIF information – metadata that is recorded with most image formats. -If you download and install the `exiftool` program, you can use it to convert your images into text about the metadata, so at least the diff will show you a textual representation of any changes that happened. -Put the following line in your `.gitattributes` file: +یک مشکل جالب دیگر که می‌توانید اینگونه حل کنید، مقایسه فایل‌های تصویری است. + یک راه برای انجام این کار این است که فایل‌های تصویری را از طریق یک فیلتر که اطلاعات EXIF آن‌ها را استخراج + می‌کند، اجرا کنید – متاداده‌ای که با اکثر فرمت‌های تصویری ثبت می‌شود. + اگر شما برنامه `exiftool` را دانلود و نصب کنید، می‌توانید از آن برای تبدیل تصاویر خود به متن درباره + متاداده استفاده کنید، بنابراین حداقل تفاوت‌ها نمایشی متنی از هر تغییری که اتفاق افتاده است را نشان می‌دهد. + خط زیر را در فایل `.gitattributes` خود قرار دهید: [source,ini] ---- *.png diff=exif ---- -Configure Git to use this tool: +گیت را پیکربندی کنید تا از این ابزار استفاده کند: [source,console] ---- $ git config diff.exif.textconv exiftool ---- -If you replace an image in your project and run `git diff`, you see something like this: +اگر شما یک تصویر را در پروژه خود جایگزین کنید و `git diff` را اجرا کنید، چیزی شبیه به این را + خواهید دید: [source,diff] ---- @@ -150,36 +169,38 @@ index 88839c4..4afcb7c 100644 Color Type : RGB with Alpha ---- -You can easily see that the file size and image dimensions have both changed. +شما به راحتی می‌توانید ببینید که اندازه فایل و ابعاد تصویر هر دو تغییر کرده‌اند. [[_keyword_expansion]] -==== Keyword Expansion +==== Keyword Expansion (گسترش کلیدواژه) (((keyword expansion))) -SVN- or CVS-style keyword expansion is often requested by developers used to those systems. -The main problem with this in Git is that you can't modify a file with information about the commit after you've committed, because Git checksums the file first. -However, you can inject text into a file when it's checked out and remove it again before it's added to a commit. -Git attributes offers you two ways to do this. - -First, you can inject the SHA-1 checksum of a blob into an `$Id$` field in the file automatically. -If you set this attribute on a file or set of files, then the next time you check out that branch, Git will replace that field with the SHA-1 of the blob. -It's important to notice that it isn't the SHA-1 of the commit, but of the blob itself. -Put the following line in your `.gitattributes` file: +گسترش کلیدواژه به سبک SVN یا CVS اغلب توسط توسعه‌دهندگانی که به آن سیستم‌ها عادت دارند درخواست می‌شود. + مشکل اصلی با این در گیت این است که شما نمی‌توانید فایلی را با اطلاعات مربوط به کامیت پس از اینکه کامیت کرده‌اید، + تغییر دهید، زیرا گیت ابتدا checksum فایل را بررسی می‌کند. + با این حال، شما می‌توانید متن را هنگام چک‌اوت به یک فایل تزریق کنید و قبل از اینکه دوباره به یک کامیت اضافه شود، + آن را حذف کنید. + ویژگی‌های گیت به شما دو روش برای انجام این کار ارائه می‌دهد. + +اول، شما می‌توانید checksum SHA-1 یک blob را به یک فیلد `$Id$` در فایل به طور خودکار تزریق کنید. + اگر این ویژگی را بر روی یک فایل یا مجموعه‌ای از فایل‌ها تنظیم کنید، سپس دفعه بعد که این شاخه را چک‌اوت کنید، گیت + آن فیلد را با SHA-1 blob جایگزین می‌کند. + مهم است که توجه داشته باشید که این SHA-1 مربوط به کامیت نیست، بلکه مربوط به خود blob است. + خط زیر را در فایل `.gitattributes` خود قرار دهید: [source,ini] ---- *.txt ident ---- -Add an `$Id$` reference to a test file: +یک مرجع `$Id$` به یک فایل آزمایشی اضافه کنید: [source,console] ---- $ echo '$Id$' > test.txt ---- -The next time you check out this file, Git injects the SHA-1 of the blob: - +دفعه بعد که این فایل را بررسی (checkout) می‌کنید، Git مقدار SHA-1 مربوط به blob را در آن قرار می‌دهد: [source,console] ---- $ rm test.txt @@ -188,31 +209,33 @@ $ cat test.txt $Id: 42812b7653c7b88933f8a9d6cad0ca16714b9bb3 $ ---- -However, that result is of limited use. -If you've used keyword substitution in CVS or Subversion, you can include a datestamp – the SHA-1 isn't all that helpful, because it's fairly random and you can't tell if one SHA-1 is older or newer than another just by looking at them. +با این حال، این نتیجه کاربرد محدودی دارد. +اگر از keyword substitution در CVS یا Subversion استفاده کرده باشید، می‌دانید که می‌توانستید یک datestamp درج کنید – اما SHA-1 چندان مفید نیست، چون نسبتاً تصادفی است و فقط با نگاه کردن به آن نمی‌توانید تشخیص دهید که یک SHA-1 قدیمی‌تر است یا جدیدتر. -It turns out that you can write your own filters for doing substitutions in files on commit/checkout. -These are called ``clean'' and ``smudge'' filters. -In the `.gitattributes` file, you can set a filter for particular paths and then set up scripts that will process files just before they're checked out (``smudge'', see <>) and just before they're staged (``clean'', see <>). -These filters can be set to do all sorts of fun things. +جالب اینجاست که می‌توانید فیلترهای خودتان را برای انجام جایگزینی‌ها روی فایل‌ها هنگام commit/checkout بنویسید. +به این فیلترها `clean` و `smudge` گفته می‌شود. +در فایل .gitattributes می‌توانید یک filter برای مسیرهای خاص تعریف کنید و سپس اسکریپت‌هایی تنظیم کنید که فایل‌ها را درست قبل از اینکه checkout شوند (smudge، مراجعه کنید به <>) و درست قبل از اینکه staged شوند (clean، مراجعه کنید به <>) پردازش کنند. +این فیلترها می‌توانند برای انجام کلی کار جالب تنظیم شوند. [[filters_a]] -.The ``smudge'' filter is run on checkout. -image::images/smudge.png[The ``smudge'' filter is run on checkout.] +.فیلتر "smudge" در زمان چک‌اوت اجرا می‌شود. +image::images/smudge.png[فیلتر "smudge" در زمان چک‌اوت اجرا می‌شود.] [[filters_b]] -.The ``clean'' filter is run when files are staged. -image::images/clean.png[The ``clean'' filter is run when files are staged.] +.فیلتر "clean" در زمان staging اجرا می‌شود. +image::images/clean.png[فیلتر "clean" در زمان staging اجرا می‌شود.] -The original commit message for this feature gives a simple example of running all your C source code through the `indent` program before committing. -You can set it up by setting the filter attribute in your `.gitattributes` file to filter `*.c` files with the ``indent'' filter: +پیام کامیت اصلی برای این ویژگی یک مثال ساده از اجرای تمام کدهای منبع C از طریق برنامه `indent` قبل + از کامیت را ارائه می‌دهد. + شما می‌توانید این را با تنظیم ویژگی فیلتر در فایل `.gitattributes` برای فیلتر `*.c` با + فیلتر "indent" تنظیم کنید: [source,ini] ---- *.c filter=indent ---- -Then, tell Git what the ``indent'' filter does on smudge and clean: +سپس، به گیت بگویید که فیلتر "indent" چه کاری در زمان smudge و clean انجام می‌دهد: [source,console] ---- @@ -220,13 +243,13 @@ $ git config --global filter.indent.clean indent $ git config --global filter.indent.smudge cat ---- -In this case, when you commit files that match `*.c`, Git will run them through the indent program before it stages them and then run them through the `cat` program before it checks them back out onto disk. -The `cat` program does essentially nothing: it spits out the same data that it comes in. -This combination effectively filters all C source code files through `indent` before committing. +در این حالت، زمانی که فایل‌هایی با الگوی `*.c` را commit می‌کنید، Git آن‌ها را پیش از stage شدن از طریق برنامه indent عبور می‌دهد، و سپس قبل از اینکه دوباره آن‌ها را روی دیسک checkout کند، از طریق برنامه `cat` عبور می‌دهد. +برنامه `cat` در اصل هیچ کاری انجام نمی‌دهد: هر داده‌ای که دریافت می‌کند را همان‌طور خارج می‌کند. +این ترکیب باعث می‌شود که تمام فایل‌های سورس C پیش از commit شدن از فیلتر indent عبور کنند. -Another interesting example gets `$Date$` keyword expansion, RCS style. -To do this properly, you need a small script that takes a filename, figures out the last commit date for this project, and inserts the date into the file. -Here is a small Ruby script that does that: +یک مثال جالب دیگر مربوط به گسترش کلیدواژه `$Date$` به سبک RCS است. +برای اینکه این کار به‌درستی انجام شود، به یک اسکریپت کوچک نیاز دارید که یک نام فایل را دریافت کند، تاریخ آخرین commit پروژه را تشخیص دهد و آن تاریخ را در فایل وارد کند. +در ادامه، یک اسکریپت کوچک Ruby آمده است که این کار را انجام می‌دهد: [source,ruby] ---- @@ -236,10 +259,11 @@ last_date = `git log --pretty=format:"%ad" -1` puts data.gsub('$Date$', '$Date: ' + last_date.to_s + '$') ---- -All the script does is get the latest commit date from the `git log` command, stick that into any `$Date$` strings it sees in stdin, and print the results – it should be simple to do in whatever language you're most comfortable in. -You can name this file `expand_date` and put it in your path. -Now, you need to set up a filter in Git (call it `dater`) and tell it to use your `expand_date` filter to smudge the files on checkout. -You'll use a Perl expression to clean that up on commit: +تمام کاری که این اسکریپت انجام می‌دهد این است که تاریخ آخرین commit را از دستور `git log` دریافت می‌کند، آن را در هر رشته‌ی `$Date$` که در stdin می‌بیند جایگذاری می‌کند، و نتیجه را چاپ می‌کند — پیاده‌سازی آن در هر زبانی که با آن راحت هستید باید ساده باشد. +می‌توانید این فایل را با نام `expand_date` ذخیره کرده و آن را در مسیر (path) سیستم خود قرار دهید. + +حالا باید یک فیلتر در Git تنظیم کنید (که مثلاً `dater` نام دارد) و به آن بگویید هنگام checkout فایل‌ها از فیلتر `expand_date` برای smudge کردن استفاده کند. +برای clean کردن هنگام commit نیز از یک عبارت Perl استفاده خواهید کرد تا آن قسمت را پاک‌سازی کند: [source,console] ---- @@ -247,8 +271,8 @@ $ git config filter.dater.smudge expand_date $ git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"' ---- -This Perl snippet strips out anything it sees in a `$Date$` string, to get back to where you started. -Now that your filter is ready, you can test it by setting up a Git attribute for that file that engages the new filter and creating a file with your `$Date$` keyword: +این قطعه کد Perl، هر چیزی را که در رشته‌ی `$Date$` ببیند حذف می‌کند، تا فایل را به حالت اولیه‌اش برگرداند. +حالا که فیلترتان آماده است، می‌توانید آن را با تنظیم یک ویژگی (attribute) در Git برای آن فایل آزمایش کنید؛ ویژگی‌ای که فیلتر جدید را فعال می‌کند، و فایلی بسازید که شامل کلیدواژه‌ی `$Date$` باشد: [source,ini] ---- @@ -260,7 +284,8 @@ date*.txt filter=dater $ echo '# $Date$' > date_test.txt ---- -If you commit those changes and check out the file again, you see the keyword properly substituted: +اگر شما آن تغییرات را کامیت کنید و دوباره فایل را چک‌اوت کنید، می‌بینید که کلیدواژه به درستی جایگزین شده + است: [source,console] ---- @@ -272,35 +297,41 @@ $ cat date_test.txt # $Date: Tue Apr 21 07:26:52 2009 -0700$ ---- -You can see how powerful this technique can be for customized applications. -You have to be careful, though, because the `.gitattributes` file is committed and passed around with the project, but the driver (in this case, `dater`) isn't, so it won't work everywhere. -When you design these filters, they should be able to fail gracefully and have the project still work properly. +می‌توانید ببینید که این تکنیک چقدر برای کاربردهای سفارشی‌سازی‌شده قدرتمند است. +با این حال، باید مراقب باشید؛ چون فایل `.gitattributes` در ریپازیتوری commit می‌شود و همراه با پروژه منتقل می‌گردد، اما driver (در این مثال، `dater`) چنین نیست، بنابراین ممکن است فیلتر در همه‌جا کار نکند. + +زمانی که این فیلترها را طراحی می‌کنید، باید طوری باشند که در صورت عدم وجود یا بروز خطا، به‌صورت «شکست محترمانه» (fail gracefully) عمل کنند و پروژه همچنان بدون مشکل اجرا شود. -==== Exporting Your Repository +==== Exporting Your Repository (خروجی گرفتن از ریپازیتوری) (((archiving))) -Git attribute data also allows you to do some interesting things when exporting an archive of your project. +اطلاعات ویژگی‌های Git (Git attribute data) همچنین به شما این امکان را می‌دهد که هنگام export گرفتن یک آرشیو از پروژه‌تان، کارهای جالبی انجام دهید. -===== `export-ignore` -You can tell Git not to export certain files or directories when generating an archive. -If there is a subdirectory or file that you don't want to include in your archive file but that you do want checked into your project, you can determine those files via the `export-ignore` attribute. +===== `export-ignore` -For example, say you have some test files in a `test/` subdirectory, and it doesn't make sense to include them in the tarball export of your project. -You can add the following line to your Git attributes file: +شما می‌توانید به Git بگویید که هنگام تولید یک آرشیو، برخی فایل‌ها یا دایرکتوری‌ها را صادر نکند. +اگر دایرکتوری یا فایلی وجود دارد که نمی‌خواهید در آرشیو پروژه‌تان گنجانده شود، ولی می‌خواهید آن را در پروژه‌تان commit کنید، می‌توانید با استفاده از ویژگی export-ignore این فایل‌ها را مشخص کنید. +برای مثال، فرض کنید که برخی فایل‌های تست در دایرکتوری test/ دارید و نیازی به گنجاندن آن‌ها در آرشیو tarball پروژه‌تان ندارید. +شما می‌توانید خط زیر را به فایل ویژگی‌های Git خود اضافه کنید: [source,ini] ---- test/ export-ignore ---- -Now, when you run `git archive` to create a tarball of your project, that directory won't be included in the archive. +اکنون، زمانی که شما `git archive` را اجرا می‌کنید تا یک tarball از پروژه خود ایجاد کنید، آن + دایرکتوری در آرشیو گنجانده نخواهد شد. ===== `export-subst` -When exporting files for deployment you can apply `git log`'s formatting and keyword-expansion processing to selected portions of files marked with the `export-subst` attribute. +هنگام صادرات فایل‌ها برای استقرار، می‌توانید پردازش فرمت‌دهی و گسترش کلیدواژه‌های `git log` را به + بخش‌های انتخاب شده از فایل‌ها که با ویژگی `export-subst` علامت‌گذاری شده‌اند، اعمال کنید. -For instance, if you want to include a file named `LAST_COMMIT` in your project, and have metadata about the last commit automatically injected into it when `git archive` runs, you can for example set up your `.gitattributes` and `LAST_COMMIT` files like this: +به عنوان مثال، اگر می‌خواهید فایلی به نام `LAST_COMMIT` را در پروژه خود شامل کنید و اطلاعات + متاداده درباره آخرین کامیت به طور خودکار در آن وارد شود زمانی که `git archive` اجرا می‌شود، + می‌توانید به عنوان مثال فایل‌های `.gitattributes` و `LAST_COMMIT` خود را به این صورت + تنظیم کنید: [source,ini] ---- @@ -314,7 +345,7 @@ $ git add LAST_COMMIT .gitattributes $ git commit -am 'adding LAST_COMMIT file for archives' ---- -When you run `git archive`, the contents of the archived file will look like this: +زمانی که شما `git archive` را اجرا می‌کنید، محتوای فایل آرشیو به این صورت خواهد بود: [source,console] ---- @@ -323,50 +354,51 @@ $ cat ../deployment-testing/LAST_COMMIT Last commit date: Tue Apr 21 08:38:48 2009 -0700 by Scott Chacon ---- -The substitutions can include for example the commit message and any `git notes`, and `git log` can do simple word wrapping: +جایگزینی‌ها می‌توانند شامل به عنوان مثال پیام کامیت و هر `git notes` باشند و `git log` + می‌تواند کارهای ساده‌ای مانند خط‌پیچی را انجام دهد: [source,console] ---- $ echo '$Format:Last commit: %h by %aN at %cd%n%+w(76,6,9)%B$' > LAST_COMMIT $ git commit -am 'export-subst uses git log'\''s custom formatter -git archive uses git log'\''s `pretty=format:` processor -directly, and strips the surrounding `$Format:` and `$` -markup from the output. +git archive از پردازشگر pretty=format: git log به طور مستقیم استفاده می‌کند +و علامت‌گذاری محاطی $Format: و $ +را از خروجی حذف می‌کند. ' $ git archive @ | tar xfO - LAST_COMMIT Last commit: 312ccc8 by Jim Hill at Fri May 8 09:14:04 2015 -0700 - export-subst uses git log's custom formatter - - git archive uses git log's `pretty=format:` processor directly, and - strips the surrounding `$Format:` and `$` markup from the output. + export-subst از پردازشگر فرمت‌دهی git log به طور مستقیم استفاده می‌کند +و علامت‌گذاری محاطی $Format: و $ +را از خروجی حذف می‌کند. ---- -The resulting archive is suitable for deployment work, but like any exported archive it isn't suitable for further development work. +آرشیو حاصل برای کارهای استقرار مناسب است، اما مانند هر آرشیو صادراتی برای کارهای توسعه‌ای مناسب نیست. -==== Merge Strategies +==== Merge Strategies (استراتژی ادغام) (((merging, strategies))) -You can also use Git attributes to tell Git to use different merge strategies for specific files in your project. -One very useful option is to tell Git to not try to merge specific files when they have conflicts, but rather to use your side of the merge over someone else's. -This is helpful if a branch in your project has diverged or is specialized, but you want to be able to merge changes back in from it, and you want to ignore certain files. -Say you have a database settings file called `database.xml` that is different in two branches, and you want to merge in your other branch without messing up the database file. -You can set up an attribute like this: +شما همچنین می‌توانید از ویژگی‌های Git برای این استفاده کنید که به Git بگویید از استراتژی‌های ادغام مختلف برای فایل‌های خاص در پروژه‌تان استفاده کند. +یکی از گزینه‌های بسیار مفید این است که به Git بگویید که هنگام بروز تضاد (conflict)، سعی نکند فایل‌های خاصی را ادغام کند، بلکه به‌جای آن از نسخه‌ی خودتان استفاده کند. + +این گزینه مفید است اگر یک شاخه در پروژه‌تان انشعاب پیدا کرده یا تخصصی شده باشد، ولی می‌خواهید تغییرات آن را دوباره ادغام کنید و برخی فایل‌ها را نادیده بگیرید. +فرض کنید شما یک فایل تنظیمات پایگاه داده به نام database.xml دارید که در دو شاخه متفاوت است و می‌خواهید شاخه‌ی دیگر را بدون خراب کردن فایل پایگاه داده ادغام کنید. +شما می‌توانید ویژگی‌ای به این شکل تنظیم کنید: [source,ini] ---- database.xml merge=ours ---- -And then define a dummy `ours` merge strategy with: +و سپس یک استراتژی ادغام جعلی `ours` را با: [source,console] ---- $ git config --global merge.ours.driver true ---- -If you merge in the other branch, instead of having merge conflicts with the `database.xml` file, you see something like this: +اگر شاخه‌ی دیگر را ادغام کنید، به‌جای اینکه تضادهای ادغامی با فایل `database.xml` مشاهده کنید، چیزی شبیه به این خواهید دید: [source,console] ---- @@ -375,4 +407,4 @@ Auto-merging database.xml Merge made by recursive. ---- -In this case, `database.xml` stays at whatever version you originally had. +در این حالت، `database.xml` در هر نسخه‌ای که شما در ابتدا داشتید باقی می‌ماند. diff --git a/book/08-customizing-git/sections/config.asc b/book/08-customizing-git/sections/config.asc index 435366bf..79a34597 100644 --- a/book/08-customizing-git/sections/config.asc +++ b/book/08-customizing-git/sections/config.asc @@ -1,86 +1,102 @@ [[_git_config]] -=== Git Configuration +=== Git Configuration (پیکربندی گیت) (((git commands, config))) -As you read briefly in <>, you can specify Git configuration settings with the `git config` command. -One of the first things you did was set up your name and email address: +همانطور که به طور مختصر در <> + خواندید، می‌توانید تنظیمات پیکربندی گیت را با دستور `git config` مشخص کنیدپیدا کنید. + یکی از اولین کارهایی که انجام دادید، تنظیم نام و آدرس ایمیل شما بود: [source,console] ---- -$ git config --global user.name "John Doe" -$ git config --global user.email johndoe@example.com +$ git config --global user.name "Your Username" +$ git config --global user.email email@example.com ---- -Now you'll learn a few of the more interesting options that you can set in this manner to customize your Git usage. +اکنون چند گزینه جالب‌تر را یاد خواهید گرفت که می‌توانید به این روش برای سفارشی‌سازی استفاده از گیت تنظیم + کنید. -First, a quick review: Git uses a series of configuration files to determine non-default behavior that you may want. -The first place Git looks for these values is in the system-wide `/etc/gitconfig` file, which contains settings that are applied to every user on the system and all of their repositories. -If you pass the option `--system` to `git config`, it reads and writes from this file specifically. +اول، یک مرور سریع: گیت از مجموعه‌ای از فایل‌های پیکربندی برای تعیین رفتار غیر پیش‌فرضی که ممکن است بخواهید + استفاده می‌کند. + اولین جایی که گیت به دنبال این مقادیر می‌گردد، فایل پیکربندی سیستم‌گسترده `/etc/gitconfig` است که شامل + تنظیماتی است که به هر کاربر در سیستم و تمام مخازن آن‌ها اعمال می‌شود. + اگر گزینه `--system` را به `git config` بدهید، به طور خاص از این فایل خوانده و نوشته می‌شود. -The next place Git looks is the `~/.gitconfig` (or `~/.config/git/config`) file, which is specific to each user. -You can make Git read and write to this file by passing the `--global` option. +جای بعدی که گیت به دنبال آن می‌گردد، فایل `~/.gitconfig` (یا `~/.config/git/config`) است که + مختص هر کاربر است. + می‌توانید با دادن گزینه `--global` به گیت بگویید که از این فایل بخواند و بنویسد. -Finally, Git looks for configuration values in the configuration file in the Git directory (`.git/config`) of whatever repository you're currently using. -These values are specific to that single repository, and represent passing the `--local` option to `git config`. -(If you don't specify which level you want to work with, this is the default.) +در نهایت، گیت به دنبال مقادیر پیکربندی در فایل پیکربندی در دایرکتوری گیت (`.git/config`) از هر مخزنی + که در حال حاضر استفاده می‌کنید، می‌گردد. + این مقادیر مختص آن مخزن خاص هستند و نمایانگر دادن گزینه `--local` به `git config` هستند. + (اگر مشخص نکنید که می‌خواهید با کدام سطح کار کنید، این پیش‌فرض است.) -Each of these ``levels'' (system, global, local) overwrites values in the previous level, so values in `.git/config` trump those in `/etc/gitconfig`, for instance. +هر یک از این "سطوح" (سیستم، جهانی، محلی) مقادیر سطح قبلی را بازنویسی می‌کند، بنابراین مقادیر در + `.git/config` بر مقادیر در `/etc/gitconfig` ارجحیت دارند، به عنوان مثال. [NOTE] ==== -Git's configuration files are plain-text, so you can also set these values by manually editing the file and inserting the correct syntax. -It's generally easier to run the `git config` command, though. +فایل‌های پیکربندی گیت متن‌ساده هستند، بنابراین می‌توانید این مقادیر را با ویرایش دستی فایل و وارد کردن + نحو صحیح نیز تنظیم کنید. + با این حال، معمولاً راحت‌تر است که دستور `git config` را اجرا کنید. ==== -==== Basic Client Configuration +==== Basic Client Configuration (پیکربندی پایه کلاینت) -The configuration options recognized by Git fall into two categories: client-side and server-side. -The majority of the options are client-side -- configuring your personal working preferences. -Many, _many_ configuration options are supported, but a large fraction of them are useful only in certain edge cases; we'll cover just the most common and useful options here. -If you want to see a list of all the options your version of Git recognizes, you can run +گزینه‌های پیکربندی که توسط Git شناسایی می‌شوند، به دو دسته تقسیم می‌شوند: سمت کلاینت و سمت سرور. +اکثر گزینه‌ها سمت کلاینت هستند — یعنی پیکربندی ترجیحات کاری شخصی شما. +بسیاری، بسیاری از گزینه‌های پیکربندی پشتیبانی می‌شوند، اما بخش زیادی از آن‌ها تنها در برخی موارد خاص مفید هستند؛ در اینجا فقط به متداول‌ترین و مفیدترین گزینه‌ها خواهیم پرداخت. +اگر می‌خواهید فهرستی از تمام گزینه‌هایی که نسخه Git شما شناسایی می‌کند ببینید، می‌توانید دستور زیر را اجرا کنید: [source,console] ---- $ man git-config ---- -This command lists all the available options in quite a bit of detail. -You can also find this reference material at https://git-scm.com/docs/git-config[]. +این دستور تمام گزینه‌های موجود را با جزئیات کافی لیست می‌کند. +شما همچنین می‌توانید این مواد مرجعی را در آدرس https://git-scm.com/docs/git-config[] پیدا کنید. ===== `core.editor` ((($EDITOR)))((($VISUAL, see $EDITOR))) -By default, Git uses whatever you've set as your default text editor via one of the shell environment variables `VISUAL` or `EDITOR`, or else falls back to the `vi` editor to create and edit your commit and tag messages. -To change that default to something else, you can use the `core.editor` setting: +به طور پیش‌فرض، گیت از هر چیزی که به عنوان ویرایشگر متن پیش‌فرض خود از طریق یکی از متغیرهای محیطی شل `VISUAL` + یا `EDITOR` تنظیم کرده‌اید، استفاده می‌کند، و در غیر این صورت به ویرایشگر `vi` برای + ایجاد و ویرایش پیام‌های کامیت و برچسب‌ها بازمی‌گردد. + برای تغییر این پیش‌فرض به چیز دیگری، می‌توانید از تنظیم `core.editor` استفاده کنید: [source,console] ---- $ git config --global core.editor emacs ---- -Now, no matter what is set as your default shell editor, Git will fire up Emacs to edit messages. +اکنون، مهم نیست که چه چیزی به عنوان ویرایشگر شل پیش‌فرض شما تنظیم شده باشد، گیت برای ویرایش پیام‌ها، Emacs را + باز می‌کند. ===== `commit.template` (((commit templates))) -If you set this to the path of a file on your system, Git will use that file as the default initial message when you commit. -The value in creating a custom commit template is that you can use it to remind yourself (or others) of the proper format and style when creating a commit message. +اگر این را به مسیر یک فایل در سیستم خود تنظیم کنید، گیت از آن فایل به عنوان پیام اولیه پیش‌فرض هنگام کامیت + استفاده خواهد کرد. + ارزش ایجاد یک الگوی کامیت سفارشی این است که می‌توانید از آن برای یادآوری خود (یا دیگران) در مورد فرمت و سبک + مناسب هنگام ایجاد یک پیام کامیت استفاده کنید. -For instance, consider a template file at `~/.gitmessage.txt` that looks like this: +به عنوان مثال، یک فایل الگو در `~/.gitmessage.txt` که به این شکل باشد: [source,text] ---- -Subject line (try to keep under 50 characters) +خط توضیحات (سعی کنید زیر 50 کاراکتر نگه دارید) -Multi-line description of commit, -feel free to be detailed. +توضیحات چند خطی از کامیت، +احساس راحتی کنید که جزئیات بیشتری اضافه کنید. [Ticket: X] ---- -Note how this commit template reminds the committer to keep the subject line short (for the sake of `git log --oneline` output), to add further detail under that, and to refer to an issue or bug tracker ticket number if one exists. +به یاد داشته باشید که این الگوی کامیت به کامیت‌کننده یادآوری می‌کند که خط موضوع را کوتاه نگه دارد (برای خروجی + `git log --oneline`)، جزئیات بیشتری زیر آن اضافه کند و اگر تیکتی وجود دارد، به شماره تیکت یا ردیاب + اشکال اشاره کند. -To tell Git to use it as the default message that appears in your editor when you run `git commit`, set the `commit.template` configuration value: +برای اینکه به گیت بگویید از آن به عنوان پیام پیش‌فرضی که هنگام اجرای `git commit` در ویرایشگر شما + ظاهر می‌شود استفاده کند، مقدار پیکربندی `commit.template` را تنظیم کنید: [source,console] ---- @@ -88,14 +104,14 @@ $ git config --global commit.template ~/.gitmessage.txt $ git commit ---- -Then, your editor will open to something like this for your placeholder commit message when you commit: +سپس، ویرایشگر شما برای پیام کامیت جایگزین شما به چیزی شبیه به این باز خواهد شد: [source,text] ---- -Subject line (try to keep under 50 characters) +خط موضوع (سعی کنید زیر 50 کاراکتر نگه دارید) -Multi-line description of commit, -feel free to be detailed. +توضیح چندخطی درباره‌ی commit، +برای توضیح جزئیات بیشتر آزاد هستید. [Ticket: X] # Please enter the commit message for your changes. Lines starting @@ -111,33 +127,35 @@ feel free to be detailed. ".git/COMMIT_EDITMSG" 14L, 297C ---- -If your team has a commit-message policy, then putting a template for that policy on your system and configuring Git to use it by default can help increase the chance of that policy being followed regularly. - +اگر تیم شما یک سیاست خاص برای پیام‌های commit دارد، قرار دادن یک الگو برای آن سیاست در سیستم شما و پیکربندی Git برای استفاده از آن به‌طور پیش‌فرض می‌تواند شانس پیروی منظم از آن سیاست را افزایش دهد. ===== `core.pager` (((pager))) -This setting determines which pager is used when Git pages output such as `log` and `diff`. -You can set it to `more` or to your favorite pager (by default, it's `less`), or you can turn it off by setting it to a blank string: + +این تنظیم تعیین می‌کند که کدام پیجر (pager) زمانی که Git خروجی‌هایی مانند log و diff را صفحه‌بندی می‌کند، استفاده شود. +شما می‌توانید آن را به more یا پیجر مورد علاقه‌تان تنظیم کنید (به‌طور پیش‌فرض، less است)، یا می‌توانید آن را با تنظیم کردن به یک رشته خالی غیرفعال کنید: [source,console] ---- $ git config --global core.pager '' ---- -If you run that, Git will page the entire output of all commands, no matter how long they are. +اگر این کار را انجام دهید، گیت تمام خروجی تمام دستورات را صفحه‌بندی می‌کند، مهم نیست که چقدر طولانی + هستند. ===== `user.signingkey` (((GPG))) -If you're making signed annotated tags (as discussed in <>), setting your GPG signing key as a configuration setting makes things easier. -Set your key ID like so: + +اگر شما در حال ایجاد تگ‌های verified و حاشیه‌نویسی شده (طبق توضیحات در <>)، تنظیم کردن کلید امضای GPG به‌عنوان یک تنظیم پیکربندی کارها را آسان‌تر می‌کند. +شما می‌توانید شناسه کلید خود را به این صورت تنظیم کنید: [source,console] ---- $ git config --global user.signingkey ---- -Now, you can sign tags without having to specify your key every time with the `git tag` command: +حالا می‌توانید تگ‌ها را بدون نیاز به مشخص کردن کلید خود هر بار با دستور `git tag` امضا کنید: [source,console] ---- @@ -147,14 +165,15 @@ $ git tag -s ===== `core.excludesfile` (((excludes)))(((.gitignore))) -You can put patterns in your project's `.gitignore` file to have Git not see them as untracked files or try to stage them when you run `git add` on them, as discussed in <>. -But sometimes you want to ignore certain files for all repositories that you work with. -If your computer is running macOS, you're probably familiar with `.DS_Store` files. -If your preferred editor is Emacs or Vim, you know about filenames that end with a `~` or `.swp`. +شما می‌توانید الگوهایی را در فایل `.gitignore` پروژه‌تان قرار دهید تا `Git` آن‌ها را به‌عنوان فایل‌های غیرپیگیری‌شده نبیند یا هنگام اجرای دستور `git add` سعی نکند آن‌ها را stage کند، همان‌طور که در <> توضیح داده شده است. -This setting lets you write a kind of global `.gitignore` file. -If you create a `~/.gitignore_global` file with these contents: +اما گاهی اوقات ممکن است بخواهید فایل‌های خاصی را برای تمام ریپازیتوری‌هایی که با آن‌ها کار می‌کنید نادیده بگیرید. +اگر سیستم‌عامل شما macOS است، احتمالاً با فایل‌های .DS_Store آشنا هستید. +اگر ویرایشگر مورد علاقه شما Emacs یا Vim باشد، از فایل‌هایی که با ~ یا .swp تمام می‌شوند، خبر دارید. + +این تنظیم به شما این امکان را می‌دهد که یک فایل .gitignore سراسری بنویسید. +اگر یک فایل `~/.gitignore_global` با این محتوا ایجاد کنید: [source,ini] ---- @@ -163,24 +182,24 @@ If you create a `~/.gitignore_global` file with these contents: .DS_Store ---- -…and you run `git config --global core.excludesfile ~/.gitignore_global`, Git will never again bother you about those files. +... و اگر دستور git config --global core.excludesfile ~/.gitignore_global را اجرا کنید، Git دیگر هیچ‌گاه شما را بابت آن فایل‌ها اذیت نخواهد کرد. ===== `help.autocorrect` (((autocorrect))) -If you mistype a command, it shows you something like this: +اگر یک دستور را اشتباه تایپ کنید، چیزی شبیه به این به شما نشان می‌دهد: [source,console] ---- $ git chekcout master git: 'chekcout' is not a git command. See 'git --help'. -Did you mean this? +آیا منظور شما این بود؟ checkout ---- -Git helpfully tries to figure out what you meant, but it still refuses to do it. -If you set `help.autocorrect` to 1, Git will actually run this command for you: +Git با کمال میل سعی می‌کند بفهمد که شما چه می‌خواستید بگویید، اما هنوز این کار را انجام نمی‌دهد. +اگر گزینه `help.autocorrect` را به 1 تنظیم کنید، Git در واقع این دستور را به‌طور خودکار برای شما اجرا خواهد کرد: [source,console] ---- @@ -190,68 +209,78 @@ Continuing under the assumption that you meant 'checkout' in 0.1 seconds automatically... ---- -Note that ``0.1 seconds'' business. -`help.autocorrect` is actually an integer which represents tenths of a second. -So if you set it to 50, Git will give you 5 seconds to change your mind before executing the autocorrected command. +به یاد داشته باشید که این "0.1 ثانیه" است. + `help.autocorrect` در واقع یک عدد صحیح است که نمایانگر دهم‌های ثانیه است. + بنابراین اگر آن را به 50 تنظیم کنید، گیت به شما 5 ثانیه زمان می‌دهد تا قبل از اجرای دستور اصلاح شده، نظر خود + را تغییر دهید. -==== Colors in Git +==== Colors in Git (رنگ‌ها در گیت) (((color))) -Git fully supports colored terminal output, which greatly aids in visually parsing command output quickly and easily. -A number of options can help you set the coloring to your preference. + +Git به‌طور کامل از خروجی رنگی در ترمینال پشتیبانی می‌کند، که به‌طور قابل توجهی در تجزیه و تحلیل سریع و آسان خروجی دستورات کمک می‌کند. +چندین گزینه وجود دارد که می‌توانند به شما کمک کنند رنگ‌بندی را طبق سلیقه‌تان تنظیم کنید ===== `color.ui` -Git automatically colors most of its output, but there's a master switch if you don't like this behavior. -To turn off all Git's colored terminal output, do this: +گیت به طور خودکار بیشتر خروجی‌های خود را رنگ‌آمیزی می‌کند، اما یک سوئیچ اصلی وجود دارد اگر این رفتار را + نپسندید. + برای خاموش کردن تمام خروجی رنگی ترمینال گیت، این کار را انجام دهید: [source,console] ---- $ git config --global color.ui false ---- -The default setting is `auto`, which colors output when it's going straight to a terminal, but omits the color-control codes when the output is redirected to a pipe or a file. +تنظیم پیش‌فرض `auto` است، که خروجی را زمانی که مستقیماً به ترمینال می‌رود رنگی می‌کند، اما کدهای کنترل رنگ را زمانی که خروجی به یک پایپ یا فایل هدایت می‌شود حذف می‌کند. -You can also set it to `always` to ignore the difference between terminals and pipes. -You'll rarely want this; in most scenarios, if you want color codes in your redirected output, you can instead pass a `--color` flag to the Git command to force it to use color codes. -The default setting is almost always what you'll want. +شما همچنین می‌توانید آن را به `always` تنظیم کنید تا تفاوت بین ترمینال‌ها و پایپ‌ها نادیده گرفته شود. +این گزینه به ندرت مورد نیاز است؛ در بیشتر سناریوها، اگر بخواهید کدهای رنگی را در خروجی هدایت‌شده‌تان داشته باشید، می‌توانید به‌جای آن یک پرچم `--color` به دستور Git اضافه کنید تا مجبور شود از کدهای رنگی استفاده کند. +تنظیم پیش‌فرض تقریباً همیشه همان چیزی است که شما نیاز دارید. ===== `color.*` -If you want to be more specific about which commands are colored and how, Git provides verb-specific coloring settings. -Each of these can be set to `true`, `false`, or `always`: +اگر می‌خواهید دقیق‌تر مشخص کنید که کدام دستورات رنگی شوند و چگونه، Git تنظیمات رنگ‌بندی خاص برای هر دستور فراهم کرده است. +هر یک از این‌ها می‌تواند به یکی از مقادیر `true،` `false` یا `always` تنظیم شود: color.branch color.diff color.interactive color.status -In addition, each of these has subsettings you can use to set specific colors for parts of the output, if you want to override each color. -For example, to set the meta information in your diff output to blue foreground, black background, and bold text, you can run +علاوه بر این، هر یک از این تنظیمات دارای زیرتنظیماتی هستند که می‌توانید از آن‌ها برای تنظیم رنگ‌های خاص برای بخش‌های مختلف خروجی استفاده کنید، اگر بخواهید هر رنگ را به‌طور جداگانه تنظیم کنید. +برای مثال، برای تنظیم اطلاعات متا در خروجی `diff` به رنگ پیش‌زمینه آبی، پس‌زمینه سیاه و متن برجسته، می‌توانید دستور زیر را اجرا کنید: [source,console] ---- $ git config --global color.diff.meta "blue black bold" ---- -You can set the color to any of the following values: `normal`, `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, or `white`. -If you want an attribute like bold in the previous example, you can choose from `bold`, `dim`, `ul` (underline), `blink`, and `reverse` (swap foreground and background). +شما می‌توانید رنگ را به هر یک از مقادیر زیر تنظیم کنید: `normal`، `black`، + `red`، `green`، `yellow`، `blue`، `magenta`، + `cyan`، یا `white`. + اگر می‌خواهید ویژگی‌ای مانند بولد در مثال قبلی داشته باشید، می‌توانید از `bold`، `dim`، + `ul` (زیرخط)، `blink` و `reverse` (معکوس کردن پیش‌زمینه و پس‌زمینه) انتخاب + کنید. [[_external_merge_tools]] -==== External Merge and Diff Tools +==== External Merge and Diff Tools (ابزارهای خارجی برای ادغام و مقایسه) (((mergetool)))(((difftool))) -Although Git has an internal implementation of diff, which is what we've been showing in this book, you can set up an external tool instead. -You can also set up a graphical merge-conflict-resolution tool instead of having to resolve conflicts manually. -We'll demonstrate setting up the Perforce Visual Merge Tool (P4Merge) to do your diffs and merge resolutions, because it's a nice graphical tool and it's free. +اگرچه Git یک پیاده‌سازی داخلی از diff دارد، که همان چیزی است که در این کتاب نشان داده‌ایم، شما می‌توانید به جای آن از یک ابزار خارجی استفاده کنید. +همچنین می‌توانید یک ابزار گرافیکی برای حل تضادهای ادغام (merge conflicts) تنظیم کنید، به جای اینکه مجبور باشید تضادها را به‌صورت دستی حل کنید. +در اینجا، نحوه تنظیم ابزار Perforce Visual Merge Tool (P4Merge) برای انجام diffها و حل تضادهای ادغام را نشان خواهیم داد، زیرا این یک ابزار گرافیکی خوب و رایگان است. -If you want to try this out, P4Merge works on all major platforms, so you should be able to do so. -We'll use path names in the examples that work on macOS and Linux systems; for Windows, you'll have to change `/usr/local/bin` to an executable path in your environment. +اگر می‌خواهید این را امتحان کنید، P4Merge بر روی تمامی پلتفرم‌های اصلی کار می‌کند، بنابراین باید قادر به استفاده از آن باشید. +ما از مسیرهای فایل در مثال‌ها استفاده خواهیم کرد که بر روی سیستم‌های macOS و Linux کار می‌کنند؛ برای ویندوز، شما باید `/usr/local/bin` را به مسیری اجرایی در محیط خود تغییر دهید. -To begin, https://www.perforce.com/product/components/perforce-visual-merge-and-diff-tools[download P4Merge from Perforce]. -Next, you'll set up external wrapper scripts to run your commands. -We'll use the macOS path for the executable; in other systems, it will be where your `p4merge` binary is installed. -Set up a merge wrapper script named `extMerge` that calls your binary with all the arguments provided: +برای شروع، https://www.perforce.com/product/components/perforce-visual-merge-and-diff-tools[P4Merge + را از Perforce دانلود کنید]. + سپس، شما اسکریپت‌های wrapper خارجی را برای اجرای دستورات خود تنظیم خواهید کرد. + ما از مسیر macOS برای اجرایی استفاده خواهیم کرد؛ در سیستم‌های دیگر، این جایی خواهد بود که باینری + `p4merge` شما نصب شده است. + یک اسکریپت wrapper ادغام به نام `extMerge` تنظیم کنید که باینری شما را با تمام آرگومان‌های ارائه شده + فراخوانی کند: [source,console] ---- @@ -260,15 +289,17 @@ $ cat /usr/local/bin/extMerge /Applications/p4merge.app/Contents/MacOS/p4merge $* ---- -The diff wrapper checks to make sure seven arguments are provided and passes two of them to your merge script. -By default, Git passes the following arguments to the diff program: +wrapper diff بررسی می‌کند که آیا هفت آرگومان ارائه شده است و دو تا از آن‌ها را به اسکریپت ادغام شما منتقل + می‌کند. + به طور پیش‌فرض، گیت آرگومان‌های زیر را به برنامه diff منتقل می‌کند: [source] ---- path old-file old-hex old-mode new-file new-hex new-mode ---- -Because you only want the `old-file` and `new-file` arguments, you use the wrapper script to pass the ones you need. +زیرا شما فقط می‌خواهید آرگومان‌های `old-file` و `new-file` را داشته باشید، از اسکریپت + wrapper برای انتقال آن‌هایی که نیاز دارید استفاده می‌کنید. [source,console] ---- @@ -277,7 +308,7 @@ $ cat /usr/local/bin/extDiff [ $# -eq 7 ] && /usr/local/bin/extMerge "$2" "$5" ---- -You also need to make sure these tools are executable: +شما همچنین باید مطمئن شوید که این ابزارها قابل اجرا هستند: [source,console] ---- @@ -285,9 +316,12 @@ $ sudo chmod +x /usr/local/bin/extMerge $ sudo chmod +x /usr/local/bin/extDiff ---- -Now you can set up your config file to use your custom merge resolution and diff tools. -This takes a number of custom settings: `merge.tool` to tell Git what strategy to use, `mergetool..cmd` to specify how to run the command, `mergetool..trustExitCode` to tell Git if the exit code of that program indicates a successful merge resolution or not, and `diff.external` to tell Git what command to run for diffs. -So, you can either run four config commands +اکنون می‌توانید فایل پیکربندی خود را برای استفاده از ابزارهای سفارشی ادغام و تفاوت خود تنظیم کنید. + این نیاز به تعدادی تنظیمات سفارشی دارد: `merge.tool` برای گفتن به گیت که از چه استراتژی استفاده کند، + `mergetool..cmd` برای مشخص کردن نحوه اجرای دستور، `mergetool..trustExitCode` + برای گفتن به گیت که آیا کد خروج آن برنامه نشان‌دهنده یک ادغام موفق است یا خیر، و `diff.external` برای + گفتن به گیت که چه دستوری را برای تفاوت‌ها اجرا کند. + بنابراین، می‌توانید چهار دستور پیکربندی را اجرا کنید [source,console] ---- @@ -297,7 +331,7 @@ $ git config --global mergetool.extMerge.cmd \ $ git config --global mergetool.extMerge.trustExitCode false $ git config --global diff.external extDiff ---- -or you can edit your `~/.gitconfig` file to add these lines: +یا می‌توانید فایل `~/.gitconfig` خود را ویرایش کنید تا این خطوط را اضافه کنید: [source,ini] ---- @@ -310,22 +344,24 @@ or you can edit your `~/.gitconfig` file to add these lines: external = extDiff ---- -After all this is set, if you run diff commands such as this: +پس از تنظیم همه این‌ها، اگر دستورات diff مانند این را اجرا کنید: [source,console] ---- $ git diff 32d1776b1^ 32d1776b1 ---- -Instead of getting the diff output on the command line, Git fires up P4Merge, which looks something like this: +به جای دریافت خروجی diff در خط فرمان، گیت P4Merge را راه‌اندازی می‌کند که چیزی شبیه به این خواهد بود: .P4Merge. image::images/p4merge.png[P4Merge.] -If you try to merge two branches and subsequently have merge conflicts, you can run the command `git mergetool`; it starts P4Merge to let you resolve the conflicts through that GUI tool. +اگر سعی کنید دو شاخه را ادغام کنید و سپس تعارضات ادغام داشته باشید، می‌توانید دستور `git mergetool` + را اجرا کنید؛ این ابزار P4Merge را برای حل تعارضات از طریق آن ابزار GUI راه‌اندازی می‌کند. -The nice thing about this wrapper setup is that you can change your diff and merge tools easily. -For example, to change your `extDiff` and `extMerge` tools to run the KDiff3 tool instead, all you have to do is edit your `extMerge` file: +نکته خوب در مورد این تنظیمات wrapper این است که می‌توانید ابزارهای تفاوت و ادغام خود را به راحتی تغییر دهید. + به عنوان مثال، برای تغییر ابزارهای `extDiff` و `extMerge` به KDiff3، تنها کاری که باید + انجام دهید ویرایش فایل `extMerge` است: [source,console] ---- @@ -334,15 +370,16 @@ $ cat /usr/local/bin/extMerge /Applications/kdiff3.app/Contents/MacOS/kdiff3 $* ---- -Now, Git will use the KDiff3 tool for diff viewing and merge conflict resolution. +اکنون، گیت از ابزار KDiff3 برای مشاهده تفاوت‌ها و حل تعارضات ادغام استفاده خواهد کرد. -Git comes preset to use a number of other merge-resolution tools without your having to set up the cmd configuration. -To see a list of the tools it supports, try this: +گیت به طور پیش‌فرض برای استفاده از تعدادی از ابزارهای دیگر حل تعارضات ادغام بدون نیاز به تنظیم پیکربندی cmd + آماده است. + برای دیدن فهرستی از ابزارهایی که پشتیبانی می‌کند، این کار را امتحان کنید: [source,console] ---- $ git mergetool --tool-help -'git mergetool --tool=' may be set to one of the following: +'git mergetool --tool=' ممکن است به یکی از موارد زیر تنظیم شود: emerge gvimdiff gvimdiff2 @@ -351,7 +388,7 @@ $ git mergetool --tool-help vimdiff vimdiff2 -The following tools are valid, but not currently available: +ابزارهای زیر معتبر هستند، اما در حال حاضر در دسترس نیستند: araxis bc3 codecompare @@ -365,53 +402,58 @@ The following tools are valid, but not currently available: tortoisemerge xxdiff -Some of the tools listed above only work in a windowed -environment. If run in a terminal-only session, they will fail. +برخی از ابزارهای ذکر شده در بالا فقط در یک محیط دارای پنجره کار می‌کنند. اگر در یک جلسه فقط ترمینال اجرا شوند، شکست خواهند خورد. ---- -If you're not interested in using KDiff3 for diff but rather want to use it just for merge resolution, and the kdiff3 command is in your path, then you can run +اگر به استفاده از KDiff3 برای تفاوت‌ها علاقه‌مند نیستید، بلکه فقط می‌خواهید از آن برای حل ادغام استفاده کنید و + دستور kdiff3 در مسیر شما قرار دارد، می‌توانید این دستور را اجرا کنید: [source,console] ---- $ git config --global merge.tool kdiff3 ---- -If you run this instead of setting up the `extMerge` and `extDiff` files, Git will use KDiff3 for merge resolution and the normal Git diff tool for diffs. +اگر این کار را به جای تنظیم فایل‌های `extMerge` و `extDiff` انجام دهید، گیت از KDiff3 + برای حل ادغام و از ابزار diff عادی گیت برای تفاوت‌ها استفاده خواهد کرد. -==== Formatting and Whitespace +==== فرمت‌بندی و فاصله‌گذاری (((whitespace))) -Formatting and whitespace issues are some of the more frustrating and subtle problems that many developers encounter when collaborating, especially cross-platform. -It's very easy for patches or other collaborated work to introduce subtle whitespace changes because editors silently introduce them, and if your files ever touch a Windows system, their line endings might be replaced. -Git has a few configuration options to help with these issues. +مسائل فرمت‌بندی و فاصله‌گذاری برخی از مشکلات آزاردهنده و ظریف هستند که بسیاری از توسعه‌دهندگان هنگام همکاری با + آن‌ها مواجه می‌شوند، به ویژه در کارهای چندپلتفرمی. + بسیار آسان است که وصله‌ها یا سایر کارهای مشترک تغییرات ظریف فاصله‌گذاری را معرفی کنند زیرا ویرایشگرها به طور + خاموش آن‌ها را وارد می‌کنند، و اگر فایل‌های شما هرگز با یک سیستم ویندوزی تماس پیدا کنند، ممکن است انتهای خط + آن‌ها جایگزین شود. + گیت چند گزینه پیکربندی برای کمک به این مسائل دارد. ===== `core.autocrlf` (((crlf)))(((line endings))) -If you're programming on Windows and working with people who are not (or vice-versa), you'll probably run into line-ending issues at some point. -This is because Windows uses both a carriage-return character and a linefeed character for newlines in its files, whereas macOS and Linux systems use only the linefeed character. -This is a subtle but incredibly annoying fact of cross-platform work; many editors on Windows silently replace existing LF-style line endings with CRLF, or insert both line-ending characters when the user hits the enter key. - -Git can handle this by auto-converting CRLF line endings into LF when you add a file to the index, and vice versa when it checks out code onto your filesystem. -You can turn on this functionality with the `core.autocrlf` setting. -If you're on a Windows machine, set it to `true` -- this converts LF endings into CRLF when you check out code: +اگر شما بر روی ویندوز برنامه‌نویسی می‌کنید و با افرادی کار می‌کنید که از سیستم‌عامل‌های دیگری استفاده می‌کنند (یا برعکس)، احتمالاً در یک نقطه با مسائل مربوط به انتهای خط (line-ending) مواجه خواهید شد. +این به این دلیل است که ویندوز هم از کاراکتر بازگشت‌به‌کار (carriage-return) و هم از کاراکتر خط‌خوان (linefeed) برای انتهای خط در فایل‌های خود استفاده می‌کند، در حالی که سیستم‌های macOS و Linux تنها از کاراکتر خط‌خوان استفاده می‌کنند. +این یک واقعیت ظریف ولی بسیار آزاردهنده در کارهای چندپلتفرمی است؛ بسیاری از ویرایشگرهای ویندوز به‌طور بی‌صدا انتهای خط‌های LF موجود را با CRLF جایگزین می‌کنند، یا هنگام فشار دادن کلید Enter هر دو کاراکتر انتهای خط را وارد می‌کنند. +Git می‌تواند این مشکل را با تبدیل خودکار انتهای خط‌های CRLF به LF هنگام افزودن یک فایل به ایندکس و بالعکس هنگام چک‌اوت کد به سیستم‌فایل شما حل کند. +شما می‌توانید این قابلیت را با تنظیم core.autocrlf فعال کنید. +اگر روی یک ماشین ویندوزی کار می‌کنید، آن را به true تنظیم کنید -- این تنظیم انتهای خط‌های LF را به CRLF تبدیل می‌کند زمانی که کد را چک‌اوت می‌کنید: [source,console] ---- $ git config --global core.autocrlf true ---- -If you're on a Linux or macOS system that uses LF line endings, then you don't want Git to automatically convert them when you check out files; however, if a file with CRLF endings accidentally gets introduced, then you may want Git to fix it. -You can tell Git to convert CRLF to LF on commit but not the other way around by setting `core.autocrlf` to input: +اگر شما بر روی یک سیستم Linux یا macOS کار می‌کنید که از انتهای خط LF استفاده می‌کند، پس نمی‌خواهید Git به‌طور خودکار آن‌ها را هنگام چک‌اوت فایل‌ها تبدیل کند؛ اما اگر یک فایل با انتهای خط CRLF به‌طور تصادفی وارد پروژه شود، ممکن است بخواهید Git آن را اصلاح کند. +شما می‌توانید به Git بگویید که هنگام commit، CRLF را به LF تبدیل کند ولی برعکس آن را انجام ندهد، با تنظیم `core.autocrlf` به input: [source,console] ---- $ git config --global core.autocrlf input ---- -This setup should leave you with CRLF endings in Windows checkouts, but LF endings on macOS and Linux systems and in the repository. +این تنظیم باید به شما اجازه دهد که انتهای CRLF را در چک‌اوت‌های ویندوز داشته باشید، اما انتهای LF را در + سیستم‌های macOS و Linux و در مخزن داشته باشید. -If you're a Windows programmer doing a Windows-only project, then you can turn off this functionality, recording the carriage returns in the repository by setting the config value to `false`: +اگر شما یک برنامه‌نویس ویندوز هستید که پروژه‌ای فقط برای ویندوز انجام می‌دهید، می‌توانید این قابلیت را خاموش + کنید و بازگشت‌های کاراکتر را در مخزن با تنظیم مقدار پیکربندی به `false` ثبت کنید: [source,console] ---- @@ -420,16 +462,26 @@ $ git config --global core.autocrlf false ===== `core.whitespace` -Git comes preset to detect and fix some whitespace issues. -It can look for six primary whitespace issues -- three are enabled by default and can be turned off, and three are disabled by default but can be activated. +گیت به طور پیش‌فرض برای شناسایی و اصلاح برخی از مسائل فاصله‌گذاری تنظیم شده است. + می‌تواند به دنبال شش مشکل اصلی فاصله‌گذاری باشد -- سه مورد به طور پیش‌فرض فعال هستند و می‌توانند خاموش شوند، و + سه مورد به طور پیش‌فرض غیرفعال هستند اما می‌توانند فعال شوند. -The three that are turned on by default are `blank-at-eol`, which looks for spaces at the end of a line; `blank-at-eof`, which notices blank lines at the end of a file; and `space-before-tab`, which looks for spaces before tabs at the beginning of a line. +سه موردی که به طور پیش‌فرض فعال هستند `blank-at-eol` است، که به دنبال فضاها در انتهای یک خط + می‌گردد؛ `blank-at-eof`، که خطوط خالی در انتهای یک فایل را شناسایی می‌کند؛ و + `space-before-tab`، که به دنبال فضاها قبل از تب‌ها در ابتدای یک خط می‌گردد. -The three that are disabled by default but can be turned on are `indent-with-non-tab`, which looks for lines that begin with spaces instead of tabs (and is controlled by the `tabwidth` option); `tab-in-indent`, which watches for tabs in the indentation portion of a line; and `cr-at-eol`, which tells Git that carriage returns at the end of lines are OK. +سه موردی که به طور پیش‌فرض غیرفعال هستند اما می‌توانند فعال شوند `indent-with-non-tab` است، که به + دنبال خطوطی می‌گردد که با فضاها به جای تب‌ها شروع می‌شوند (و توسط گزینه `tabwidth` کنترل می‌شود)؛ + `tab-in-indent`، که به دنبال تب‌ها در بخش فاصله‌گذاری یک خط می‌گردد؛ و `cr-at-eol`، که + به گیت می‌گوید که بازگشت‌های کاراکتر در انتهای خطوط اشکالی ندارد. -You can tell Git which of these you want enabled by setting `core.whitespace` to the values you want on or off, separated by commas. -You can disable an option by prepending a `-` in front of its name, or use the default value by leaving it out of the setting string entirely. -For example, if you want all but `space-before-tab` to be set, you can do this (with `trailing-space` being a short-hand to cover both `blank-at-eol` and `blank-at-eof`): +می‌توانید به گیت بگویید که کدام یک از این‌ها را می‌خواهید با تنظیم `core.whitespace` به مقادیر + مورد نظر خود روشن یا خاموش کنید، که با کاما جدا شده‌اند. + می‌توانید یک گزینه را با پیشوند `-` در جلوی نام آن غیرفعال کنید، یا با حذف آن از رشته تنظیم به ارزش + پیش‌فرض برگردید. + به عنوان مثال، اگر می‌خواهید همه به جز `space-before-tab` تنظیم شوند، می‌توانید این کار را انجام + دهید (با `trailing-space` که به عنوان یک کوتاه‌نویس برای پوشش هر دو `blank-at-eol` و + `blank-at-eof` است): [source,console] ---- @@ -437,7 +489,7 @@ $ git config --global core.whitespace \ trailing-space,-space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eol ---- -Or you can specify the customizing part only: +یا می‌توانید فقط قسمت سفارشی‌سازی را مشخص کنید: [source,console] ---- @@ -445,67 +497,72 @@ $ git config --global core.whitespace \ -space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eol ---- -Git will detect these issues when you run a `git diff` command and try to color them so you can possibly fix them before you commit. -It will also use these values to help you when you apply patches with `git apply`. -When you're applying patches, you can ask Git to warn you if it's applying patches with the specified whitespace issues: +گیت این مسائل را زمانی که دستور `git diff` را اجرا می‌کنید شناسایی می‌کند و سعی می‌کند آن‌ها را + رنگ‌آمیزی کند تا بتوانید قبل از کامیت آن‌ها را اصلاح کنید. + همچنین از این مقادیر برای کمک به شما هنگام اعمال وصله‌ها با `git apply` استفاده خواهد کرد. + هنگامی که وصله‌ها را اعمال می‌کنید، می‌توانید از گیت بخواهید که اگر وصله‌هایی با مسائل فاصله‌گذاری مشخص شده را + اعمال می‌کند، به شما هشدار دهد: [source,console] ---- $ git apply --whitespace=warn ---- -Or you can have Git try to automatically fix the issue before applying the patch: +یا می‌توانید از گیت بخواهید که قبل از اعمال وصله، سعی کند مشکل را به طور خودکار اصلاح کند: [source,console] ---- $ git apply --whitespace=fix ---- -These options apply to the `git rebase` command as well. -If you've committed whitespace issues but haven't yet pushed upstream, you can run `git rebase --whitespace=fix` to have Git automatically fix whitespace issues as it's rewriting the patches. +این گزینه‌ها همچنین به دستور `git rebase` اعمال می‌شوند. + اگر شما مسائل فاصله‌گذاری را کامیت کرده‌اید اما هنوز به بالا فشار نداده‌اید، می‌توانید دستور `git rebase + --whitespace=fix` را اجرا کنید تا گیت به طور خودکار مسائل فاصله‌گذاری را در حین بازنویسی وصله‌ها اصلاح + کند. -==== Server Configuration +==== Server Configuration (پیکربندی سرور) -Not nearly as many configuration options are available for the server side of Git, but there are a few interesting ones you may want to take note of. +تنظیمات پیکربندی کمتری برای سمت سرور Git موجود است، اما چند گزینه جالب وجود دارد که ممکن است بخواهید به آن‌ها توجه کنید. ===== `receive.fsckObjects` -Git is capable of making sure every object received during a push still matches its SHA-1 checksum and points to valid objects. -However, it doesn't do this by default; it's a fairly expensive operation, and might slow down the operation, especially on large repositories or pushes. -If you want Git to check object consistency on every push, you can force it to do so by setting `receive.fsckObjects` to true: +Git قادر است اطمینان حاصل کند که هر شیء دریافتی در طول یک push همچنان با چک‌سام SHA-1 خود مطابقت دارد و به اشیاء معتبر اشاره می‌کند. +با این حال، این کار به‌طور پیش‌فرض انجام نمی‌شود؛ زیرا یک عملیات نسبتاً پرهزینه است و ممکن است باعث کند شدن عملکرد، به‌ویژه در ریپازیتوری‌های بزرگ یا pushهای حجیم شود. +اگر می‌خواهید Git هر بار که push انجام می‌دهید، سازگاری اشیاء را بررسی کند، می‌توانید با تنظیم `receive.fsckObjects` به true آن را مجبور به انجام این کار کنید: [source,console] ---- $ git config --system receive.fsckObjects true ---- -Now, Git will check the integrity of your repository before each push is accepted to make sure faulty (or malicious) clients aren't introducing corrupt data. +اکنون، گیت قبل از پذیرش هر فشار، یکپارچگی مخزن شما را بررسی می‌کند تا مطمئن شود که مشتریان معیوب (یا مخرب) + داده‌های خراب را معرفی نمی‌کنند. ===== `receive.denyNonFastForwards` -If you rebase commits that you've already pushed and then try to push again, or otherwise try to push a commit to a remote branch that doesn't contain the commit that the remote branch currently points to, you'll be denied. -This is generally good policy; but in the case of the rebase, you may determine that you know what you're doing and can force-update the remote branch with a `-f` flag to your push command. +اگر شما کامیت‌هایی را که قبلاً push کرده‌اید rebase کنید و سپس دوباره تلاش کنید تا آن‌ها را push کنید، یا به‌طور کلی تلاش کنید تا یک کامیت را به یک شاخه‌ی ریموتی که شامل کامیتی نیست که شاخه‌ی ریموتی به آن اشاره می‌کند، ارسال کنید، درخواست شما رد خواهد شد. +این معمولاً سیاست خوبی است؛ اما در مورد rebase، ممکن است تشخیص دهید که می‌دانید چه کاری انجام می‌دهید و می‌توانید با استفاده از پرچم -f در دستور push خود، شاخه‌ی ریموتی را مجبور به به‌روزرسانی کنید. -To tell Git to refuse force-pushes, set `receive.denyNonFastForwards`: +برای اینکه به Git بگویید که force-pushها را رد کند، می‌توانید `receive.denyNonFastForwards` را تنظیم کنید: [source,console] ---- $ git config --system receive.denyNonFastForwards true ---- -The other way you can do this is via server-side receive hooks, which we'll cover in a bit. -That approach lets you do more complex things like deny non-fast-forwards to a certain subset of users. +راه دیگری که می‌توانید این کار را انجام دهید، استفاده از hookهای دریافت (receive hooks) سمت سرور است، که در ادامه به آن‌ها خواهیم پرداخت. +این روش به شما امکان انجام کارهای پیچیده‌تری را می‌دهد، مانند رد کردن non-fast-forward ها برای یک زیرمجموعه خاص از کاربران. ===== `receive.denyDeletes` -One of the workarounds to the `denyNonFastForwards` policy is for the user to delete the branch and then push it back up with the new reference. -To avoid this, set `receive.denyDeletes` to true: +یکی از راه‌حل‌ها برای دور زدن سیاست `denyNonFastForwards` این است که کاربر شاخه را حذف کرده و سپس آن را با مرجع جدید دوباره push کند. +برای جلوگیری از این کار، می‌توانید `receive.denyDeletes` را به true تنظیم کنید: [source,console] ---- $ git config --system receive.denyDeletes true ---- -This denies any deletion of branches or tags -- no user can do it. -To remove remote branches, you must remove the ref files from the server manually. -There are also more interesting ways to do this on a per-user basis via ACLs, as you'll learn in <>. +این تنظیم هرگونه حذف شاخه‌ها یا تگ‌ها را رد می‌کند -- هیچ کاربری قادر به انجام این کار نخواهد بود. +برای حذف شاخه‌های ریموت، باید فایل‌های ref را از سرور به‌طور دستی حذف کنید. +همچنین روش‌های جالب‌تری برای انجام این کار به‌صورت اختصاصی برای هر کاربر از طریق ACLها وجود دارد، همانطور که در <> خواهید آموخت. diff --git a/book/08-customizing-git/sections/hooks.asc b/book/08-customizing-git/sections/hooks.asc index fa80387a..726d2cec 100644 --- a/book/08-customizing-git/sections/hooks.asc +++ b/book/08-customizing-git/sections/hooks.asc @@ -1,126 +1,141 @@ [[_git_hooks]] -=== Git Hooks +=== Git Hooks (هوک‌های گیت) (((hooks))) -Like many other Version Control Systems, Git has a way to fire off custom scripts when certain important actions occur. -There are two groups of these hooks: client-side and server-side. -Client-side hooks are triggered by operations such as committing and merging, while server-side hooks run on network operations such as receiving pushed commits. -You can use these hooks for all sorts of reasons. -==== Installing a Hook +مانند بسیاری از سیستم‌های کنترل نسخه دیگر، Git این امکان را دارد که هنگام وقوع اقدامات مهم، اسکریپت‌های سفارشی را اجرا کند. +این hookها به دو دسته تقسیم می‌شوند: سمت کلاینت (client-side) و سمت سرور (server-side). +Hookهای سمت کلاینت توسط عملیاتی مانند commit و merge فعال می‌شوند، در حالی که hookهای سمت سرور هنگام انجام عملیات شبکه‌ای مانند دریافت pushها اجرا می‌شوند. +شما می‌توانید از این hookها برای اهداف گوناگونی استفاده کنید. -The hooks are all stored in the `hooks` subdirectory of the Git directory. -In most projects, that's `.git/hooks`. -When you initialize a new repository with `git init`, Git populates the hooks directory with a bunch of example scripts, many of which are useful by themselves; but they also document the input values of each script. -All the examples are written as shell scripts, with some Perl thrown in, but any properly named executable scripts will work fine – you can write them in Ruby or Python or whatever language you are familiar with. -If you want to use the bundled hook scripts, you'll have to rename them; their file names all end with `.sample`. +==== Installing a Hook (نصب یک هوک) -To enable a hook script, put a file in the `hooks` subdirectory of your .git directory that is named appropriately (without any extension) and is executable. -From that point forward, it should be called. -We'll cover most of the major hook filenames here. +تمام hookها در زیر‌پوشه‌ای به نام `hooks` در دایرکتوری Git ذخیره می‌شوند. +در اکثر پروژه‌ها، این مسیر برابر است با `.git/hooks`. +وقتی یک ریپازیتوری جدید را با git init مقداردهی اولیه می‌کنید، Git دایرکتوری hooks را با مجموعه‌ای از اسکریپت‌های نمونه پر می‌کند؛ بسیاری از این اسکریپت‌ها به خودی خود مفید هستند، و همچنین نحوه‌ی دریافت ورودی‌ها توسط هر اسکریپت را مستند کرده‌اند. +تمام مثال‌ها به‌صورت shell script نوشته شده‌اند (با کمی کد Perl)، اما هر اسکریپت اجرایی با نام مناسب کار خواهد کرد — می‌توانید آن‌ها را با Ruby، Python یا هر زبان دیگری که با آن آشنایی دارید بنویسید. -==== Client-Side Hooks +اگر می‌خواهید از اسکریپت‌های آماده استفاده کنید، باید آن‌ها را تغییر نام دهید؛ زیرا همه‌ی فایل‌ها پسوند `.sample` دارند. -There are a lot of client-side hooks. -This section splits them into committing-workflow hooks, email-workflow scripts, and everything else. +برای فعال‌سازی یک اسکریپت hook، کافیست یک فایل اجرایی (بدون پسوند) با نام مناسب در زیرپوشه hooks از دایرکتوری .git قرار دهید. +از آن لحظه به بعد، Git در زمان مناسب آن اسکریپت را اجرا خواهد کرد. + +در ادامه، بیشتر نام‌های رایج و کلیدی hookها را بررسی خواهیم کرد. + + +==== Client-Side Hooks (هوک‌های سمت کلاینت) + +تعداد زیادی hook سمت کلاینت وجود دارد. +در این بخش، آن‌ها را به سه دسته تقسیم می‌کنیم: + + hookهای مربوط به فرآیند commit + + اسکریپت‌های مرتبط با گردش‌کار ایمیل (email workflow) + + و سایر موارد متفرقه + +هر دسته نقش خاصی در خودکارسازی یا کنترل دقیق‌تر عملیات در Git دارد. [NOTE] ==== -It's important to note that client-side hooks are *not* copied when you clone a repository. -If your intent with these scripts is to enforce a policy, you'll probably want to do that on the server side; see the example in <>. +نکته‌ی مهم این است که hookهای سمت کلاینت هنگام clone کردن یک ریپازیتوری کپی نمی‌شوند. +اگر هدف شما از این اسکریپت‌ها اعمال یک سیاست یا محدودیت خاص است، بهتر است این کار را در سمت سرور انجام دهید. +برای این منظور، می‌توانید به مثال موجود در بخش <> مراجعه کنید، که نحوه‌ی پیاده‌سازی یک سیاست کنترل‌شده توسط Git را در سمت سرور توضیح می‌دهد. ==== -===== Committing-Workflow Hooks +===== Committing-Workflow Hooks (هوک‌های جریان کاری کامیت) -The first four hooks have to do with the committing process. +چهار هوک اول مربوط به فرآیند کامیت کردن هستند. -The `pre-commit` hook is run first, before you even type in a commit message. -It's used to inspect the snapshot that's about to be committed, to see if you've forgotten something, to make sure tests run, or to examine whatever you need to inspect in the code. -Exiting non-zero from this hook aborts the commit, although you can bypass it with `git commit --no-verify`. -You can do things like check for code style (run `lint` or something equivalent), check for trailing whitespace (the default hook does exactly this), or check for appropriate documentation on new methods. +هوک `pre-commit` اولین هوکی است که اجرا می‌شود، پیش از آن‌که حتی پیام کامیت را بنویسید. +از آن برای بررسی اسنپ‌شاتی که قرار است کامیت شود استفاده می‌شود — برای اینکه مطمئن شوید چیزی را فراموش نکرده‌اید، تست‌ها به‌درستی اجرا می‌شوند، یا هر بررسی دلخواه دیگری روی کد انجام شده است. +اگر اجرای این هوک با وضعیت غیر صفر (non-zero) تمام شود، فرآیند کامیت لغو می‌شود. البته می‌توانید با استفاده از `git commit --no-verify` از آن عبور کنید. +با این هوک می‌توانید کارهایی مثل بررسی استایل کد (مثلاً اجرای lint یا ابزار مشابه)، بررسی وجود فاصله‌ی اضافی در انتهای خطوط (که هوک پیش‌فرض همین کار را انجام می‌دهد)، یا بررسی مستندات مناسب برای متدهای جدید را انجام دهید. -The `prepare-commit-msg` hook is run before the commit message editor is fired up but after the default message is created. -It lets you edit the default message before the commit author sees it. -This hook takes a few parameters: the path to the file that holds the commit message so far, the type of commit, and the commit SHA-1 if this is an amended commit. -This hook generally isn't useful for normal commits; rather, it's good for commits where the default message is auto-generated, such as templated commit messages, merge commits, squashed commits, and amended commits. -You may use it in conjunction with a commit template to programmatically insert information. +هوک `prepare-commit-msg` قبل از باز شدن ادیتور پیام کامیت اجرا می‌شود، اما بعد از تولید پیام پیش‌فرض. +این امکان را می‌دهد که پیش از آن‌که نویسنده پیام را ببیند، آن را ویرایش کنید. +این هوک چند پارامتر دریافت می‌کند: مسیر فایلی که تا اینجا پیام کامیت در آن نوشته شده، نوع کامیت، و اگر کامیت از نوع «اصلاح‌شده» (amended) باشد، SHA-1 آن کامیت. +این هوک معمولاً برای کامیت‌های عادی کاربرد زیادی ندارد؛ بلکه بیشتر در مواردی مفید است که پیام پیش‌فرض کامیت به‌صورت خودکار تولید می‌شود — مثل کامیت‌های حاصل از مرج، اسکواش، یا اصلاح. +می‌توانید از این هوک همراه با یک تمپلیت پیام کامیت استفاده کنید تا اطلاعات موردنظر را به‌صورت برنامه‌نویسی‌شده درج کنید. -The `commit-msg` hook takes one parameter, which again is the path to a temporary file that contains the commit message written by the developer. -If this script exits non-zero, Git aborts the commit process, so you can use it to validate your project state or commit message before allowing a commit to go through. -In the last section of this chapter, we'll demonstrate using this hook to check that your commit message is conformant to a required pattern. +هوک `commit-msg` یک پارامتر دریافت می‌کند: مسیر فایلی موقت که پیام کامیت نوشته‌شده توسط توسعه‌دهنده در آن قرار دارد. +اگر این اسکریپت با وضعیت غیر صفر خاتمه یابد، Git فرآیند کامیت را متوقف می‌کند. +پس می‌توان از آن برای اعتبارسنجی وضعیت پروژه یا بررسی فرمت پیام کامیت پیش از انجام کامیت استفاده کرد. +در انتهای این فصل، مثالی از کاربرد این هوک برای بررسی تطابق پیام کامیت با یک الگوی خاص خواهیم دید. -After the entire commit process is completed, the `post-commit` hook runs. -It doesn't take any parameters, but you can easily get the last commit by running `git log -1 HEAD`. -Generally, this script is used for notification or something similar. +پس از تکمیل کامل فرآیند کامیت، هوک `post-commit` اجرا می‌شود. +این هوک هیچ پارامتری دریافت نمی‌کند، اما به‌راحتی می‌توانید آخرین کامیت را با اجرای git log -1 HEAD به‌دست آورید. +معمولاً از این اسکریپت برای کارهایی مثل ارسال نوتیفیکیشن یا موارد مشابه استفاده می‌شود. [[_email_hooks]] -===== Email Workflow Hooks +===== Email Workflow Hooks (هوک‌های جریان کاری ایمیل) -You can set up three client-side hooks for an email-based workflow. -They're all invoked by the `git am` command, so if you aren't using that command in your workflow, you can safely skip to the next section. -If you're taking patches over email prepared by `git format-patch`, then some of these may be helpful to you. +می‌توانید سه هوک سمت کلاینت برای یک گردش‌کار مبتنی بر ایمیل تنظیم کنید. +تمام این هوک‌ها توسط دستور `git am` فراخوانی می‌شوند، بنابراین اگر در روند کاری‌تان از این دستور استفاده نمی‌کنید، می‌توانید با خیال راحت به بخش بعدی بروید. +اگر وصله‌ها (patch) را از طریق ایمیل و با استفاده از `git format-patch` دریافت می‌کنید، بعضی از این هوک‌ها ممکن است برایتان مفید باشند. -The first hook that is run is `applypatch-msg`. -It takes a single argument: the name of the temporary file that contains the proposed commit message. -Git aborts the patch if this script exits non-zero. -You can use this to make sure a commit message is properly formatted, or to normalize the message by having the script edit it in place. +اولین هوکی که اجرا می‌شود، `applypatch-msg` است. +این هوک یک آرگومان دریافت می‌کند: نام فایل موقتی که پیام کامیت پیشنهادی در آن قرار دارد. +اگر این اسکریپت با وضعیت غیر صفر (non-zero) خارج شود، Git عملیات وصله را متوقف می‌کند. +می‌توانید از این هوک برای اطمینان از قالب مناسب پیام کامیت استفاده کنید، یا اینکه با ویرایش پیام در همان فایل، آن را به شکل دلخواه نرمال‌سازی کنید. -The next hook to run when applying patches via `git am` is `pre-applypatch`. -Somewhat confusingly, it is run _after_ the patch is applied but before a commit is made, so you can use it to inspect the snapshot before making the commit. -You can run tests or otherwise inspect the working tree with this script. -If something is missing or the tests don't pass, exiting non-zero aborts the `git am` script without committing the patch. +هوک بعدی که هنگام اعمال وصله از طریق `git am` اجرا می‌شود، `pre-applypatch` است. +نکته‌ای که ممکن است کمی گیج‌کننده باشد این است که این هوک بعد از اعمال وصله ولی پیش از ایجاد کامیت اجرا می‌شود، بنابراین می‌توانید از آن برای بررسی اسنپ‌شات قبل از ثبت نهایی استفاده کنید. +می‌توانید تست‌ها را اجرا کنید یا به هر شکل دیگری شاخه‌ی کاری را بررسی کنید. +اگر چیزی کم باشد یا تست‌ها رد شوند، با خروجی غیر صفر، اسکریپت `git am` را بدون اعمال کامیت متوقف می‌کند. -The last hook to run during a `git am` operation is `post-applypatch`, which runs after the commit is made. -You can use it to notify a group or the author of the patch you pulled in that you've done so. -You can't stop the patching process with this script. +آخرین هوکی که در فرآیند `git am` اجرا می‌شود، `post-applypatch` است، که بعد از انجام کامیت اجرا می‌شود. +می‌توانید از آن برای اطلاع‌رسانی به گروه یا نویسنده‌ی وصله‌ای که دریافت کرده‌اید استفاده کنید که این وصله دریافت و اعمال شده است. +توجه داشته باشید که این اسکریپت نمی‌تواند فرآیند اعمال وصله را متوقف کند. [[_other_client_hooks]] -===== Other Client Hooks +===== Other Client Hooks (سایر هوک‌های کلاینت) -The `pre-rebase` hook runs before you rebase anything and can halt the process by exiting non-zero. -You can use this hook to disallow rebasing any commits that have already been pushed. -The example `pre-rebase` hook that Git installs does this, although it makes some assumptions that may not match with your workflow. +هوک `pre-rebase` قبل از آنکه چیزی را ریبیس (rebase) کنید، اجرا می‌شود و می‌تواند فرآیند را با خروجی غیر صفر متوقف کند. +از این هوک می‌توانید برای جلوگیری از ریبیس کردن کامیت‌هایی که قبلاً به ریموت پوش شده‌اند استفاده کنید. +مثال هوک `pre-rebase` که توسط Git نصب می‌شود همین کار را انجام می‌دهد، هرچند که ممکن است فرضیاتی داشته باشد که با روند کاری شما هم‌خوانی نداشته باشد. -The `post-rewrite` hook is run by commands that replace commits, such as `git commit --amend` and `git rebase` (though not by `git filter-branch`). -Its single argument is which command triggered the rewrite, and it receives a list of rewrites on `stdin`. -This hook has many of the same uses as the `post-checkout` and `post-merge` hooks. +هوک `post-rewrite` توسط دستوراتی که کامیت‌ها را تغییر می‌دهند اجرا می‌شود، مانند `git commit --amend` و `git rebase` (اما نه `git filter-branch`). +این هوک یک پارامتر دریافت می‌کند که مشخص می‌کند کدام دستور تغییر را ایجاد کرده است، و همچنین فهرستی از تغییرات را از طریق stdin دریافت می‌کند. +این هوک بسیاری از کاربردهای مشابه هوک‌های `post-checkout` و `post-merge` را دارد. -After you run a successful `git checkout`, the `post-checkout` hook runs; you can use it to set up your working directory properly for your project environment. -This may mean moving in large binary files that you don't want source controlled, auto-generating documentation, or something along those lines. +پس از اجرای موفقیت‌آمیز دستور `git checkout`، هوک `post-checkout` اجرا می‌شود. +می‌توانید از این هوک برای تنظیم مناسب دایرکتوری کاری‌تان برای محیط پروژه استفاده کنید. +این ممکن است شامل جابجایی فایل‌های باینری بزرگ که نمی‌خواهید تحت کنترل نسخه باشند، تولید خودکار مستندات، یا کارهای مشابه باشد. -The `post-merge` hook runs after a successful `merge` command. -You can use it to restore data in the working tree that Git can't track, such as permissions data. -This hook can likewise validate the presence of files external to Git control that you may want copied in when the working tree changes. +هوک `post-merge` پس از اجرای موفقیت‌آمیز دستور `merge` اجرا می‌شود. +می‌توانید از این هوک برای بازیابی داده‌ها در دایرکتوری کاری استفاده کنید که Git قادر به پیگیری آن‌ها نیست، مانند داده‌های دسترسی (permissions). +این هوک همچنین می‌تواند وجود فایل‌های خارجی که تحت کنترل Git نیستند را اعتبارسنجی کرده و در صورتی که نیاز باشد آن‌ها را هنگام تغییر دایرکتوری کاری کپی کند. -The `pre-push` hook runs during `git push`, after the remote refs have been updated but before any objects have been transferred. -It receives the name and location of the remote as parameters, and a list of to-be-updated refs through `stdin`. -You can use it to validate a set of ref updates before a push occurs (a non-zero exit code will abort the push). +هوک `pre-push` هنگام اجرای دستور `git push` اجرا می‌شود، پس از آنکه رفرنس‌های ریموت به‌روزرسانی شده‌اند، اما قبل از انتقال هر شیء. +این هوک نام و موقعیت ریموت را به‌عنوان پارامتر دریافت می‌کند، و فهرستی از رفرنس‌های به‌روزرسانی‌شده از طریق `stdin` دریافت می‌کند. +می‌توانید از آن برای اعتبارسنجی مجموعه‌ای از به‌روزرسانی‌های رفرنس پیش از انجام پوش استفاده کنید (خروجی غیر صفر باعث توقف فرآیند پوش می‌شود). -Git occasionally does garbage collection as part of its normal operation, by invoking `git gc --auto`. -The `pre-auto-gc` hook is invoked just before the garbage collection takes place, and can be used to notify you that this is happening, or to abort the collection if now isn't a good time. +Git به‌طور دوره‌ای عملیات جمع‌آوری زباله (garbage collection) را به‌عنوان بخشی از عملکرد معمول خود انجام می‌دهد، با فراخوانی دستور `git gc --auto`. +هوک `pre-auto-gc` درست قبل از انجام جمع‌آوری زباله اجرا می‌شود و می‌توان از آن برای اطلاع‌رسانی به شما در مورد وقوع این عملیات یا برای متوقف کردن جمع‌آوری در صورت عدم مناسب بودن زمان استفاده کرد. -==== Server-Side Hooks +==== Server-Side Hooks (هوک‌های سمت سرور) -In addition to the client-side hooks, you can use a couple of important server-side hooks as a system administrator to enforce nearly any kind of policy for your project. -These scripts run before and after pushes to the server. -The pre hooks can exit non-zero at any time to reject the push as well as print an error message back to the client; you can set up a push policy that's as complex as you wish. +علاوه بر هوک‌های سمت کلاینت، به‌عنوان یک مدیر سیستم می‌توانید از چند هوک مهم سمت سرور برای اعمال هر نوع سیاستی که می‌خواهید برای پروژه‌تان استفاده کنید. +این اسکریپت‌ها قبل و بعد از پوش به سرور اجرا می‌شوند. +هوک‌های پیشین (pre-hooks) در هر زمانی می‌توانند با خروجی غیر صفر (non-zero) پوش را رد کنند و همچنین پیام خطا را به کلاینت ارسال کنند. شما می‌توانید یک سیاست پوش با هر پیچیدگی که می‌خواهید تنظیم کنید. ===== `pre-receive` -The first script to run when handling a push from a client is `pre-receive`. -It takes a list of references that are being pushed from stdin; if it exits non-zero, none of them are accepted. -You can use this hook to do things like make sure none of the updated references are non-fast-forwards, or to do access control for all the refs and files they're modifying with the push. +اولین اسکریپت که هنگام پردازش یک پوش از سمت کلاینت اجرا می‌شود، `pre-receive` است. +این اسکریپت فهرستی از رفرنس‌هایی که در حال پوش شدن هستند را از طریق stdin دریافت می‌کند؛ اگر با خروجی غیر صفر (non-zero) تمام شود، هیچ‌کدام از آن‌ها پذیرفته نمی‌شوند. +می‌توانید از این هوک برای کارهایی مانند اطمینان از اینکه هیچ‌کدام از رفرنس‌های به‌روزرسانی‌شده غیر-فست‌فورواد (non-fast-forwards) نباشند، یا برای اعمال کنترل دسترسی به تمامی رفرنس‌ها و فایل‌هایی که با پوش تغییر می‌کنند، استفاده کنید. ===== `update` -The `update` script is very similar to the `pre-receive` script, except that it's run once for each branch the pusher is trying to update. -If the pusher is trying to push to multiple branches, `pre-receive` runs only once, whereas update runs once per branch they're pushing to. -Instead of reading from stdin, this script takes three arguments: the name of the reference (branch), the SHA-1 that reference pointed to before the push, and the SHA-1 the user is trying to push. -If the update script exits non-zero, only that reference is rejected; other references can still be updated. +اسکریپت `update` شباهت زیادی به اسکریپت `pre-receive` دارد، با این تفاوت که برای هر برنچی که پُشر (pusher) در تلاش است تا به‌روزرسانی کند، یکبار اجرا می‌شود. +اگر پُشر در تلاش باشد که به چندین برنچ پوش کند، pre-receive تنها یکبار اجرا می‌شود، در حالی که update برای هر برنچی که قصد پوش آن را دارد، یکبار اجرا می‌شود. +این اسکریپت به‌جای خواندن از stdin، سه پارامتر دریافت می‌کند: نام رفرنس (برنچ)، SHA-1 که آن رفرنس قبل از پوش به آن اشاره می‌کرد، و SHA-1 که کاربر در تلاش است آن را پوش کند. +اگر اسکریپت update با خروجی غیر صفر (non-zero) تمام شود، تنها همان رفرنس رد می‌شود؛ رفرنس‌های دیگر همچنان می‌توانند به‌روزرسانی شوند. ===== `post-receive` -The `post-receive` hook runs after the entire process is completed and can be used to update other services or notify users. -It takes the same stdin data as the `pre-receive` hook. -Examples include emailing a list, notifying a continuous integration server, or updating a ticket-tracking system – you can even parse the commit messages to see if any tickets need to be opened, modified, or closed. -This script can't stop the push process, but the client doesn't disconnect until it has completed, so be careful if you try to do anything that may take a long time. +هوک `post-receive` پس از اتمام کامل فرآیند اجرا می‌شود و می‌توان از آن برای به‌روزرسانی خدمات دیگر یا اطلاع‌رسانی به کاربران استفاده کرد. +این اسکریپت همان داده‌های `stdin` را که `pre-receive` دریافت می‌کند، می‌گیرد. +مثال‌هایی از این استفاده‌ها شامل ارسال ایمیل به یک فهرست، اطلاع‌رسانی به سرور یکپارچه‌سازی مداوم (CI)، یا به‌روزرسانی سیستم پیگیری تیکت‌ها است – حتی می‌توانید پیام‌های کامیت را تجزیه کرده و بررسی کنید که آیا تیکتی باید باز، ویرایش یا بسته شود. +این اسکریپت نمی‌تواند فرآیند پوش را متوقف کند، اما کلاینت تا زمانی که اسکریپت کامل شود از سرور جدا نمی‌شود، بنابراین اگر قصد دارید کاری انجام دهید که زمان زیادی می‌برد، باید مراقب باشید. \ No newline at end of file diff --git a/book/08-customizing-git/sections/policy.asc b/book/08-customizing-git/sections/policy.asc index 48e759b1..0aace96f 100644 --- a/book/08-customizing-git/sections/policy.asc +++ b/book/08-customizing-git/sections/policy.asc @@ -1,25 +1,28 @@ [[_an_example_git_enforced_policy]] -=== An Example Git-Enforced Policy +=== An Example Git-Enforced Policy (یک مثال از سیاست‌های تحمیلی گیت) (((policy example))) -In this section, you'll use what you've learned to establish a Git workflow that checks for a custom commit message format, and allows only certain users to modify certain subdirectories in a project. -You'll build client scripts that help the developer know if their push will be rejected and server scripts that actually enforce the policies. -The scripts we'll show are written in Ruby; partly because of our intellectual inertia, but also because Ruby is easy to read, even if you can't necessarily write it. -However, any language will work – all the sample hook scripts distributed with Git are in either Perl or Bash, so you can also see plenty of examples of hooks in those languages by looking at the samples. +در این بخش، شما از آنچه که آموخته‌اید برای ایجاد یک گردش‌کار Git استفاده خواهید کرد که قالب پیام کامیت سفارشی را بررسی می‌کند و تنها به برخی از کاربران اجازه می‌دهد که برخی زیرشاخه‌ها (subdirectories) در پروژه را ویرایش کنند. +شما اسکریپت‌های کلاینتی خواهید ساخت که به توسعه‌دهنده اطلاع می‌دهد که آیا پوش او رد خواهد شد یا خیر و همچنین اسکریپت‌های سرور که در واقع این سیاست‌ها را اعمال می‌کنند. -==== Server-Side Hook +اسکریپت‌هایی که در اینجا نشان داده می‌شود به زبان Ruby نوشته شده‌اند؛ بخشی به دلیل تنبلی فکری ما، ولی همچنین به این دلیل که Ruby خواندن آن آسان است، حتی اگر نتوانید حتماً آن را بنویسید. +با این حال، هر زبان برنامه‌نویسی دیگری نیز کار خواهد کرد – تمام اسکریپت‌های هوک نمونه که با Git توزیع شده‌اند، به زبان‌های Perl یا Bash هستند، بنابراین شما می‌توانید نمونه‌های زیادی از هوک‌ها به این زبان‌ها را با نگاه کردن به نمونه‌ها ببینید. -All the server-side work will go into the `update` file in your `hooks` directory. -The `update` hook runs once per branch being pushed and takes three arguments: +==== Server-Side Hook (هوک سمت سرور) -* The name of the reference being pushed to -* The old revision where that branch was -* The new revision being pushed +تمام کارهای سمت سرور در فایل update داخل دایرکتوری hooks شما قرار خواهد گرفت. +هوک update برای هر برنچی که در حال پوش است یکبار اجرا می‌شود و سه پارامتر دریافت می‌کند: -You also have access to the user doing the pushing if the push is being run over SSH. -If you've allowed everyone to connect with a single user (like ``git'') via public-key authentication, you may have to give that user a shell wrapper that determines which user is connecting based on the public key, and set an environment variable accordingly. -Here we'll assume the connecting user is in the `$USER` environment variable, so your update script begins by gathering all the information you need: + نام رفرنس که به آن پوش می‌شود * + + بازنگری قدیمی که آن برنچ به آن اشاره می‌کرد * + + بازنگری جدیدی که در حال پوش است * + +همچنین اگر پوش از طریق SSH انجام شود، به کاربری که در حال پوش است دسترسی خواهید داشت. +اگر به همه اجازه داده‌اید که با یک کاربر واحد (مثل `git`) از طریق احراز هویت کلید عمومی به سرور متصل شوند، ممکن است مجبور باشید به آن کاربر یک پوسته (shell) wrapper بدهید که تشخیص دهد کدام کاربر در حال اتصال است، بر اساس کلید عمومی، و سپس یک متغیر محیطی را مطابق آن تنظیم کند. +در اینجا فرض می‌کنیم که کاربر متصل در متغیر محیطی `$USER` قرار دارد، بنابراین اسکریپت `update` شما با جمع‌آوری تمام اطلاعات مورد نیاز شروع می‌شود: [source,ruby] ---- @@ -34,19 +37,20 @@ puts "Enforcing Policies..." puts "(#{$refname}) (#{$oldrev[0,6]}) (#{$newrev[0,6]})" ---- -Yes, those are global variables. -Don't judge – it's easier to demonstrate this way. +بله، این‌ها متغیرهای جهانی هستند. + قضاوت نکنید – این روش آسان‌تر برای نشان دادن است. [[_enforcing_commit_message_format]] -===== Enforcing a Specific Commit-Message Format +===== Enforcing a Specific Commit-Message Format (تحمیل فرمت خاص پیام کامیت) + +اولین چالش شما این است که اطمینان حاصل کنید که هر پیام کامیت با فرمت خاصی سازگار است. +برای داشتن یک هدف مشخص، فرض کنید که هر پیام باید شامل رشته‌ای مانند `ref: 1234` باشد، زیرا می‌خواهید هر کامیت به یک آیتم کاری در سیستم تیکتینگ شما لینک شود. +شما باید هر کامیتی که در حال پوش است را بررسی کنید، ببینید آیا آن رشته در پیام کامیت وجود دارد یا خیر و اگر آن رشته از هرکدام از کامیت‌ها غایب بود، با خروجی غیر صفر (non-zero) خارج شوید تا پوش رد شود. -Your first challenge is to enforce that each commit message adheres to a particular format. -Just to have a target, assume that each message has to include a string that looks like ``ref: 1234'' because you want each commit to link to a work item in your ticketing system. -You must look at each commit being pushed up, see if that string is in the commit message, and, if the string is absent from any of the commits, exit non-zero so the push is rejected. +برای به‌دست آوردن فهرستی از مقادیر SHA-1 تمام کامیت‌هایی که در حال پوش شدن هستند، می‌توانید مقادیر `$newrev` و `$oldrev` را گرفته و آن‌ها را به یک دستور Git به نام `git rev-list` ارسال کنید. +این در واقع همان دستور `git log` است، اما به طور پیش‌فرض تنها مقادیر SHA-1 را چاپ می‌کند و هیچ اطلاعات دیگری را نمایش نمی‌دهد. +پس برای دریافت فهرستی از تمام SHA-1های کامیت‌هایی که بین یک SHA-1 کامیت و دیگری معرفی شده‌اند، می‌توانید چیزی شبیه به این را اجرا کنید: -You can get a list of the SHA-1 values of all the commits that are being pushed by taking the `$newrev` and `$oldrev` values and passing them to a Git plumbing command called `git rev-list`. -This is basically the `git log` command, but by default it prints out only the SHA-1 values and no other information. -So, to get a list of all the commit SHA-1s introduced between one commit SHA-1 and another, you can run something like this: [source,console] ---- @@ -58,11 +62,11 @@ dfa04c9ef3d5197182f13fb5b9b1fb7717d2222a 17716ec0f1ff5c77eff40b7fe912f9f6cfd0e475 ---- -You can take that output, loop through each of those commit SHA-1s, grab the message for it, and test that message against a regular expression that looks for a pattern. +شما می‌توانید آن خروجی را بگیرید، برای هر کدام از SHA-1های کامیت‌ها حلقه بزنید، پیام مربوط به آن‌ها را بگیرید و سپس آن پیام را با یک عبارت منظم (regular expression) که به دنبال یک الگو می‌گردد تست کنید. -You have to figure out how to get the commit message from each of these commits to test. -To get the raw commit data, you can use another plumbing command called `git cat-file`. -We'll go over all these plumbing commands in detail in <>; but for now, here's what that command gives you: +شما باید راهی پیدا کنید که چگونه پیام کامیت هر کدام از این کامیت‌ها را برای تست بدست آورید. +برای دریافت داده‌های خام کامیت، می‌توانید از دستور دیگری به نام `git cat-file` استفاده کنید. +ما تمام این دستورات پلاومبینگ (plumbing) را به طور دقیق در <> بررسی خواهیم کرد؛ اما برای حالا، در اینجا چیزی است که آن دستور به شما می‌دهد: [source,console] ---- @@ -72,27 +76,27 @@ parent 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 author Scott Chacon 1205815931 -0700 committer Scott Chacon 1240030591 -0700 -Change the version number +تغییر شماره نسخه ---- -A simple way to get the commit message from a commit when you have the SHA-1 value is to go to the first blank line and take everything after that. -You can do so with the `sed` command on Unix systems: +یک روش ساده برای دریافت پیام کامیت از یک کامیت زمانی که SHA-1 آن را دارید این است که به اولین خط خالی بروید و تمام چیزی که بعد از آن آمده را بگیرید. +شما می‌توانید این کار را با دستور sed در سیستم‌های یونیکس انجام دهید: [source,console] ---- $ git cat-file commit ca82a6 | sed '1,/^$/d' -Change the version number +تغییر شماره نسخه ---- -You can use that incantation to grab the commit message from each commit that is trying to be pushed and exit if you see anything that doesn't match. -To exit the script and reject the push, exit non-zero. -The whole method looks like this: +شما می‌توانید از آن روش جادویی برای دریافت پیام کامیت از هر کامیتی که در حال تلاش برای ارسال است استفاده کنید و اگر چیزی را ببینید که با آن مطابقت ندارد، از اسکریپت خارج شوید. +برای خروج از اسکریپت و رد کردن ارسال، باید با خروجی غیرصفر (non-zero) خارج شوید. +کل روش به این صورت است: [source,ruby] ---- $regex = /\[ref: (\d+)\]/ -# enforced custom commit message format +# enforced custom commit message format (تحمیل فرمت پیام کامیت سفارشی) def check_message_format missed_revs = `git rev-list #{$oldrev}..#{$newrev}`.split("\n") missed_revs.each do |rev| @@ -106,20 +110,21 @@ end check_message_format ---- -Putting that in your `update` script will reject updates that contain commits that have messages that don't adhere to your rule. +قرار دادن این در اسکریپت `update` شما، به‌روزرسانی‌هایی را که شامل کامیت‌هایی هستند با پیام‌هایی که با قانون شما هم‌خوانی ندارند، رد خواهد کرد. -===== Enforcing a User-Based ACL System +===== Enforcing a User-Based ACL System (اجرای یک سیستم کنترل دسترسی مبتنی بر کاربر (User-Based ACL System)) -Suppose you want to add a mechanism that uses an access control list (ACL) that specifies which users are allowed to push changes to which parts of your projects. -Some people have full access, and others can only push changes to certain subdirectories or specific files. -To enforce this, you'll write those rules to a file named `acl` that lives in your bare Git repository on the server. -You'll have the `update` hook look at those rules, see what files are being introduced for all the commits being pushed, and determine whether the user doing the push has access to update all those files. +فرض کنید می‌خواهید یک مکانیسم اضافه کنید که از یک فهرست کنترل دسترسی (ACL) استفاده کند و مشخص کند که کدام کاربران مجاز به ارسال تغییرات به کدام بخش‌های پروژه شما هستند. +برخی افراد دسترسی کامل دارند و دیگران تنها می‌توانند تغییرات را به زیرشاخه‌ها یا فایل‌های خاصی ارسال کنند. +برای اعمال این محدودیت‌ها، شما این قوانین را در فایلی به نام `acl` که در مخزن `bare Git` شما روی سرور قرار دارد، می‌نویسید. +هوک `update` شما این قوانین را بررسی می‌کند، مشاهده می‌کند که چه فایل‌هایی برای تمام کامیت‌هایی که در حال ارسال هستند معرفی شده‌اند و تعیین می‌کند که آیا کاربری که در حال ارسال است دسترسی به به‌روزرسانی تمام آن فایل‌ها را دارد یا خیر. -The first thing you'll do is write your ACL. -Here you'll use a format very much like the CVS ACL mechanism: it uses a series of lines, where the first field is `avail` or `unavail`, the next field is a comma-delimited list of the users to which the rule applies, and the last field is the path to which the rule applies (blank meaning open access). -All of these fields are delimited by a pipe (`|`) character. +اولین کاری که باید انجام دهید نوشتن فهرست ACL است. +در اینجا از فرمت مشابهی با مکانیسم ACL در CVS استفاده خواهید کرد: این فرمت شامل یک سری خط است، جایی که اولین فیلد `avail` یا `unavail` است، فیلد بعدی یک لیست از کاربران است که قانون به آن‌ها اعمال می‌شود (که با ویرگول از هم جدا شده‌اند)، و آخرین فیلد مسیر مربوطه است (که اگر خالی باشد یعنی دسترسی باز است). +تمام این فیلدها با یک کاراکتر خط عمودی (`|`) از هم جدا شده‌اند. + +در این مثال، شما چند مدیر، برخی نویسندگان مستندات با دسترسی به دایرکتوری `doc` و یک توسعه‌دهنده که تنها دسترسی به دایرکتوری‌های `lib` و `tests` دارد، دارید. بنابراین فایل ACL شما به این شکل خواهد بود: -In this case, you have a couple of administrators, some documentation writers with access to the `doc` directory, and one developer who only has access to the `lib` and `tests` directories, and your ACL file looks like this: [source] ---- @@ -129,9 +134,9 @@ avail|schacon|lib avail|schacon|tests ---- -You begin by reading this data into a structure that you can use. -In this case, to keep the example simple, you'll only enforce the `avail` directives. -Here is a method that gives you an associative array where the key is the user name and the value is an array of paths to which the user has write access: +شما با خواندن این داده‌ها به یک ساختار که می‌توانید از آن استفاده کنید، شروع می‌کنید. +در این مثال، برای ساده نگه داشتن موضوع، تنها دستورات avail را اعمال خواهید کرد. +در اینجا یک متد آورده شده که یک آرایه انجمنی (associative array) به شما می‌دهد که در آن کلید، نام کاربر و مقدار، یک آرایه از مسیرهایی است که کاربر به آن‌ها دسترسی نوشتن دارد: [source,ruby] ---- @@ -151,7 +156,7 @@ def get_acl_access_data(acl_file) end ---- -On the ACL file you looked at earlier, this `get_acl_access_data` method returns a data structure that looks like this: +در فایل ACL که پیش‌تر مشاهده کردید، این متد `get_acl_access_data` یک ساختار داده‌ای را باز می‌گرداند که به این شکل است: [source,ruby] ---- @@ -165,9 +170,9 @@ On the ACL file you looked at earlier, this `get_acl_access_data` method returns "ebronte"=>["doc"]} ---- -Now that you have the permissions sorted out, you need to determine what paths the commits being pushed have modified, so you can make sure the user who's pushing has access to all of them. +حالا که مجوزها را مرتب کرده‌اید، باید تعیین کنید که کامیت‌های در حال ارسال چه مسیرهایی را تغییر داده‌اند تا مطمئن شوید که کاربری که در حال ارسال است به تمام آن‌ها دسترسی دارد. -You can pretty easily see what files have been modified in a single commit with the `--name-only` option to the `git log` command (mentioned briefly in <>): +شما به راحتی می‌توانید ببینید که چه فایل‌هایی در یک کامیت تغییر کرده‌اند با استفاده از گزینه --name-only در دستور `git log` (که به طور مختصر در <> ذکر شده است): [source,console] ---- @@ -177,11 +182,11 @@ README lib/test.rb ---- -If you use the ACL structure returned from the `get_acl_access_data` method and check it against the listed files in each of the commits, you can determine whether the user has access to push all of their commits: +اگر از ساختار ACL که از متد `get_acl_access_data` باز می‌گردد استفاده کنید و آن را با فایل‌های فهرست شده در هر یک از کامیت‌ها مقایسه کنید، می‌توانید تعیین کنید که آیا کاربر دسترسی به ارسال تمام کامیت‌های خود را دارد یا خیر: [source,ruby] ---- -# only allows certain users to modify certain subdirectories in a project +# فقط اجازه می‌دهد کاربران خاصی زیرپوشه‌های خاصی را در یک پروژه تغییر دهند def check_directory_perms access = get_acl_access_data('acl') @@ -209,14 +214,14 @@ end check_directory_perms ---- -You get a list of new commits being pushed to your server with `git rev-list`. -Then, for each of those commits, you find which files are modified and make sure the user who's pushing has access to all the paths being modified. +شما با استفاده از دستور `git rev-list` فهرستی از کامیت‌های جدیدی که به سرور شما ارسال می‌شوند، دریافت می‌کنید. +سپس برای هر یک از این کامیت‌ها، فایل‌های تغییر یافته را پیدا کرده و مطمئن می‌شوید که کاربری که در حال ارسال است، به تمام مسیرهایی که در حال تغییر هستند، دسترسی دارد. -Now your users can't push any commits with badly formed messages or with modified files outside of their designated paths. +حالا کاربران شما نمی‌توانند کامیت‌هایی با پیام‌های نادرست یا فایل‌هایی که خارج از مسیرهای مجازشان تغییر کرده‌اند، ارسال کنند. -===== Testing It Out +===== Testing It Out `آزمایش آن` -If you run `chmod u+x .git/hooks/update`, which is the file into which you should have put all this code, and then try to push a commit with a non-compliant message, you get something like this: +اگر دستور `chmod u+x .git/hooks/update` را اجرا کنید (که فایلی است که باید تمام این کدها را در آن قرار دهید) و سپس سعی کنید یک کامیت با پیامی غیرمنطبق ارسال کنید، چیزی شبیه به این دریافت خواهید کرد: [source,console] ---- @@ -235,20 +240,19 @@ To git@gitserver:project.git ! [remote rejected] master -> master (hook declined) error: failed to push some refs to 'git@gitserver:project.git' ---- - -There are a couple of interesting things here. -First, you see this where the hook starts running. - +چند نکته جالب در اینجا وجود دارد. +اولاً، شما این را مشاهده می‌کنید که اسکریپت هوک شروع به اجرا می‌کند. +---- [source,console] ---- -Enforcing Policies... +تحمیل سیاست‌ها... (refs/heads/master) (fb8c72) (c56860) ---- -Remember that you printed that out at the very beginning of your update script. -Anything your script echoes to `stdout` will be transferred to the client. +یادآوری کنید که شما این را در ابتدای اسکریپت `update` خود چاپ کردید. +هر چیزی که اسکریپت شما به `stdout` ارسال کند، به کلاینت منتقل خواهد شد. -The next thing you'll notice is the error message. +چیز بعدی که متوجه خواهید شد، پیام خطاست. [source,console] ---- @@ -257,8 +261,8 @@ error: hooks/update exited with error code 1 error: hook declined to update refs/heads/master ---- -The first line was printed out by you, the other two were Git telling you that the update script exited non-zero and that is what is declining your push. -Lastly, you have this: +خط اول توسط شما چاپ شده است، دو خط دیگر از طرف Git است که به شما می‌گوید اسکریپت update با کد غیر صفر خارج شده و این باعث رد شدن ارسال شما شده است. +در نهایت، شما این را مشاهده می‌کنید: [source,console] ---- @@ -267,31 +271,32 @@ To git@gitserver:project.git error: failed to push some refs to 'git@gitserver:project.git' ---- -You'll see a remote rejected message for each reference that your hook declined, and it tells you that it was declined specifically because of a hook failure. +برای هر مرجعی که هوک شما آن را رد کرده است، پیامی مبنی بر رد از طرف ریموت خواهید دید و به شما گفته می‌شود که دقیقاً به دلیل شکست هوک این ارسال رد شده است. -Furthermore, if someone tries to edit a file they don't have access to and push a commit containing it, they will see something similar. -For instance, if a documentation author tries to push a commit modifying something in the `lib` directory, they see +علاوه بر این، اگر کسی سعی کند فایلی را که به آن دسترسی ندارد ویرایش کرده و یک کامیت شامل آن ارسال کند، پیامی مشابه مشاهده خواهد کرد. +برای مثال، اگر یک نویسنده مستندات سعی کند یک کامیت ارسال کند که در آن فایلی در دایرکتوری lib تغییر کرده باشد، او این را مشاهده می‌کند: [source,console] ---- [POLICY] You do not have access to push to lib/test.rb ---- -From now on, as long as that `update` script is there and executable, your repository will never have a commit message without your pattern in it, and your users will be sandboxed. +از این به بعد، تا زمانی که اسکریپت `update` در آن‌جا باشد و قابل اجرا باقی بماند، مخزن شما هرگز کامیتی نخواهد داشت که پیام آن الگوی مورد نظر شما را نداشته باشد، و کاربران شما در محدوده دسترسی مشخص‌شده خود (sandboxed) باقی خواهند ماند. -==== Client-Side Hooks +==== Client-Side Hooks (هوک‌های سمت کلاینت) -The downside to this approach is the whining that will inevitably result when your users' commit pushes are rejected. -Having their carefully crafted work rejected at the last minute can be extremely frustrating and confusing; and furthermore, they will have to edit their history to correct it, which isn't always for the faint of heart. +یکی از معایب این روش، نارضایتی و غرولندی است که اجتناب‌ناپذیر خواهد بود، زمانی که پوش‌های کاربران به دلیل رد شدن کامیت‌ها پذیرفته نمی‌شوند. +رد شدن کارِ با دقت و زحمت انجام‌شده‌ی آن‌ها در لحظه‌ی آخر می‌تواند بسیار ناامیدکننده و گیج‌کننده باشد؛ و علاوه بر این، آن‌ها مجبور خواهند شد تاریخچه‌ی خود را برای اصلاح تغییر دهند، که این کار همیشه برای همه آسان نیست. -The answer to this dilemma is to provide some client-side hooks that users can run to notify them when they're doing something that the server is likely to reject. -That way, they can correct any problems before committing and before those issues become more difficult to fix. -Because hooks aren't transferred with a clone of a project, you must distribute these scripts some other way and then have your users copy them to their `.git/hooks` directory and make them executable. -You can distribute these hooks within the project or in a separate project, but Git won't set them up automatically. +راه‌حل این مشکل، فراهم کردن چند هوک سمت کلاینت (Client-side hooks) است که کاربران بتوانند با اجرای آن‌ها، از احتمال رد شدن تغییرات‌شان توسط سرور مطلع شوند. +به این ترتیب، آن‌ها می‌توانند مشکلات را قبل از کامیت کردن اصلاح کنند و این‌طوری حل آن‌ها ساده‌تر خواهد بود. -To begin, you should check your commit message just before each commit is recorded, so you know the server won't reject your changes due to badly formatted commit messages. -To do this, you can add the `commit-msg` hook. -If you have it read the message from the file passed as the first argument and compare that to the pattern, you can force Git to abort the commit if there is no match: +از آن‌جا که هوک‌ها به‌طور خودکار همراه با کلون یک پروژه منتقل نمی‌شوند، باید این اسکریپت‌ها را از طریقی دیگر منتشر کرده و از کاربران بخواهید آن‌ها را در مسیر `.git/hooks/` کپی کرده و اجرایی (executable) کنند. +می‌توانید این هوک‌ها را درون خود پروژه یا در پروژه‌ای مجزا منتشر کنید، اما گیت به‌صورت خودکار آن‌ها را تنظیم نمی‌کند. + +برای شروع، باید پیام کامیت را درست قبل از ثبت هر کامیت بررسی کنید، تا مطمئن شوید که سرور به‌خاطر فرمت نادرست پیام آن را رد نخواهد کرد. +برای این کار می‌توانید از هوک `commit-msg` استفاده کنید. +اگر این هوک، پیام کامیت را از فایلی که به‌عنوان آرگومان اول دریافت می‌کند بخواند و آن را با الگوی موردنظر مطابقت دهد، می‌توانید با عدم تطابق، گیت را مجبور به توقف فرآیند کامیت کنید: [source,ruby] ---- @@ -307,7 +312,7 @@ if !$regex.match(message) end ---- -If that script is in place (in `.git/hooks/commit-msg`) and executable, and you commit with a message that isn't properly formatted, you see this: +اگر این اسکریپت در مسیر `.git/hooks/commit-msg` قرار گرفته باشد و قابل اجرا (executable) باشد، و شما سعی کنید با پیامی که فرمت درستی ندارد کامیت بزنید، با چنین چیزی مواجه خواهید شد: [source,console] ---- @@ -315,8 +320,8 @@ $ git commit -am 'Test' [POLICY] Your message is not formatted correctly ---- -No commit was completed in that instance. -However, if your message contains the proper pattern, Git allows you to commit: +در آن حالت هیچ کامیتی انجام نشد. + با این حال، اگر پیام شما شامل الگوی مناسب باشد، گیت به شما اجازه می‌دهد که کامیت کنید: [source,console] ---- @@ -325,8 +330,9 @@ $ git commit -am 'Test [ref: 132]' 1 file changed, 1 insertions(+), 0 deletions(-) ---- -Next, you want to make sure you aren't modifying files that are outside your ACL scope. -If your project's `.git` directory contains a copy of the ACL file you used previously, then the following `pre-commit` script will enforce those constraints for you: +در مرحله‌ی بعد، باید مطمئن شوید که فایل‌هایی خارج از محدوده‌ی دسترسی ACL خود را تغییر نمی‌دهید. +اگر دایرکتوری `.git` پروژه‌تان شامل یک نسخه از فایل ACL باشد که قبلاً از آن استفاده کرده‌اید، اسکریپت `pre-commit` زیر این محدودیت‌ها را برایتان اعمال خواهد کرد: + [source,ruby] ---- @@ -358,50 +364,54 @@ end check_directory_perms ---- -This is roughly the same script as the server-side part, but with two important differences. -First, the ACL file is in a different place, because this script runs from your working directory, not from your `.git` directory. -You have to change the path to the ACL file from this +این تقریباً همان اسکریپت بخش سمت سرور است، اما با دو تفاوت مهم. + +اول اینکه، فایل ACL در مکان متفاوتی قرار دارد، زیرا این اسکریپت از دایرکتوری کاری شما اجرا می‌شود، نه از دایرکتوری `.git` شما. + +شما باید مسیر فایل ACL را از این تغییر دهید: [source,ruby] ---- access = get_acl_access_data('acl') ---- -to this: +به این تغییر دهید: [source,ruby] ---- access = get_acl_access_data('.git/acl') ---- -The other important difference is the way you get a listing of the files that have been changed. -Because the server-side method looks at the log of commits, and, at this point, the commit hasn't been recorded yet, you must get your file listing from the staging area instead. -Instead of +تفاوت مهم دیگر در نحوه دریافت فهرست فایل‌هایی است که تغییر کرده‌اند. + +از آنجا که روش سمت سرور به لاگ کامیت‌ها نگاه می‌کند و در این مرحله هنوز کامیت ثبت نشده است، باید فهرست فایل‌های خود را از ناحیه استیجینگ (staging area) دریافت کنید. + +به جای اینکه [source,ruby] ---- files_modified = `git log -1 --name-only --pretty=format:'' #{ref}` ---- -you have to use +شما باید از این استفاده کنید: [source,ruby] ---- files_modified = `git diff-index --cached --name-only HEAD` ---- -But those are the only two differences – otherwise, the script works the same way. -One caveat is that it expects you to be running locally as the same user you push as to the remote machine. -If that is different, you must set the `$user` variable manually. +اما این تنها دو تفاوت هستند – در غیر این صورت، اسکریپت به همان شیوه عمل می‌کند. +یک هشدار این است که اسکریپت انتظار دارد شما به‌طور محلی و با همان کاربری که به ماشین ریموت پوش می‌کنید، در حال اجرا باشید. +اگر این دو کاربر متفاوت هستند، باید متغیر `$user` را به صورت دستی تنظیم کنید. -One other thing we can do here is make sure the user doesn't push non-fast-forwarded references. -To get a reference that isn't a fast-forward, you either have to rebase past a commit you've already pushed up or try pushing a different local branch up to the same remote branch. +یک نکته دیگر که می‌توانیم اینجا انجام دهیم این است که اطمینان حاصل کنیم کاربر مراجع غیر فست-فوروارد را پوش نکند. +برای دریافت یک مرجع که فست-فوروارد نیست، یا باید بازبیس کنید (rebase) و از یک کمیتی که قبلاً پوش کرده‌اید عبور کنید، یا سعی کنید یک شاخه محلی متفاوت را به همان شاخه ریموت پوش کنید. -Presumably, the server is already configured with `receive.denyDeletes` and `receive.denyNonFastForwards` to enforce this policy, so the only accidental thing you can try to catch is rebasing commits that have already been pushed. +احتمالاً سرور از قبل با گزینه‌های `receive.denyDeletes` و `receive.denyNonFastForwards` پیکربندی شده است تا این سیاست را اجرا کند، بنابراین تنها چیزی که می‌توانید به‌طور تصادفی سعی کنید جلوگیری کنید، بازبیس کردن کمیت‌هایی است که قبلاً پوش شده‌اند. -Here is an example pre-rebase script that checks for that. -It gets a list of all the commits you're about to rewrite and checks whether they exist in any of your remote references. -If it sees one that is reachable from one of your remote references, it aborts the rebase. +در اینجا یک مثال از اسکریپت `pre-rebase` آورده شده که این موضوع را بررسی می‌کند. +این اسکریپت فهرستی از تمام کمیت‌هایی که قرار است بازنویسی شوند دریافت می‌کند و بررسی می‌کند که آیا در هر یک از مراجع ریموت شما وجود دارند یا خیر. +اگر کمیتی را ببیند که از یکی از مراجع ریموت شما قابل دسترسی باشد، بازبیس را متوقف می‌کند. [source,ruby] ---- @@ -428,16 +438,16 @@ target_shas.each do |sha| end ---- -This script uses a syntax that wasn't covered in <>. -You get a list of commits that have already been pushed up by running this: +این اسکریپت از دستوری استفاده می‌کند که در <> پوشش داده نشده است. +برای دریافت فهرستی از کمیت‌هایی که قبلاً پوش شده‌اند، باید این دستور را اجرا کنید: [source,ruby] ---- `git rev-list ^#{sha}^@ refs/remotes/#{remote_ref}` ---- -The `SHA^@` syntax resolves to all the parents of that commit. -You're looking for any commit that is reachable from the last commit on the remote and that isn't reachable from any parent of any of the SHA-1s you're trying to push up – meaning it's a fast-forward. +ساختار SHA^@ به تمام والدین آن کمیت اشاره می‌کند. +شما به دنبال هر کمیتی هستید که از آخرین کمیت روی ریموت قابل دسترسی باشد و از هیچ‌یک از والدین SHA-1هایی که قصد دارید پوش کنید، قابل دسترسی نباشد – یعنی یک فست-فوروارد باشد. -The main drawback to this approach is that it can be very slow and is often unnecessary – if you don't try to force the push with `-f`, the server will warn you and not accept the push. -However, it's an interesting exercise and can in theory help you avoid a rebase that you might later have to go back and fix. +اشکال اصلی این روش این است که ممکن است بسیار کند باشد و اغلب ضروری نباشد – اگر شما تلاش نکنید که پوش را با استفاده از `-f` اجباری کنید، سرور به شما هشدار خواهد داد و پوش را قبول نخواهد کرد. +با این حال، این یک تمرین جالب است و به‌طور تئوری می‌تواند به شما کمک کند تا از بازبیس (rebase) جلوگیری کنید، بازبیس‌هایی که ممکن است بعدها نیاز به اصلاح داشته باشند. \ No newline at end of file diff --git a/book/09-git-and-other-scms/sections/client-hg.asc b/book/09-git-and-other-scms/sections/client-hg.asc index e84a6a40..62f76fae 100644 --- a/book/09-git-and-other-scms/sections/client-hg.asc +++ b/book/09-git-and-other-scms/sections/client-hg.asc @@ -1,20 +1,18 @@ -==== Git and Mercurial +==== Git and Mercurial (گیت و مرکیوریال) (((Interoperation with other VCSs, Mercurial))) (((Mercurial))) -The DVCS universe is larger than just Git. -In fact, there are many other systems in this space, each with their own angle on how to do distributed version control correctly. -Apart from Git, the most popular is Mercurial, and the two are very similar in many respects. - -The good news, if you prefer Git's client-side behavior but are working with a project whose source code is controlled with Mercurial, is that there's a way to use Git as a client for a Mercurial-hosted repository. -Since the way Git talks to server repositories is through remotes, it should come as no surprise that this bridge is implemented as a remote helper. -The project's name is git-remote-hg, and it can be found at https://github.com/felipec/git-remote-hg[]. +دنیای سیستم‌های کنترل نسخه توزیع‌شده (DVCS) بزرگ‌تر از فقط گیت است. +در واقع، سیستم‌های زیادی در این فضا وجود دارند که هرکدام رویکرد خاص خود را برای انجام کنترل نسخه توزیع‌شده به‌طور صحیح دارند. +علاوه بر گیت، مرکیوریال محبوب‌ترین سیستم در این فضا است و این دو در بسیاری از جنبه‌ها شباهت زیادی به هم دارند. +خبر خوب این است که اگر شما رفتار کلاینت-سمت گیت را ترجیح می‌دهید اما با پروژه‌ای کار می‌کنید که کد منبع آن با مرکیوریال کنترل می‌شود، راهی وجود دارد که از گیت به‌عنوان یک کلاینت برای مخزن میزبان‌شده با مرکیوریال استفاده کنید. +از آنجا که گیت از طریق ریموت‌ها با مخازن سرور ارتباط برقرار می‌کند، این پل به‌عنوان یک ابزار کمکی ریموت پیاده‌سازی شده است. +نام پروژه git-remote-hg است و می‌توانید آن را در آدرس https://github.com/felipec/git-remote-hg[] پیدا کنید. ===== git-remote-hg -First, you need to install git-remote-hg. -This basically entails dropping its file somewhere in your path, like so: - +اولین قدم این است که git-remote-hg را نصب کنید. +این کار اساساً به این معناست که فایل آن را در مکانی از مسیر خود قرار دهید، به‌طور مثال: [source,console] ---- $ curl -o ~/bin/git-remote-hg \ @@ -22,36 +20,34 @@ $ curl -o ~/bin/git-remote-hg \ $ chmod +x ~/bin/git-remote-hg ---- -…assuming `~/bin` is in your `$PATH`. -Git-remote-hg has one other dependency: the `mercurial` library for Python. -If you have Python installed, this is as simple as: +… فرض بر این است که `~/bin` در متغیر `$PATH` شما قرار دارد. +گیت-ریموت-اچ‌جی یک وابستگی دیگر نیز دارد: کتابخانه `mercurial` برای پایتون. +اگر پایتون نصب شده باشد، این کار به سادگی با دستور زیر انجام می‌شود: + [source,console] ---- $ pip install mercurial ---- +(اگر پایتون نصب نکرده‌اید، به آدرس https://www.python.org/[] بروید و ابتدا آن را نصب کنید.) -(If you don't have Python installed, visit https://www.python.org/[] and get it first.) - -The last thing you'll need is the Mercurial client. -Go to https://www.mercurial-scm.org/[] and install it if you haven't already. - -Now you're ready to rock. -All you need is a Mercurial repository you can push to. -Fortunately, every Mercurial repository can act this way, so we'll just use the "hello world" repository everyone uses to learn Mercurial: +آخرین چیزی که به آن نیاز دارید، کلاینت مرکیوریال است. +به آدرس https://www.mercurial-scm.org/[] بروید و آن را نصب کنید اگر هنوز این کار را نکرده‌اید. +حالا شما آماده هستید که شروع کنید. +تنها چیزی که نیاز دارید، یک مخزن مرکیوریال است که بتوانید به آن پوش کنید. +خوشبختانه، هر مخزن مرکیوریال می‌تواند به این صورت عمل کند، بنابراین ما فقط از مخزن "hello world" که همه برای یادگیری مرکیوریال از آن استفاده می‌کنند، استفاده خواهیم کرد: [source,console] ---- $ hg clone http://selenic.com/repo/hello /tmp/hello ---- -===== Getting Started - -Now that we have a suitable ``server-side'' repository, we can go through a typical workflow. -As you'll see, these two systems are similar enough that there isn't much friction. +===== Getting Started (شروع) -As always with Git, first we clone: +حالا که یک مخزن مناسب "سمت سرور" داریم، می‌توانیم یک روند کاری معمولی را بررسی کنیم. +همان‌طور که خواهید دید، این دو سیستم آن‌قدر مشابه هستند که هیچ‌گونه مشکلی در استفاده از آن‌ها وجود ندارد. +همانطور که همیشه در گیت داریم، ابتدا مخزن را کلون می‌کنیم: [source,console] ---- $ git clone hg::/tmp/hello /tmp/hello-git @@ -61,13 +57,13 @@ $ git log --oneline --graph --decorate * 65bb417 Create a standard 'hello, world' program ---- -You'll notice that working with a Mercurial repository uses the standard `git clone` command. -That's because git-remote-hg is working at a fairly low level, using a similar mechanism to how Git's HTTP/S protocol is implemented (remote helpers). -Since Git and Mercurial are both designed for every client to have a full copy of the repository history, this command makes a full clone, including all the project's history, and does it fairly quickly. +شما متوجه خواهید شد که کار کردن با یک مخزن مرکیوریال از دستور استاندارد `git clone` استفاده می‌کند. +این به این دلیل است که `git-remote-hg` در سطح نسبتاً پایین‌تری عمل می‌کند، به طوری که از مکانیزمی مشابه با نحوه پیاده‌سازی پروتکل HTTP/S گیت (ابزارهای کمکی ریموت) استفاده می‌کند. +از آنجا که گیت و مرکیوریال هر دو به گونه‌ای طراحی شده‌اند که هر کلاینت یک کپی کامل از تاریخچه مخزن داشته باشد، این دستور یک کلون کامل می‌سازد، شامل تمام تاریخچه پروژه، و این کار را نسبتاً سریع انجام می‌دهد. -The log command shows two commits, the latest of which is pointed to by a whole slew of refs. -It turns out some of these aren't actually there. -Let's take a look at what's actually in the `.git` directory: +دستور log دو کمیت را نشان می‌دهد که آخرین آن‌ها توسط مجموعه‌ای از مراجع به آن اشاره شده است. +متوجه می‌شویم که برخی از این مراجع در واقع وجود ندارند. +بیایید نگاهی به آنچه که در دایرکتوری `.git` قرار دارد بیندازیم: [source,console] ---- @@ -91,14 +87,13 @@ $ tree .git/refs 9 directories, 5 files ---- -Git-remote-hg is trying to make things more idiomatically Git-esque, but under the hood it's managing the conceptual mapping between two slightly different systems. -The `refs/hg` directory is where the actual remote refs are stored. -For example, the `refs/hg/origin/branches/default` is a Git ref file that contains the SHA-1 starting with ``ac7955c'', which is the commit that `master` points to. -So the `refs/hg` directory is kind of like a fake `refs/remotes/origin`, but it has the added distinction between bookmarks and branches. - -The `notes/hg` file is the starting point for how git-remote-hg maps Git commit hashes to Mercurial changeset IDs. -Let's explore a bit: +گیت-ریموت-اچ‌جی سعی دارد که کارها را به شیوه‌ای شبیه به گیت انجام دهد، اما در پشت‌صحنه در حال مدیریت نقشه‌برداری مفهومی بین دو سیستم کمی متفاوت است. +دایرکتوری `refs/hg` جایی است که مراجع ریموت واقعی ذخیره می‌شوند. +برای مثال، refs/hg/origin/branches/default یک فایل مرجع گیت است که SHA-1 آن با ac7955c شروع می‌شود، که همان کمیتی است که master به آن اشاره دارد. +بنابراین، دایرکتوری `refs/hg` شبیه به یک `refs/remotes/origin` جعلی است، اما تفاوت اضافی‌ای بین بوک‌مارک‌ها و شاخه‌ها دارد. +فایل `notes/hg` نقطه شروعی برای نحوه‌ی نقشه‌برداری گیت-ریموت-اچ‌جی از هش‌های کمیت گیت به شناسه‌های تغییرات مرکیوریال است. +بیایید کمی بیشتر کاوش کنیم: [source,console] ---- $ cat notes/hg @@ -119,28 +114,21 @@ $ git cat-file -p ac9117f 0a04b987be5ae354b710cefeba0e2d9de7ad41a9 ---- -So `refs/notes/hg` points to a tree, which in the Git object database is a list of other objects with names. -`git ls-tree` outputs the mode, type, object hash, and filename for items inside a tree. -Once we dig down to one of the tree items, we find that inside it is a blob named ``ac9117f'' (the SHA-1 hash of the commit pointed to by `master`), with contents ``0a04b98'' (which is the ID of the Mercurial changeset at the tip of the `default` branch). - -The good news is that we mostly don't have to worry about all of this. -The typical workflow won't be very different from working with a Git remote. +بنابراین `refs/notes/hg` به یک درخت اشاره دارد، که در پایگاه داده اشیاء گیت، لیستی از اشیاء دیگر با نام‌ها است. دستور `git ls-tree` وضعیت، نوع، هش شیء و نام فایل برای آیتم‌های داخل یک درخت را نمایش می‌دهد. زمانی که به یکی از آیتم‌های درخت می‌پردازیم، متوجه می‌شویم که داخل آن یک blob به نام ac9117f (هش SHA-1 کمیتی که به وسیله `master` اشاره شده است) وجود دارد، که محتوای آن 0a04b98 (که شناسه تغییرات Mercurial در نوک شاخه `default` است) می‌باشد. -There's one more thing we should attend to before we continue: ignores. -Mercurial and Git use a very similar mechanism for this, but it's likely you don't want to actually commit a `.gitignore` file into a Mercurial repository. -Fortunately, Git has a way to ignore files that's local to an on-disk repository, and the Mercurial format is compatible with Git, so you just have to copy it over: +خبر خوب این است که بیشتر وقت‌ها نیازی نیست نگران این موضوعات باشیم. روند کاری معمول معمولاً تفاوت زیادی با کار کردن با یک ریموت گیت نخواهد داشت. +یک چیز دیگر وجود دارد که قبل از ادامه باید به آن توجه کنیم: فایل‌های نادیده گرفته شده (ignores). Mercurial و Git از مکانیزم بسیار مشابهی برای این کار استفاده می‌کنند، اما احتمالاً نمی‌خواهید که واقعاً یک فایل `.gitignore` را به یک مخزن Mercurial اضافه کنید. خوشبختانه، Git روشی برای نادیده گرفتن فایل‌ها دارد که مخصوص یک مخزن محلی است، و فرمت Mercurial با Git سازگار است، بنابراین شما فقط باید آن را کپی کنید: [source,console] ---- $ cp .hgignore .git/info/exclude ---- -The `.git/info/exclude` file acts just like a `.gitignore`, but isn't included in commits. +فایل `.git/info/exclude` دقیقا مانند یک `.gitignore` عمل می‌کند، اما در کامیت‌ها گنجانده نمی‌شود. -===== Workflow +===== Workflow (روند کاری) -Let's assume we've done some work and made some commits on the `master` branch, and you're ready to push it to the remote repository. -Here's what our repository looks like right now: +فرض کنیم که ما مقداری کار انجام داده‌ایم و چند کامیت در شاخه master ایجاد کرده‌ایم و حالا آماده‌ایم که آن را به مخزن ریموت ارسال کنیم. در حال حاضر مخزن ما به این شکل است: [source,console] ---- @@ -151,9 +139,7 @@ $ git log --oneline --graph --decorate * 65bb417 Create a standard 'hello, world' program ---- -Our `master` branch is two commits ahead of `origin/master`, but those two commits exist only on our local machine. -Let's see if anyone else has been doing important work at the same time: - +شاخه `master` ما دو کامیت جلوتر از `origin/master` است، اما این دو کامیت فقط بر روی دستگاه محلی ما وجود دارند. بیایید ببینیم آیا کسی دیگری هم به طور همزمان کار مهمی انجام داده است: [source,console] ---- $ git fetch @@ -171,10 +157,7 @@ $ git log --oneline --graph --decorate --all * 65bb417 Create a standard 'hello, world' program ---- -Since we used the `--all` flag, we see the ``notes'' refs that are used internally by git-remote-hg, but we can ignore them. -The rest is what we expected; `origin/master` has advanced by one commit, and our history has now diverged. -Unlike the other systems we work with in this chapter, Mercurial is capable of handling merges, so we're not going to do anything fancy. - +از آنجایی که از فلگ `--all` استفاده کردیم، رفرنس‌های `notes` که به طور داخلی توسط `git-remote-hg` استفاده می‌شوند را می‌بینیم، اما می‌توانیم آن‌ها را نادیده بگیریم. بقیه موارد همانطور که انتظار می‌رفت، `origin/master` با یک کامیت پیش رفته است و تاریخچه ما اکنون از هم جدا شده است. برخلاف سیستم‌های دیگری که در این فصل با آن‌ها کار می‌کنیم، Mercurial قادر به مدیریت ادغام‌ها (merges) است، بنابراین ما نیازی به انجام کار خاصی نداریم. [source,console] ---- $ git merge origin/master @@ -193,8 +176,7 @@ $ git log --oneline --graph --decorate * 65bb417 Create a standard 'hello, world' program ---- -Perfect. -We run the tests and everything passes, so we're ready to share our work with the rest of the team: +عالی است. ما تست‌ها را اجرا می‌کنیم و همه آن‌ها با موفقیت عبور می‌کنند، بنابراین آماده‌ایم تا کار خود را با بقیه تیم به اشتراک بگذاریم: [source,console] ---- @@ -203,9 +185,7 @@ To hg::/tmp/hello df85e87..0c64627 master -> master ---- -That's it! -If you take a look at the Mercurial repository, you'll see that this did what we'd expect: - +تمام شد! اگر به مخزن Mercurial نگاهی بیندازید، خواهید دید که این همان چیزی بود که انتظار داشتیم: [source,console] ---- $ hg log -G --style compact @@ -228,16 +208,12 @@ o 0 0a04b987be5a 2005-08-26 01:20 -0700 mpm Create a standard 'hello, world' program ---- -The changeset numbered _2_ was made by Mercurial, and the changesets numbered _3_ and _4_ were made by git-remote-hg, by pushing commits made with Git. - -===== Branches and Bookmarks +تغییرات شماره‌گذاری شده 2 توسط Mercurial ایجاد شده است، و تغییرات شماره‌گذاری شده 3 و 4 توسط `git-remote-hg` ایجاد شده‌اند، که با ارسال کامیت‌های انجام شده با Git به وجود آمده‌اند. +===== Branches and Bookmarks (شاخه‌ها و بوک‌مارک‌ها) -Git has only one kind of branch: a reference that moves when commits are made. -In Mercurial, this kind of a reference is called a ``bookmark,'' and it behaves in much the same way as a Git branch. +گیت تنها یک نوع شاخه دارد: یک ارجاع که هنگام ایجاد کامیت‌ها جابجا می‌شود. در Mercurial، این نوع ارجاع `bookmark` نامیده می‌شود و رفتار آن تقریباً مشابه شاخه در گیت است. -Mercurial's concept of a ``branch'' is more heavyweight. -The branch that a changeset is made on is recorded _with the changeset_, which means it will always be in the repository history. -Here's an example of a commit that was made on the `develop` branch: +مفهوم `branch` در Mercurial سنگین‌تر است. شاخه‌ای که یک تغییرات (changeset) بر روی آن ایجاد می‌شود، با تغییرات ذخیره می‌شود، که به این معنی است که همیشه در تاریخچه مخزن خواهد بود. در اینجا یک مثال از یک کامیت که بر روی شاخه develop ایجاد شده است آورده شده: [source,console] ---- @@ -250,12 +226,9 @@ date: Thu Aug 14 20:06:38 2014 -0700 summary: More documentation ---- -Note the line that begins with ``branch''. -Git can't really replicate this (and doesn't need to; both types of branch can be represented as a Git ref), but git-remote-hg needs to understand the difference, because Mercurial cares. - -Creating Mercurial bookmarks is as easy as creating Git branches. -On the Git side: +به خطی که با `branch` شروع می‌شود توجه کنید. گیت واقعاً نمی‌تواند این را شبیه‌سازی کند (و نیازی هم به آن ندارد؛ هر دو نوع شاخه می‌توانند به عنوان یک مرجع گیت نمایش داده شوند)، اما `git-remote-hg` باید تفاوت را درک کند، زیرا Mercurial اهمیت می‌دهد. +ساخت بوک‌مارک‌های Mercurial به راحتی ایجاد شاخه‌های گیت است. در طرف گیت: [source,console] ---- $ git checkout -b featureA @@ -265,8 +238,7 @@ To hg::/tmp/hello * [new branch] featureA -> featureA ---- -That's all there is to it. -On the Mercurial side, it looks like this: +همین است. در طرف Mercurial، اینطور به نظر می‌رسد: [source,console] ---- @@ -295,11 +267,9 @@ o 0 0a04b987be5a 2005-08-26 01:20 -0700 mpm Create a standard 'hello, world' program ---- -Note the new `[featureA]` tag on revision 5. -These act exactly like Git branches on the Git side, with one exception: you can't delete a bookmark from the Git side (this is a limitation of remote helpers). - -You can work on a ``heavyweight'' Mercurial branch also: just put a branch in the `branches` namespace: +به تگ جدید [featureA] در بازبینی 5 توجه کنید. این‌ها دقیقاً مانند شاخه‌های گیت در طرف گیت عمل می‌کنند، با یک استثنا: شما نمی‌توانید یک بوک‌مارک را از طرف گیت حذف کنید (این یک محدودیت در کمک‌کننده‌های ریموت است). +شما همچنین می‌توانید بر روی یک شاخه "سنگین‌" Mercurial کار کنید: فقط کافی است که یک شاخه را در فضای نام `branches` قرار دهید: [source,console] ---- $ git checkout -b branches/permanent @@ -311,7 +281,7 @@ To hg::/tmp/hello * [new branch] branches/permanent -> branches/permanent ---- -Here's what that looks like on the Mercurial side: +در اینجا نحوه نمایش آن در طرف Mercurial آمده است: [source,console] ---- @@ -344,12 +314,9 @@ o changeset: 5:bd5ac26f11f9 [...] ---- -The branch name ``permanent'' was recorded with the changeset marked _7_. - -From the Git side, working with either of these branch styles is the same: just checkout, commit, fetch, merge, pull, and push as you normally would. -One thing you should know is that Mercurial doesn't support rewriting history, only adding to it. -Here's what our Mercurial repository looks like after an interactive rebase and a force-push: +نام شاخه `permanent` با تغییرات شماره‌گذاری شده 7 ثبت شده است. +از طرف گیت، کار کردن با هر یک از این سبک‌های شاخه مشابه است: فقط به صورت معمول checkout، commit، fetch، merge، pull و push انجام دهید. یک نکته‌ای که باید بدانید این است که Mercurial از بازنویسی تاریخچه پشتیبانی نمی‌کند، بلکه فقط می‌توان به آن اضافه کرد. در اینجا نحوه نمایش مخزن Mercurial ما پس از یک `rebase` تعاملی و یک `force-push` آمده است: [source,console] ---- $ hg log --style compact -G @@ -387,11 +354,8 @@ o 0 0a04b987be5a 2005-08-26 01:20 -0700 mpm Create a standard "hello, world" program ---- -Changesets _8_, _9_, and _10_ have been created and belong to the `permanent` branch, but the old changesets are still there. -This can be *very* confusing for your teammates who are using Mercurial, so try to avoid it. - +تغییرات شماره‌گذاری شده 8، 9 و 10 ایجاد شده‌اند و به شاخه `permanent` تعلق دارند، اما تغییرات قدیمی هنوز در آنجا هستند. این ممکن است بسیار گیج‌کننده باشد برای هم‌تیمی‌هایی که از Mercurial استفاده می‌کنند، بنابراین سعی کنید از آن اجتناب کنید. -===== Mercurial Summary +===== Mercurial Summary (خلاصه مرکوریال) -Git and Mercurial are similar enough that working across the boundary is fairly painless. -If you avoid changing history that's left your machine (as is generally recommended), you may not even be aware that the other end is Mercurial. +گیت و Mercurial به اندازه کافی مشابه هستند که کار کردن در مرز بین آن‌ها نسبتا بدون دردسر است. اگر از تغییر تاریخچه‌ای که از دستگاه شما خارج شده (همانطور که معمولاً توصیه می‌شود) اجتناب کنید، ممکن است حتی متوجه نشوید که طرف مقابل Mercurial است. \ No newline at end of file diff --git a/book/09-git-and-other-scms/sections/import-bzr.asc b/book/09-git-and-other-scms/sections/import-bzr.asc index 7617d0bb..67f2da64 100644 --- a/book/09-git-and-other-scms/sections/import-bzr.asc +++ b/book/09-git-and-other-scms/sections/import-bzr.asc @@ -1,48 +1,48 @@ -==== Bazaar +==== Bazaar بازار (((Bazaar)))(((Importing, from Bazaar))) -Bazaar is a DVCS tool much like Git, and as a result it's pretty straightforward to convert a Bazaar repository into a Git one. -To accomplish this, you'll need to import the `bzr-fastimport` plugin. +Bazaar یک ابزار کنترل نسخه توزیع‌شده (DVCS) شبیه به Git است، و در نتیجه تبدیل یک مخزن Bazaar به یک مخزن Git نسبتاً ساده است. +برای انجام این کار، باید افزونه `bzr-fastimport` را وارد (import) کنید. -===== Getting the bzr-fastimport plugin +===== دریافت افزونه bzr-fastimport -The procedure for installing the fastimport plugin is different on UNIX-like operating systems and on Windows. -In the first case, the simplest is to install the `bzr-fastimport` package that will install all the required dependencies. +فرآیند نصب افزونه fastimport در سیستم‌عامل‌های شبه یونیکس و ویندوز متفاوت است. +در سیستم‌عامل‌های شبه یونیکس، ساده‌ترین روش نصب پکیج bzr-fastimport است که تمامی وابستگی‌های مورد نیاز را نیز نصب خواهد کرد. -For example, with Debian and derived, you would do the following: +برای مثال، در Debian و توزیع‌های مشتق‌شده از آن، می‌توانید این کار را به شکل زیر انجام دهید: [source,console] ---- $ sudo apt-get install bzr-fastimport ---- -With RHEL, you would do the following: +با RHEL، شما باید به صورت زیر عمل کنید: [source,console] ---- $ sudo yum install bzr-fastimport ---- -With Fedora, since release 22, the new package manager is dnf: +در Fedora، از نسخه ۲۲ به بعد، مدیر بسته جدید dnf است: [source,console] ---- $ sudo dnf install bzr-fastimport ---- -If the package is not available, you may install it as a plugin: +اگر این پکیج در دسترس نباشد، می‌توانید آن را به صورت یک افزونه (plugin) نصب کنید: [source,console] ---- -$ mkdir --parents ~/.bazaar/plugins # creates the necessary folders for the plugins +$ mkdir --parents ~/.bazaar/plugins # ایجاد پوشه‌های لازم برای پلاگین‌ها $ cd ~/.bazaar/plugins -$ bzr branch lp:bzr-fastimport fastimport # imports the fastimport plugin +$ bzr branch lp:bzr-fastimport fastimport # وارد کردن پلاگین fastimport $ cd fastimport -$ sudo python setup.py install --record=files.txt # installs the plugin +$ sudo python setup.py install --record=files.txt # نصب پلاگین ---- -For this plugin to work, you'll also need the `fastimport` Python module. -You can check whether it is present or not and install it with the following commands: +برای اینکه این پلاگین کار کند، شما همچنین به ماژول پایتون `fastimport` نیاز دارید. + می‌توانید بررسی کنید که آیا موجود است یا نه و با دستورات زیر آن را نصب کنید: [source,console] ---- @@ -52,16 +52,16 @@ Traceback (most recent call last): ImportError: No module named fastimport $ pip install fastimport ---- -If it is not available, you can download it at address https://pypi.python.org/pypi/fastimport/. +اگر در دسترس نیست، می‌توانید آن را از آدرس https://pypi.python.org/pypi/fastimport/. -In the second case (on Windows), `bzr-fastimport` is automatically installed with the standalone version and the default installation (let all the checkboxes checked). -So in this case you have nothing to do. +در حالت دوم (در ویندوز)، افزونه bzr-fastimport به‌صورت خودکار همراه با نسخه مستقل (standalone) و نصب پیش‌فرض (در صورتی که تمام چک‌باکس‌ها تیک‌خورده باقی بمانند) نصب می‌شود. +بنابراین در این حالت، نیازی به انجام کار خاصی ندارید. -At this point, the way to import a Bazaar repository differs according to that you have a single branch or you are working with a repository that has several branches. +در این مرحله، روش وارد کردن یک مخزن Bazaar بسته به این که فقط یک شاخه داشته باشید یا با مخزنی با چندین شاخه کار می‌کنید، متفاوت است. -===== Project with a single branch +===== Project with a single branch (پروژه با یک شاخه واحد) -Now `cd` in the directory that contains your Bazaar repository and initialize the Git repository: +اکنون `cd` در دایرکتوری که مخزن بازار شما در آن قرار دارد و مخزن گیت را راه‌اندازی کنید: [source,console] ---- @@ -69,19 +69,20 @@ $ cd /path/to/the/bzr/repository $ git init ---- -Now, you can simply export your Bazaar repository and convert it into a Git repository using the following command: +اکنون، می‌توانید به سادگی مخزن بازار خود را صادر کرده و آن را به یک مخزن گیت تبدیل کنید با استفاده از دستور + زیر: [source,console] ---- $ bzr fast-export --plain . | git fast-import ---- -Depending on the size of the project, your Git repository is built in a lapse from a few seconds to a few minutes. +بسته به اندازه پروژه، مخزن Git شما در بازه‌ای از چند ثانیه تا چند دقیقه ساخته می‌شود. -===== Case of a project with a main branch and a working branch - -You can also import a Bazaar repository that contains branches. -Let us suppose that you have two branches: one represents the main branch (myProject.trunk), the other one is the working branch (myProject.work). +===== Case of a project with a main branch and a working branch (حالت پروژه‌ای با یک شاخه اصلی و یک شاخه کاری) + +شما می‌توانید یک مخزن Bazaar را که شامل چند شاخه است نیز وارد (import) کنید. +فرض کنیم که دو شاخه دارید: یکی شاخه اصلی را نمایش می‌دهد (myProject.trunk) و دیگری شاخه کاری است (myProject.work). [source,console] ---- @@ -89,7 +90,7 @@ $ ls myProject.trunk myProject.work ---- -Create the Git repository and `cd` into it: +مخزن گیت را ایجاد کنید و با دستور `cd` به آن بروید: [source,console] ---- @@ -97,7 +98,7 @@ $ git init git-repo $ cd git-repo ---- -Pull the `master` branch into git: +شاخه `master` را به گیت بکشید: [source,console] ---- @@ -105,7 +106,7 @@ $ bzr fast-export --export-marks=../marks.bzr ../myProject.trunk | \ git fast-import --export-marks=../marks.git ---- -Pull the working branch into Git: +شاخه کاری را به گیت بکشید: [source,console] ---- @@ -113,26 +114,27 @@ $ bzr fast-export --marks=../marks.bzr --git-branch=work ../myProject.work | \ git fast-import --import-marks=../marks.git --export-marks=../marks.git ---- -Now `git branch` shows you the `master` branch as well as the `work` branch. -Check the logs to make sure they're complete and get rid of the `marks.bzr` and `marks.git` files. +اکنون دستور git branch شاخه master و همچنین شاخه work را به شما نشان می‌دهد. +لاگ‌ها (logs) را بررسی کنید تا مطمئن شوید همه چیز به‌طور کامل منتقل شده، و سپس فایل‌های marks.bzr و marks.git را حذف کنید. -===== Synchronizing the staging area +===== Synchronizing the staging area (همگام‌سازی ناحیه موقت) -Whatever the number of branches you had and the import method you used, your staging area is not synchronized with `HEAD`, and with the import of several branches, your working directory is not synchronized either. -This situation is easily solved by the following command: +فارغ از تعداد شاخه‌هایی که داشتید و روشی که برای وارد کردن آن‌ها استفاده کردید، ناحیه staging شما با `HEAD` همگام نیست، و در صورت وارد کردن چند شاخه، دایرکتوری کاری شما نیز همگام نخواهد بود. +این وضعیت به‌سادگی با اجرای دستور زیر حل می‌شود: [source,console] ---- $ git reset --hard HEAD ---- -===== Ignoring the files that were ignored with .bzrignore +===== نادیده گرفتن فایل‌هایی که با .bzrignore نادیده گرفته شده بودند + +حالا بیایید نگاهی به فایل‌های نادیده گرفته شده بیندازیم. +اولین کاری که باید انجام دهید این است که فایل .bzrignore را به .gitignore تغییر نام دهید. -Now let's have a look at the files to ignore. -The first thing to do is to rename `.bzrignore` into `.gitignore`. -If the `.bzrignore` file contains one or several lines starting with "!!" or "RE:", you'll have to modify it and perhaps create several `.gitignore` files in order to ignore exactly the same files that Bazaar was ignoring. +اگر فایل .bzrignore شامل یک یا چند خط باشد که با "!!" یا "RE:" شروع می‌شوند، باید آن را ویرایش کرده و شاید نیاز باشد چند فایل .gitignore جداگانه بسازید تا دقیقاً همان فایل‌هایی را نادیده بگیرید که قبلاً توسط Bazaar نادیده گرفته می‌شدند. -Finally, you will have to create a commit that contains this modification for the migration: +در نهایت، باید یک کامیت ایجاد کنید که این تغییرات را برای ثبت فرآیند مهاجرت شامل شود: [source,console] ---- @@ -141,10 +143,10 @@ $ # modify .gitignore if needed $ git commit -am 'Migration from Bazaar to Git' ---- -===== Sending your repository to the server +===== Sending your repository to the server (ارسال مخزن شما به سرور) -Here we are! -Now you can push the repository onto its new home server: +الان آماده‌ایم! +حالا می‌توانید مخزن را به سرور جدید خانه خود ارسال کنید: [source,console] ---- @@ -153,4 +155,4 @@ $ git push origin --all $ git push origin --tags ---- -Your Git repository is ready to use. +مخزن گیت شما آماده استفاده است. diff --git a/book/09-git-and-other-scms/sections/import-custom.asc b/book/09-git-and-other-scms/sections/import-custom.asc index 14bc9c00..e26b6ddd 100644 --- a/book/09-git-and-other-scms/sections/import-custom.asc +++ b/book/09-git-and-other-scms/sections/import-custom.asc @@ -1,18 +1,14 @@ [[_custom_importer]] -==== A Custom Importer +==== A Custom Importer (واردکننده سفارشی) (((git commands, fast-import))) (((Importing, from others))) -If your system isn't one of the above, you should look for an importer online – quality importers are available for many other systems, including CVS, Clear Case, Visual Source Safe, even a directory of archives. -If none of these tools works for you, you have a more obscure tool, or you otherwise need a more custom importing process, you should use `git fast-import`. -This command reads simple instructions from stdin to write specific Git data. -It's much easier to create Git objects this way than to run the raw Git commands or try to write the raw objects (see <> for more information). -This way, you can write an import script that reads the necessary information out of the system you're importing from and prints straightforward instructions to stdout. -You can then run this program and pipe its output through `git fast-import`. -To quickly demonstrate, you'll write a simple importer. -Suppose you work in `current`, you back up your project by occasionally copying the directory into a time-stamped `back_YYYY_MM_DD` backup directory, and you want to import this into Git. -Your directory structure looks like this: + اگر سیستم شما یکی از موارد ذکر شده در بالا نیست، باید به دنبال یک واردکننده آنلاین بگردید – واردکننده‌های با کیفیت برای بسیاری از سیستم‌های دیگر از جمله CVS، Clear Case، Visual Source Safe و حتی یک دایرکتوری از آرشیوها در دسترس هستند. اگر هیچ‌کدام از این ابزارها برای شما کار نمی‌کنند، ابزار نادری دارید یا نیاز به فرآیند واردسازی سفارشی‌تر دارید، باید از git fast-import استفاده کنید. این دستور دستورالعمل‌های ساده‌ای را از stdin می‌خواند تا داده‌های خاص گیت را بنویسد. این روش بسیار راحت‌تر از اجرای دستورات خام گیت یا تلاش برای نوشتن اشیاء خام است (برای اطلاعات بیشتر به <> مراجعه کنید). به این ترتیب، می‌توانید یک اسکریپت واردسازی بنویسید که اطلاعات لازم را از سیستم واردکننده استخراج کرده و دستورالعمل‌های ساده‌ای را به stdout چاپ کند. سپس می‌توانید این برنامه را اجرا کرده و خروجی آن را از طریق git fast-import منتقل کنید. + +برای نمایش سریع، شما یک واردکننده ساده می‌نویسید. +فرض کنید شما در دایرکتوری current کار می‌کنید، پروژه خود را با کپی کردن گاه به گاه دایرکتوری به دایرکتوری پشتیبان با زمان‌بندی back_YYYY_MM_DD پشتیبان‌گیری می‌کنید و می‌خواهید این را به گیت وارد کنید. +ساختار دایرکتوری شما به این شکل است: [source,console] ---- @@ -24,18 +20,18 @@ back_2014_02_03 current ---- -In order to import a Git directory, you need to review how Git stores its data. -As you may remember, Git is fundamentally a linked list of commit objects that point to a snapshot of content. -All you have to do is tell `fast-import` what the content snapshots are, what commit data points to them, and the order they go in. -Your strategy will be to go through the snapshots one at a time and create commits with the contents of each directory, linking each commit back to the previous one. +برای وارد کردن یک دایرکتوری گیت، باید نحوه ذخیره‌سازی داده‌ها در گیت را بررسی کنید. +همانطور که ممکن است به یاد داشته باشید، گیت اساساً یک لیست پیوندی از اشیاء کامیت است که به یک snapshot از محتویات اشاره دارند. +تمام کاری که باید انجام دهید این است که به `fast-import` بگویید که snapshotهای محتویات کجا هستند، داده‌های کامیت به کدام‌ یک اشاره می‌کنند، و ترتیب آن‌ها چگونه است. +استراتژی شما این خواهد بود که به‌طور تک‌تک از میان snapshotها عبور کنید و برای محتویات هر دایرکتوری کامیت ایجاد کرده و هر کامیت را به کامیت قبلی متصل کنید. -As we did in <>, we'll write this in Ruby, because it's what we generally work with and it tends to be easy to read. -You can write this example pretty easily in anything you're familiar with – it just needs to print the appropriate information to `stdout`. -And, if you are running on Windows, this means you'll need to take special care to not introduce carriage returns at the end your lines – `git fast-import` is very particular about just wanting line feeds (LF) not the carriage return line feeds (CRLF) that Windows uses. +همانطور که در <> انجام دادیم، این را در Ruby می‌نویسیم، چون این زبان معمولاً آنچه که با آن کار می‌کنیم است و خواندن آن راحت‌تر است. +شما می‌توانید این مثال را به راحتی در هر زبان دیگری که با آن آشنا هستید بنویسید – تنها باید اطلاعات مناسب را به `stdout` چاپ کند. +و اگر در ویندوز کار می‌کنید، باید دقت ویژه‌ای داشته باشید که در انتهای خطوط کاراکتر بازگشتی (carriage return) اضافه نکنید – `git fast-import` خیلی خاص است و فقط به خط‌خورهای (LF) نیاز دارد نه بازگشت‌خط‌های (CRLF) ویندوز. -To begin, you'll change into the target directory and identify every subdirectory, each of which is a snapshot that you want to import as a commit. -You'll change into each subdirectory and print the commands necessary to export it. -Your basic main loop looks like this: +برای شروع، شما باید وارد دایرکتوری هدف شوید و هر زیر دایرکتوری را شناسایی کنید، که هر کدام یک snapshot است که می‌خواهید به عنوان یک کامیت وارد کنید. +سپس وارد هر زیر دایرکتوری می‌شوید و دستورات لازم برای صادر کردن آن را چاپ می‌کنید. +حلقه اصلی شما به شکل زیر خواهد بود: [source,ruby] ---- @@ -54,17 +50,17 @@ Dir.chdir(ARGV[0]) do end ---- -You run `print_export` inside each directory, which takes the manifest and mark of the previous snapshot and returns the manifest and mark of this one; that way, you can link them properly. -``Mark'' is the `fast-import` term for an identifier you give to a commit; as you create commits, you give each one a mark that you can use to link to it from other commits. -So, the first thing to do in your `print_export` method is generate a mark from the directory name: +شما دستور `print_export` را در داخل هر دایرکتوری اجرا می‌کنید، که منیفست و مارک snapshot قبلی را می‌گیرد و منیفست و مارک این snapshot را باز می‌گرداند؛ به این ترتیب، می‌توانید آن‌ها را به درستی به هم متصل کنید. +`Mark` اصطلاحی است در `fast-import` برای شناسه‌ای که به یک کامیت می‌دهید؛ زمانی که کامیت‌ها را ایجاد می‌کنید، به هرکدام یک مارک می‌دهید که می‌توانید از آن برای لینک کردن به آن کامیت‌ها از کامیت‌های دیگر استفاده کنید. +بنابراین، اولین کاری که باید در متد `print_export` خود انجام دهید این است که یک مارک از نام دایرکتوری ایجاد کنید: [source,ruby] ---- mark = convert_dir_to_mark(dir) ---- -You'll do this by creating an array of directories and using the index value as the mark, because a mark must be an integer. -Your method looks like this: +شما این کار را با ایجاد یک آرایه از دایرکتوری‌ها و استفاده از مقدار ایندکس به‌عنوان مارک انجام خواهید داد، زیرا مارک باید یک عدد صحیح (integer) باشد. +متد شما به شکل زیر خواهد بود: [source,ruby] ---- @@ -77,16 +73,16 @@ def convert_dir_to_mark(dir) end ---- -Now that you have an integer representation of your commit, you need a date for the commit metadata. -Because the date is expressed in the name of the directory, you'll parse it out. -The next line in your `print_export` file is: +حال که نمایه عددی از کامیت خود دارید، به یک تاریخ برای داده‌های متا-داده کامیت نیاز دارید. +زیرا تاریخ در نام دایرکتوری بیان شده است، بنابراین باید آن را استخراج کنید. +خط بعدی در فایل `print_export` شما به شکل زیر خواهد بود: [source,ruby] ---- date = convert_dir_to_date(dir) ---- -where `convert_dir_to_date` is defined as: +جایی که `convert_dir_to_date` به این شکل تعریف شده است: [source,ruby] ---- @@ -101,17 +97,17 @@ def convert_dir_to_date(dir) end ---- -That returns an integer value for the date of each directory. -The last piece of meta-information you need for each commit is the committer data, which you hardcode in a global variable: +این مقدار یک عدد صحیح برای تاریخ هر دایرکتوری برمی‌گرداند. +آخرین بخش از اطلاعات متا که برای هر کامیت نیاز دارید، داده‌های فرستنده (committer) است که آن را در یک متغیر سراسری (global variable) به صورت ثابت تنظیم می‌کنید: [source,ruby] ---- $author = 'John Doe ' ---- -Now you're ready to begin printing out the commit data for your importer. -The initial information states that you're defining a commit object and what branch it's on, followed by the mark you've generated, the committer information and commit message, and then the previous commit, if any. -The code looks like this: +اکنون شما آماده‌اید که داده‌های کامیت را برای واردکننده خود چاپ کنید. +اطلاعات اولیه بیان می‌کند که شما یک شیء کامیت را تعریف می‌کنید و بیان می‌کنید که در کدام شاخه است، سپس مارک تولید شده، اطلاعات کامیت‌کننده و پیام کامیت را درج کرده و در نهایت کامیت قبلی را، در صورت وجود، اضافه می‌کنید. +کد به این صورت خواهد بود: [source,ruby] ---- @@ -123,17 +119,18 @@ export_data('imported from ' + dir) puts 'from :' + last_mark if last_mark ---- -You hardcode the time zone (-0700) because doing so is easy. -If you're importing from another system, you must specify the time zone as an offset. -The commit message must be expressed in a special format: +شما منطقه زمانی (-0700) را به صورت ثابت تنظیم می‌کنید زیرا انجام این کار ساده است. +اگر از سیستم دیگری وارد می‌کنید، باید منطقه زمانی را به صورت یک آفست مشخص کنید. +پیام کامیت باید در یک فرمت خاص بیان شود: [source] ---- data (size)\n(contents) ---- -The format consists of the word data, the size of the data to be read, a newline, and finally the data. -Because you need to use the same format to specify the file contents later, you create a helper method, `export_data`: +فرمت شامل کلمه data، اندازه داده‌ای که باید خوانده شود، یک خط جدید، و در نهایت خود داده‌ها است. +زیرا شما باید از همین فرمت برای مشخص کردن محتویات فایل‌ها در مراحل بعدی استفاده کنید، بنابراین یک متد کمکی به نام `export_data` ایجاد می‌کنید: + [source,ruby] ---- @@ -142,9 +139,9 @@ def export_data(string) end ---- -All that's left is to specify the file contents for each snapshot. -This is easy, because you have each one in a directory – you can print out the `deleteall` command followed by the contents of each file in the directory. -Git will then record each snapshot appropriately: +تمام چیزی که باقی مانده، مشخص کردن محتویات فایل‌ها برای هر snapshot است. +این کار ساده است، زیرا شما هر کدام را در یک دایرکتوری دارید – می‌توانید دستور `deleteall` را چاپ کرده و سپس محتویات هر فایل در دایرکتوری را دنبال کنید. +گیت سپس هر snapshot را به‌طور مناسب ثبت خواهد کرد: [source,ruby] ---- @@ -155,12 +152,11 @@ Dir.glob("**/*").each do |file| end ---- -Note: Because many systems think of their revisions as changes from one commit to another, fast-import can also take commands with each commit to specify which files have been added, removed, or modified and what the new contents are. -You could calculate the differences between snapshots and provide only this data, but doing so is more complex – you may as well give Git all the data and let it figure it out. -If this is better suited to your data, check the `fast-import` man page for details about how to provide your data in this manner. - -The format for listing the new file contents or specifying a modified file with the new contents is as follows: +توجه داشته باشید: چون بسیاری از سیستم‌ها تغییرات خود را به‌عنوان تغییرات بین یک کامیت و کامیت دیگر می‌بینند، `fast-import` همچنین می‌تواند دستوراتی برای هر کامیت دریافت کند که مشخص می‌کند کدام فایل‌ها اضافه، حذف یا تغییر یافته‌اند و محتویات جدید آن‌ها چیست. +شما می‌توانید تفاوت‌ها بین snapshotها را محاسبه کرده و فقط این داده‌ها را فراهم کنید، اما این کار پیچیده‌تر است – بهتر است تمام داده‌ها را به گیت بدهید و بگذارید خودش این کار را انجام دهد. +اگر این روش برای داده‌های شما مناسب‌تر است، برای جزئیات بیشتر در مورد نحوه ارائه داده‌ها به این شیوه، صفحه راهنمای `fast-import` را بررسی کنید. +فرمت برای فهرست کردن محتویات فایل‌های جدید یا مشخص کردن یک فایل تغییر یافته با محتویات جدید به شکل زیر است: [source] ---- M 644 inline path/to/file @@ -168,8 +164,8 @@ data (size) (file contents) ---- -Here, 644 is the mode (if you have executable files, you need to detect and specify 755 instead), and inline says you'll list the contents immediately after this line. -Your `inline_data` method looks like this: +در اینجا، 644 حالت فایل است (اگر فایل‌های اجرایی دارید، باید آن‌ها را شناسایی کرده و 755 را به جای آن مشخص کنید)، و inline می‌گوید که شما محتویات فایل را بلافاصله پس از این خط فهرست خواهید کرد. +متد `inline_data` شما به شکل زیر خواهد بود: [source,ruby] ---- @@ -180,9 +176,9 @@ def inline_data(file, code = 'M', mode = '644') end ---- -You reuse the `export_data` method you defined earlier, because it's the same as the way you specified your commit message data. +شما از متد `export_data` که قبلاً تعریف کرده‌اید دوباره استفاده می‌کنید، زیرا این روش مشابه روش مشخص کردن داده‌های پیام کامیت شما است. -The last thing you need to do is to return the current mark so it can be passed to the next iteration: +آخرین کاری که باید انجام دهید این است که مارک فعلی را برگردانید تا بتوانید آن را به تکرار بعدی منتقل کنید: [source,ruby] ---- @@ -191,9 +187,10 @@ return mark [NOTE] ==== -If you are running on Windows you'll need to make sure that you add one extra step. -As mentioned before, Windows uses CRLF for new line characters while `git fast-import` expects only LF. -To get around this problem and make `git fast-import` happy, you need to tell ruby to use LF instead of CRLF: + +اگر شما در حال اجرای این کد در ویندوز هستید، باید مطمئن شوید که یک مرحله اضافی اضافه کنید. +همانطور که قبلاً اشاره شد، ویندوز از CRLF برای کاراکترهای خط جدید استفاده می‌کند، در حالی که `git fast-import` تنها انتظار دارد که از LF استفاده شود. +برای دور زدن این مشکل و راضی نگه داشتن git fast-import، باید به روبی بگویید که از LF به جای CRLF استفاده کند: [source,ruby] ---- @@ -201,9 +198,8 @@ $stdout.binmode ---- ==== -That's it. -Here's the script in its entirety: - +این تمام چیزی است که نیاز دارید. +در اینجا اسکریپت به طور کامل آمده است: [source,ruby] ---- @@ -272,7 +268,7 @@ Dir.chdir(ARGV[0]) do end ---- -If you run this script, you'll get content that looks something like this: +اگر این اسکریپت را اجرا کنید، محتوای خروجی به این شکل خواهد بود: [source,console] ---- @@ -302,8 +298,8 @@ M 644 inline README.md (...) ---- -To run the importer, pipe this output through `git fast-import` while in the Git directory you want to import into. -You can create a new directory and then run `git init` in it for a starting point, and then run your script: +برای اجرای واردکننده، این خروجی را از طریق `git fast-import` در دایرکتوری گیت که می‌خواهید وارد کنید، پایپ کنید. +شما می‌توانید یک دایرکتوری جدید ایجاد کرده و سپس دستور git init را در آن اجرا کنید تا نقطه شروعی داشته باشید، سپس اسکریپت خود را اجرا کنید: [source,console] ---- @@ -335,9 +331,9 @@ pack_report: pack_mapped = 1457 / 1457 --------------------------------------------------------------------- ---- -As you can see, when it completes successfully, it gives you a bunch of statistics about what it accomplished. -In this case, you imported 13 objects total for 4 commits into 1 branch. -Now, you can run `git log` to see your new history: +همانطور که می‌بینید، زمانی که این فرآیند با موفقیت تکمیل می‌شود، به شما تعدادی آمار در مورد کارهایی که انجام شده است، ارائه می‌دهد. +در این حالت، شما ۱۳ شیء به‌طور کلی برای ۴ کامیت به یک شاخه وارد کرده‌اید. +اکنون می‌توانید دستور `git log` را اجرا کنید تا تاریخچه جدید خود را مشاهده کنید: [source,console] ---- @@ -355,9 +351,9 @@ Date: Mon Feb 3 01:00:00 2014 -0700 imported from back_2014_02_03 ---- -There you go – a nice, clean Git repository. -It's important to note that nothing is checked out – you don't have any files in your working directory at first. -To get them, you must reset your branch to where `master` is now: +حالا یک مخزن گیت تمیز و مرتب دارید. +مهم است که توجه داشته باشید که هیچ چیزی چک‌اوت نشده است – در ابتدا هیچ فایلی در دایرکتوری کاری شما وجود ندارد. +برای دریافت فایل‌ها، باید شاخه خود را به جایی که `master` اکنون قرار دارد، ریست کنید: [source,console] ---- @@ -368,5 +364,5 @@ $ ls README.md main.rb ---- -You can do a lot more with the `fast-import` tool – handle different modes, binary data, multiple branches and merging, tags, progress indicators, and more. -A number of examples of more complex scenarios are available in the `contrib/fast-import` directory of the Git source code. +شما می‌توانید با ابزار `fast-import` کارهای بیشتری انجام دهید – مدیریت حالت‌های مختلف، داده‌های باینری، شاخه‌های متعدد و ادغام‌ها، تگ‌ها، نشانگرهای پیشرفت و موارد دیگر. +چندین مثال از سناریوهای پیچیده‌تر در دایرکتوری `contrib/fast-import` کد منبع گیت موجود است. diff --git a/book/09-git-and-other-scms/sections/import-hg.asc b/book/09-git-and-other-scms/sections/import-hg.asc index 132fa8c0..43ed9009 100644 --- a/book/09-git-and-other-scms/sections/import-hg.asc +++ b/book/09-git-and-other-scms/sections/import-hg.asc @@ -1,23 +1,25 @@ ==== Mercurial (((Mercurial)))(((Importing, from Mercurial))) -Since Mercurial and Git have fairly similar models for representing versions, and since Git is a bit more flexible, converting a repository from Mercurial to Git is fairly straightforward, using a tool called "hg-fast-export", which you'll need a copy of: + +از آنجا که مرکیوریال و گیت مدل‌های نسبتاً مشابهی برای نمایش نسخه‌ها دارند و گیت کمی انعطاف‌پذیرتر است، تبدیل یک مخزن از مرکیوریال به گیت به‌طور نسبتاً ساده‌ای امکان‌پذیر است، با استفاده از ابزاری به نام "hg-fast-export"، که شما به یک نسخه از آن نیاز خواهید داشت: [source,console] ---- $ git clone https://github.com/frej/fast-export.git ---- -The first step in the conversion is to get a full clone of the Mercurial repository you want to convert: +اولین قدم در تبدیل، گرفتن یک کلون کامل از مخزن مرکیوریالی است که می‌خواهید آن را تبدیل کنید: + [source,console] ---- $ hg clone /tmp/hg-repo ---- -The next step is to create an author mapping file. -Mercurial is a bit more forgiving than Git for what it will put in the author field for changesets, so this is a good time to clean house. -Generating this is a one-line command in a `bash` shell: +مرحله بعدی ایجاد یک فایل نگاشت نویسنده است. +مرکیوریال کمی بیشتر از گیت در مورد چیزی که در فیلد نویسنده برای تغییرات قرار می‌دهد، انعطاف‌پذیر است، بنابراین این زمان مناسبی برای پاک‌سازی است. +برای تولید این فایل، کافی است که یک دستور یک‌خطی در شل `bash` اجرا کنید: [source,console] ---- @@ -25,7 +27,7 @@ $ cd /tmp/hg-repo $ hg log | grep user: | sort | uniq | sed 's/user: *//' > ../authors ---- -This will take a few seconds, depending on how long your project's history is, and afterwards the `/tmp/authors` file will look something like this: +این فرایند چند ثانیه طول خواهد کشید، بسته به اینکه تاریخچه پروژه شما چقدر طولانی باشد، و پس از آن فایل `/tmp/authors` چیزی شبیه به این خواهد بود: [source] ---- @@ -37,12 +39,12 @@ Bob Jones Joe Smith ---- -In this example, the same person (Bob) has created changesets under four different names, one of which actually looks correct, and one of which would be completely invalid for a Git commit. -Hg-fast-export lets us fix this by turning each line into a rule: `""=""`, mapping an `` to an ``. -Inside the `` and `` strings, all escape sequences understood by the python `string_escape` encoding are supported. -If the author mapping file does not contain a matching ``, that author will be sent on to Git unmodified. -If all the usernames look fine, we won't need this file at all. -In this example, we want our file to look like this: +در این مثال، همان شخص (باب) تغییرات را تحت چهار نام مختلف ایجاد کرده است، که یکی از آن‌ها به درستی به نظر می‌رسد و یکی دیگر به طور کامل برای یک کامیت گیت نامعتبر است. +ابزار `hg-fast-export` به ما اجازه می‌دهد این مشکل را با تبدیل هر خط به یک قانون حل کنیم: ""=""، که یک `` را به یک `` نگاشت می‌کند. +در داخل رشته‌های `` و ``، تمام دنباله‌های فرار که توسط کدگذاری `string_escape` پایتون درک می‌شوند، پشتیبانی می‌شوند. +اگر فایل نگاشت نویسنده شامل `` مطابقت نداشته باشد، آن نویسنده بدون تغییر به گیت ارسال خواهد شد. +اگر تمام نام‌های کاربری درست به نظر برسند، نیازی به این فایل نخواهیم داشت. +در این مثال، ما می‌خواهیم فایل ما به این شکل باشد: [source] ---- @@ -52,9 +54,10 @@ In this example, we want our file to look like this: "bob jones company com>"="Bob Jones " ---- -The same kind of mapping file can be used to rename branches and tags when the Mercurial name is not allowed by Git. +همین نوع فایل نگاشت می‌تواند برای تغییر نام شاخه‌ها و تگ‌ها زمانی که نام مرکیوریال توسط گیت مجاز نیست، استفاده شود. + +مرحله بعدی ایجاد مخزن جدید گیت ما است و سپس اجرای اسکریپت صادرات: -The next step is to create our new Git repository, and run the export script: [source,console] ---- @@ -63,9 +66,9 @@ $ cd /tmp/converted $ /tmp/fast-export/hg-fast-export.sh -r /tmp/hg-repo -A /tmp/authors ---- -The `-r` flag tells hg-fast-export where to find the Mercurial repository we want to convert, and the `-A` flag tells it where to find the author-mapping file (branch and tag mapping files are specified by the `-B` and `-T` flags respectively). -The script parses Mercurial changesets and converts them into a script for Git's "fast-import" feature (which we'll discuss in detail a bit later on). -This takes a bit (though it's _much_ faster than it would be over the network), and the output is fairly verbose: +فلگ `-r` به hg-fast-export می‌گوید که مخزن مرکیوریال که می‌خواهیم تبدیل کنیم کجا قرار دارد، و فلگ `-A` به آن می‌گوید که فایل نگاشت نویسندگان کجا قرار دارد (فایل‌های نگاشت شاخه و تگ به ترتیب با فلگ‌های `-B` و `-T` مشخص می‌شوند). +اسکریپت تغییرات مرکیوریال را تجزیه می‌کند و آن‌ها را به یک اسکریپت برای ویژگی "fast-import" گیت تبدیل می‌کند (که بعداً به تفصیل در مورد آن صحبت خواهیم کرد). +این فرایند کمی طول می‌کشد (اگرچه بسیار سریع‌تر از زمانی است که بخواهید از طریق شبکه این کار را انجام دهید)، و خروجی آن نسبتاً مفصل است: [source,console] ---- @@ -113,9 +116,9 @@ $ git shortlog -sn 365 Joe Smith ---- -That's pretty much all there is to it. -All of the Mercurial tags have been converted to Git tags, and Mercurial branches and bookmarks have been converted to Git branches. -Now you're ready to push the repository up to its new server-side home: +تقریباً همین‌قدر است. +تمامی تگ‌های مرکیوریال به تگ‌های گیت تبدیل شده‌اند، و شاخه‌ها و بوک‌مارک‌های مرکیوریال به شاخه‌های گیت تبدیل شده‌اند. +حالا شما آماده‌اید که مخزن را به سرور جدید خود ارسال کنید: [source,console] ---- diff --git a/book/09-git-and-other-scms/sections/import-p4.asc b/book/09-git-and-other-scms/sections/import-p4.asc index a8501fba..5b6b0513 100644 --- a/book/09-git-and-other-scms/sections/import-p4.asc +++ b/book/09-git-and-other-scms/sections/import-p4.asc @@ -1,23 +1,23 @@ [[_perforce_import]] -==== Perforce +==== Perforce (پرفورمنس) (((Perforce)))(((Importing, from Perforce))) -The next system you'll look at importing from is Perforce. -As we discussed above, there are two ways to let Git and Perforce talk to each other: git-p4 and Perforce Git Fusion. + +سیستم بعدی که به بررسی وارد کردن از آن خواهیم پرداخت، پر فورس (Perforce) است. +همانطور که قبلاً اشاره کردیم، دو روش برای ارتباط بین گیت و پر فورس وجود دارد: git-p4 و Perforce Git Fusion. ===== Perforce Git Fusion -Git Fusion makes this process fairly painless. -Just configure your project settings, user mappings, and branches using a configuration file (as discussed in <<_p4_git_fusion>>), and clone the repository. -Git Fusion leaves you with what looks like a native Git repository, which is then ready to push to a native Git host if you desire. -You could even use Perforce as your Git host if you like. +Perforce Git Fusion این فرآیند را به‌طور قابل توجهی ساده می‌کند. +فقط کافی است تنظیمات پروژه، نقشه‌های کاربری و شاخه‌ها را با استفاده از یک فایل پیکربندی (همانطور که در بخش <<_p4_git_fusion>> توضیح داده شده است) پیکربندی کرده و مخزن را کلون کنید. +Git Fusion یک مخزن گیت مشابه مخزن بومی گیت برای شما ایجاد می‌کند، که سپس می‌توانید آن را به یک میزبان بومی گیت ارسال کنید، اگر بخواهید. +حتی می‌توانید از Perforce به‌عنوان میزبان گیت خود استفاده کنید، اگر تمایل داشته باشید [[_git_p4]] ===== Git-p4 -Git-p4 can also act as an import tool. -As an example, we'll import the Jam project from the Perforce Public Depot. -To set up your client, you must export the P4PORT environment variable to point to the Perforce depot: +برای استفاده از git-p4 به‌عنوان ابزار واردات، ابتدا باید محیط خود را تنظیم کنید. +به‌عنوان مثال، برای وارد کردن پروژه Jam از Perforce Public Depot، باید متغیر محیطی P4PORT را به درستی تنظیم کنید تا به مخزن Perforce اشاره کند. این کار را می‌توانید با دستور زیر انجام دهید: [source,console] ---- @@ -26,12 +26,11 @@ $ export P4PORT=public.perforce.com:1666 [NOTE] ==== -In order to follow along, you'll need a Perforce depot to connect with. -We'll be using the public depot at public.perforce.com for our examples, but you can use any depot you have access to. +برای همراهی با این آموزش، به یک پایگاه داده Perforce نیاز دارید تا به آن متصل شوید. ما از پایگاه داده عمومی public.perforce.com برای مثال‌هایمان استفاده خواهیم کرد، اما شما می‌توانید از هر پایگاه داده‌ای که به آن دسترسی دارید استفاده کنید. ==== (((git commands, p4))) -Run the `git p4 clone` command to import the Jam project from the Perforce server, supplying the depot and project path and the path into which you want to import the project: +دستور `git p4 clone` را برای وارد کردن پروژه Jam از سرور Perforce اجرا کنید، با ارائه مسیر مخزن و پروژه و مسیری که می‌خواهید پروژه را در آن وارد کنید: [source,console] ---- @@ -42,11 +41,9 @@ Import destination: refs/remotes/p4/master Importing revision 9957 (100%) ---- -This particular project has only one branch, but if you have branches that are configured with branch views (or just a set of directories), you can use the `--detect-branches` flag to `git p4 clone` to import all the project's branches as well. -See <<_git_p4_branches>> for a bit more detail on this. +این پروژه خاص تنها یک شاخه دارد، اما اگر شما شاخه‌هایی دارید که با نمای شاخه‌ها (یا فقط مجموعه‌ای از دایرکتوری‌ها) پیکربندی شده‌اند، می‌توانید از فلگ `--detect-branches` در دستور `git p4 clone` برای وارد کردن تمام شاخه‌های پروژه استفاده کنید. برای اطلاعات بیشتر در این زمینه به <<_git_p4_branches>> مراجعه کنید. -At this point you're almost done. -If you go to the `p4import` directory and run `git log`, you can see your imported work: +در این مرحله شما تقریباً کار را تمام کرده‌اید. اگر به دایرکتوری `p4import` بروید و دستور `git log` را اجرا کنید، می‌توانید کار وارد شده خود را مشاهده کنید: [source,console] ---- @@ -68,11 +65,7 @@ Date: Tue Jul 7 01:35:51 2009 -0800 [git-p4: depot-paths = "//public/jam/src/": change = 7304] ---- -You can see that `git-p4` has left an identifier in each commit message. -It's fine to keep that identifier there, in case you need to reference the Perforce change number later. -However, if you'd like to remove the identifier, now is the time to do so – before you start doing work on the new repository. -(((git commands, filter-branch))) -You can use `git filter-branch` to remove the identifier strings en masse: +شما می‌توانید مشاهده کنید که `git-p4` یک شناسه در هر پیغام commit باقی گذاشته است. نگهداری این شناسه مشکلی ندارد، در صورتی که بخواهید شماره تغییر Perforce را بعداً ارجاع دهید. اما اگر تمایل دارید شناسه را حذف کنید، اکنون زمان مناسبی برای این کار است – قبل از شروع به انجام کار روی مخزن جدید. (((دستورات git، filter-branch))) شما می‌توانید از دستور `git filter-branch` برای حذف گروهی شناسه‌ها استفاده کنید: [source,console] ---- @@ -81,7 +74,7 @@ Rewrite e5da1c909e5db3036475419f6379f2c73710c4e6 (125/125) Ref 'refs/heads/master' was rewritten ---- -If you run `git log`, you can see that all the SHA-1 checksums for the commits have changed, but the `git-p4` strings are no longer in the commit messages: +اگر دستور `git log` را اجرا کنید، می‌توانید مشاهده کنید که تمام چک‌سام‌های SHA-1 برای commitها تغییر کرده‌اند، اما رشته‌های `git-p4` دیگر در پیغام‌های commit وجود ندارند: [source,console] ---- @@ -99,4 +92,4 @@ Date: Tue Jul 7 01:35:51 2009 -0800 Fix spelling error on Jam doc page (cummulative -> cumulative). ---- -Your import is ready to push up to your new Git server. +واردات شما آماده است تا به سرور جدید Git منتقل شود. \ No newline at end of file diff --git a/book/09-git-and-other-scms/sections/import-svn.asc b/book/09-git-and-other-scms/sections/import-svn.asc index f33c6ccb..435e2dd8 100644 --- a/book/09-git-and-other-scms/sections/import-svn.asc +++ b/book/09-git-and-other-scms/sections/import-svn.asc @@ -1,16 +1,12 @@ -==== Subversion +==== Subversion (ساب‌ورژن) (((Subversion))) (((Importing, from Subversion))) -If you read the previous section about using `git svn`, you can easily use those instructions to `git svn clone` a repository; then, stop using the Subversion server, push to a new Git server, and start using that. -If you want the history, you can accomplish that as quickly as you can pull the data out of the Subversion server (which may take a while). -However, the import isn't perfect; and because it will take so long, you may as well do it right. -The first problem is the author information. -In Subversion, each person committing has a user on the system who is recorded in the commit information. -The examples in the previous section show `schacon` in some places, such as the `blame` output and the `git svn log`. -If you want to map this to better Git author data, you need a mapping from the Subversion users to the Git authors. -Create a file called `users.txt` that has this mapping in a format like this: +اگر بخش قبلی در مورد استفاده از `git svn` را خوانده باشید، می‌توانید به راحتی از آن دستورالعمل‌ها برای `git svn clone` یک مخزن استفاده کنید؛ سپس از استفاده از سرور Subversion دست بردارید، به سرور جدید Git منتقل کنید و شروع به استفاده از آن کنید. اگر می‌خواهید تاریخچه را نیز حفظ کنید، می‌توانید به سرعت این کار را انجام دهید، به شرطی که داده‌ها را از سرور Subversion استخراج کنید (که ممکن است کمی زمان ببرد). + +با این حال، واردات کامل نیست؛ و چون این فرآیند طولانی خواهد بود، بهتر است آن را به درستی انجام دهید. اولین مشکل اطلاعات نویسنده است. در Subversion، هر شخصی که commit می‌کند، یک کاربر در سیستم دارد که در اطلاعات commit ثبت می‌شود. نمونه‌های بخش قبلی schacon را در برخی مکان‌ها نشان می‌دهند، مانند خروجی blame و git svn log. اگر می‌خواهید این را به داده‌های نویسنده بهتری در Git نگاشت کنید، به یک نگاشت از کاربران Subversion به نویسندگان Git نیاز دارید. یک فایل به نام users.txt ایجاد کنید که این نگاشت را در فرمت زیر داشته باشد: + [source] ---- @@ -18,7 +14,7 @@ schacon = Scott Chacon selse = Someo Nelse ---- -To get a list of the author names that SVN uses, you can run this: +برای دریافت فهرستی از نام‌های نویسندگان که SVN استفاده می‌کند، می‌توانید دستور زیر را اجرا کنید: [source,console] ---- @@ -26,28 +22,21 @@ $ svn log --xml --quiet | grep author | sort -u | \ perl -pe 's/.*>(.*?)<.*/$1 = /' ---- -That generates the log output in XML format, then keeps only the lines with author information, discards duplicates, strips out the XML tags. -Obviously this only works on a machine with `grep`, `sort`, and `perl` installed. -Then, redirect that output into your `users.txt` file so you can add the equivalent Git user data next to each entry. +این دستور خروجی لاگ را در فرمت XML تولید می‌کند، سپس فقط خطوطی که اطلاعات نویسنده را دارند نگه می‌دارد، تکراری‌ها را حذف می‌کند و برچسب‌های XML را حذف می‌کند. مشخصاً این تنها روی سیستمی که `grep`، `sort` و `perl` نصب شده باشد کار می‌کند. سپس آن خروجی را به فایل `users.txt` هدایت کنید تا بتوانید داده‌های معادل نویسنده Git را در کنار هر ورودی اضافه کنید. [NOTE] ==== -If you're trying this on a Windows machine, this is the point where you'll run into trouble. -Microsoft have provided some good advice and samples at https://docs.microsoft.com/en-us/azure/devops/repos/git/perform-migration-from-svn-to-git[]. +اگر این کار را روی یک سیستم ویندوزی امتحان می‌کنید، این نقطه‌ای است که ممکن است با مشکل مواجه شوید. مایکروسافت مشاوره‌ها و نمونه‌های خوبی را در آدرس https://docs.microsoft.com/en-us/azure/devops/repos/git/perform-migration-from-svn-to-git[] ارائه داده است. ==== -You can provide this file to `git svn` to help it map the author data more accurately. -You can also tell `git svn` not to include the metadata that Subversion normally imports, by passing `--no-metadata` to the `clone` or `init` command. -The metadata includes a `git-svn-id` inside each commit message that Git will generate during import. -This can bloat your Git log and might make it a bit unclear. +شما می‌توانید این فایل را به دستور `git svn` ارائه دهید تا به آن کمک کند اطلاعات نویسنده را دقیق‌تر نگاشت کند. همچنین می‌توانید به `git svn` بگویید که متاداده‌هایی که معمولاً توسط Subversion وارد می‌شود را شامل نکند، با استفاده از فلگ `--no-metadata` در دستور `clone` یا `init`. متاداده شامل یک `git-svn-id` در داخل هر پیغام commit است که Git در حین واردات تولید می‌کند. این می‌تواند لاگ Git شما را بزرگ کرده و ممکن است آن را کمی غیرقابل فهم کند. [NOTE] ==== -You need to keep the metadata when you want to mirror commits made in the Git repository back into the original SVN repository. -If you don't want the synchronization in your commit log, feel free to omit the `--no-metadata` parameter. +شما نیاز به نگهداری متاداده زمانی دارید که بخواهید commitهای انجام شده در مخزن Git را دوباره به مخزن اصلی SVN منتقل کنید. اگر نمی‌خواهید همگام‌سازی در لاگ commit شما ظاهر شود، می‌توانید از پارامتر `--no-metadata` صرف‌نظر کنید. ==== -This makes your `import` command look like this: +این دستور باعث می‌شود که دستور `import` شما به شکل زیر باشد: [source,console] ---- @@ -56,8 +45,7 @@ $ git svn clone http://my-project.googlecode.com/svn/ \ $ cd my_project ---- -Now you should have a nicer Subversion import in your `my_project` directory. -Instead of commits that look like this +حالا باید یک واردات بهتر از Subversion در دایرکتوری `my_project` خود داشته باشید. به جای commitهایی که به این شکل هستند [source] ---- @@ -71,7 +59,7 @@ Date: Sun May 3 00:12:22 2009 +0000 be05-5f7a86268029 ---- -they look like this: +آنها به این شکل هستند: [source] ---- @@ -82,58 +70,50 @@ Date: Sun May 3 00:12:22 2009 +0000 fixed install - go to trunk ---- -Not only does the Author field look a lot better, but the `git-svn-id` is no longer there, either. +نه تنها فیلد Author خیلی بهتر به نظر می‌رسد، بلکه `git-svn-id` نیز دیگر وجود ندارد. -You should also do a bit of post-import cleanup. -For one thing, you should clean up the weird references that `git svn` set up. -First you'll move the tags so they're actual tags rather than strange remote branches, and then you'll move the rest of the branches so they're local. +همچنین باید کمی تمیزکاری پس از واردات انجام دهید. اولاً، باید ارجاعات عجیبی که `git svn` ایجاد کرده است را پاک کنید. ابتدا تگ‌ها را جابه‌جا خواهید کرد تا تگ‌های واقعی شوند نه شاخه‌های عجیب از راه دور، سپس باقی‌مانده شاخه‌ها را جابه‌جا خواهید کرد تا به شاخه‌های محلی تبدیل شوند. -To move the tags to be proper Git tags, run: +برای جابه‌جایی تگ‌ها به تگ‌های مناسب Git، دستور زیر را اجرا کنید: [source,console] ---- $ for t in $(git for-each-ref --format='%(refname:short)' refs/remotes/tags); do git tag ${t/tags\//} $t && git branch -D -r $t; done ---- -This takes the references that were remote branches that started with `refs/remotes/tags/` and makes them real (lightweight) tags. +این دستور ارجاعات مربوط به شاخه‌های از راه دور که با `refs/remotes/tags/` شروع می‌شدند را گرفته و آن‌ها را به تگ‌های واقعی (سبک‌وزن) تبدیل می‌کند. -Next, move the rest of the references under `refs/remotes` to be local branches: +سپس، باقی‌مانده ارجاعات زیر `refs/remotes` را به شاخه‌های محلی تبدیل کنید: [source,console] ---- $ for b in $(git for-each-ref --format='%(refname:short)' refs/remotes); do git branch $b refs/remotes/$b && git branch -D -r $b; done ---- -It may happen that you'll see some extra branches which are suffixed by `@xxx` (where xxx is a number), while in Subversion you only see one branch. -This is actually a Subversion feature called ``peg-revisions'', which is something that Git simply has no syntactical counterpart for. -Hence, `git svn` simply adds the svn version number to the branch name just in the same way as you would have written it in svn to address the peg-revision of that branch. -If you do not care anymore about the peg-revisions, simply remove them: +ممکن است با برخی شاخه‌های اضافی روبه‌رو شوید که با `@xxx` (که در آن xxx یک عدد است) پسوند خورده‌اند، در حالی که در Subversion فقط یک شاخه مشاهده می‌کنید. این در واقع یک ویژگی از Subversion به نام `peg-revisions` است، که چیزی است که Git هیچ معادل نحوی برای آن ندارد. بنابراین، `git svn` به سادگی شماره نسخه svn را به نام شاخه اضافه می‌کند، به همان روشی که شما در svn برای ارجاع به peg-revision آن شاخه نوشته‌اید. اگر دیگر به peg-revisions اهمیتی نمی‌دهید، به سادگی آن‌ها را حذف کنید: [source,console] ---- $ for p in $(git for-each-ref --format='%(refname:short)' | grep @); do git branch -D $p; done ---- -Now all the old branches are real Git branches and all the old tags are real Git tags. +حال همه شاخه‌های قدیمی به شاخه‌های واقعی Git تبدیل شده‌اند و تمام تگ‌های قدیمی به تگ‌های واقعی Git تبدیل شده‌اند. -There's one last thing to clean up. -Unfortunately, `git svn` creates an extra branch named `trunk`, which maps to Subversion's default branch, but the `trunk` ref points to the same place as `master`. -Since `master` is more idiomatically Git, here's how to remove the extra branch: +یک چیز آخر برای تمیزکاری باقی‌مانده است. متاسفانه، `git svn` یک شاخه اضافی به نام `trunk` ایجاد می‌کند که به شاخه پیش‌فرض Subversion اشاره دارد، اما ارجاع trunk به همان مکانی اشاره می‌کند که `master` است. از آنجا که `master` به طور معمول در Git استفاده می‌شود، اینجا نحوه حذف شاخه اضافی آورده شده است: [source,console] ---- $ git branch -d trunk ---- -The last thing to do is add your new Git server as a remote and push to it. -Here is an example of adding your server as a remote: +آخرین کاری که باید انجام دهید، اضافه کردن سرور جدید Git خود به عنوان یک remote و سپس push کردن به آن است. در اینجا یک مثال از اضافه کردن سرور خود به عنوان یک remote آورده شده است: [source,console] ---- $ git remote add origin git@my-git-server:myrepository.git ---- -Because you want all your branches and tags to go up, you can now run this: +چون می‌خواهید تمام شاخه‌ها و تگ‌های خود را ارسال کنید، اکنون می‌توانید دستور زیر را اجرا کنید: [source,console] ---- @@ -141,4 +121,4 @@ $ git push origin --all $ git push origin --tags ---- -All your branches and tags should be on your new Git server in a nice, clean import. +تمام شاخه‌ها و تگ‌های شما باید در سرور جدید Git شما در یک واردات تمیز و مرتب قرار داشته باشند. diff --git a/book/09-git-and-other-scms/sections/import-tfs.asc b/book/09-git-and-other-scms/sections/import-tfs.asc index 68a7f4cf..4678041f 100644 --- a/book/09-git-and-other-scms/sections/import-tfs.asc +++ b/book/09-git-and-other-scms/sections/import-tfs.asc @@ -2,59 +2,51 @@ ==== TFS (((TFS)))(((Importing, from TFS))) -If your team is converting their source control from TFVC to Git, you'll want the highest-fidelity conversion you can get. -This means that, while we covered both git-tfs and git-tf for the interop section, we'll only be covering git-tfs for this part, because git-tfs supports branches, and this is prohibitively difficult using git-tf. + +اگر تیم شما در حال تبدیل کنترل نسخه خود از TFVC به Git است، شما به یک تبدیل با بالاترین دقت نیاز دارید. این به این معناست که، در حالی که ما هم `git-tfs` و هم `git-tf` را برای بخش ارتباط متقابل بررسی کردیم، در این بخش فقط `git-tfs` را پوشش خواهیم داد، زیرا `git-tfs` از شاخه‌ها پشتیبانی می‌کند، و انجام این کار با استفاده از `git-tf` به طور غیرقابل تحملی دشوار است. [NOTE] ==== -This is a one-way conversion. -The resulting Git repository won't be able to connect with the original TFVC project. +این یک تبدیل یک‌طرفه است. مخزن Git نتیجه‌گیری شده قادر نخواهد بود به پروژه اصلی TFVC متصل شود. ==== -The first thing to do is map usernames. -TFVC is fairly liberal with what goes into the author field for changesets, but Git wants a human-readable name and email address. -You can get this information from the `tf` command-line client, like so: +اولین کاری که باید انجام دهید، نگاشت نام‌های کاربری است. TFVC نسبتاً آزاد است در مورد اینکه چه چیزی در فیلد نویسنده برای تغییرات وارد شود، اما Git به یک نام قابل‌خواندن و آدرس ایمیل نیاز دارد. شما می‌توانید این اطلاعات را از طریق کلاینت خط فرمان `tf` به دست آورید، به این صورت: [source,powershell] ---- PS> tf history $/myproject -recursive > AUTHORS_TMP ---- -This grabs all of the changesets in the history of the project and put it in the AUTHORS_TMP file that we will process to extract the data of the 'User' column (the 2nd one). -Open the file and find at which characters start and end the column and replace, in the following command-line, the parameters `11-20` of the `cut` command with the ones found: +این دستور تمام تغییرات در تاریخچه پروژه را جمع‌آوری می‌کند و آن را در فایل `AUTHORS_TMP` قرار می‌دهد که ما برای استخراج داده‌های ستون 'User' (دومین ستون) آن را پردازش خواهیم کرد. فایل را باز کنید و پیدا کنید که ستون از کدام کاراکترها شروع و تمام می‌شود، سپس در دستور خط فرمان زیر، پارامترهای `11-20` دستور `cut` را با مقادیری که پیدا کرده‌اید جایگزین کنید: [source,powershell] ---- PS> cat AUTHORS_TMP | cut -b 11-20 | tail -n+3 | sort | uniq > AUTHORS ---- -The `cut` command keeps only the characters between 11 and 20 from each line. -The `tail` command skips the first two lines, which are field headers and ASCII-art underlines. -The result of all of this is piped to `sort` and `uniq` to eliminate duplicates, and saved to a file named `AUTHORS`. -The next step is manual; in order for git-tfs to make effective use of this file, each line must be in this format: +دستور `cut` تنها کاراکترهای بین 11 و 20 هر خط را نگه می‌دارد. دستور `tail` دو خط اول را که شامل هدرهای فیلد و خط‌های زیرنویس `ASCII` هستند، نادیده می‌گیرد. نتیجه تمام این‌ها به دستور `sort` و سپس `uniq` ارسال می‌شود تا تکراری‌ها حذف شوند و در فایلی به نام `AUTHORS` ذخیره می‌شود. گام بعدی دستی است؛ برای اینکه `git-tfs` به طور مؤثر از این فایل استفاده کند، هر خط باید به این فرمت باشد: [source,text] ---- DOMAIN\username = User Name ---- -The portion on the left is the ``User'' field from TFVC, and the portion on the right side of the equals sign is the user name that will be used for Git commits. +بخش سمت چپ فیلد `User` از `TFVC` است، و بخش سمت راست علامت مساوی نام کاربری است که برای commitهای Git استفاده خواهد شد. -Once you have this file, the next thing to do is make a full clone of the TFVC project you're interested in: +زمانی که این فایل را داشته باشید، گام بعدی این است که یک کلون کامل از پروژه TFVC که به آن علاقه دارید، ایجاد کنید: [source,powershell] ---- PS> git tfs clone --with-branches --authors=AUTHORS https://username.visualstudio.com/DefaultCollection $/project/Trunk project_git ---- -Next you'll want to clean the `git-tfs-id` sections from the bottom of the commit messages. -The following command will do that: +در مرحله بعد، شما باید بخش‌های `git-tfs-id` را از انتهای پیغام‌های commit پاک کنید. دستور زیر این کار را انجام می‌دهد: [source,powershell] ---- PS> git filter-branch -f --msg-filter 'sed "s/^git-tfs-id:.*$//g"' '--' --all ---- -That uses the `sed` command from the Git-bash environment to replace any line starting with ``git-tfs-id:'' with emptiness, which Git will then ignore. +این دستور از دستور `sed` در محیط Git-bash استفاده می‌کند تا هر خطی که با `git-tfs-id:` شروع می‌شود را با فضای خالی جایگزین کند، که سپس توسط Git نادیده گرفته می‌شود. -Once that's all done, you're ready to add a new remote, push all your branches up, and have your team start working from Git. +زمانی که این مراحل انجام شد، شما آماده‌اید تا یک remote جدید اضافه کنید، تمام شاخه‌های خود را push کنید و تیم شما از Git شروع به کار کند. diff --git a/book/10-git-internals/sections/environment.asc b/book/10-git-internals/sections/environment.asc index fb39c9a4..4a22e3f9 100644 --- a/book/10-git-internals/sections/environment.asc +++ b/book/10-git-internals/sections/environment.asc @@ -1,138 +1,134 @@ -=== Environment Variables +=== Environment Variables (متغیرهای محیطی) -Git always runs inside a `bash` shell, and uses a number of shell environment variables to determine how it behaves. -Occasionally, it comes in handy to know what these are, and how they can be used to make Git behave the way you want it to. -This isn't an exhaustive list of all the environment variables Git pays attention to, but we'll cover the most useful. + همیشه در یک شِل `bash` اجرا می‌شود و از مجموعه‌ای از متغیرهای محیطی شِل برای تعیین رفتار خود استفاده می‌کند. +گاهی اوقات دانستن این متغیرها و نحوه استفاده از آن‌ها برای کنترل دقیق‌تر Git مفید است. +این فهرست، تمام متغیرهای محیطی مورد توجه Git را شامل نمی‌شود، اما پرکاربردترین و مفیدترین آن‌ها را پوشش می‌دهد. +==== Global Behavior (رفتار سراسری) -==== Global Behavior +برخی از رفتارهای کلی Git به عنوان یک برنامه کامپیوتری، به متغیرهای محیطی بستگی دارد. -Some of Git's general behavior as a computer program depends on environment variables. +*`GIT_EXEC_PATH`* مشخص می‌کند که Git کجا به دنبال زیر‌برنامه‌های خود می‌گردد (مانند `git-commit`، `git-diff` و سایر ابزارها). +برای بررسی مقدار فعلی آن، می‌توانید دستور `git --exec-path` را اجرا کنید. -*`GIT_EXEC_PATH`* determines where Git looks for its sub-programs (like `git-commit`, `git-diff`, and others). - You can check the current setting by running `git --exec-path`. +*`HOME`* معمولاً به‌عنوان متغیری قابل تنظیم در نظر گرفته نمی‌شود (چون بسیاری از چیزهای دیگر به آن وابسته‌اند)، اما Git از این مسیر برای یافتن فایل تنظیمات سراسری (global config) استفاده می‌کند. +اگر بخواهید یک نصب قابل حمل از Git داشته باشید (که شامل تنظیمات سراسری هم باشد)، می‌توانید متغیر HOME را در پروفایل شِل Git قابل حمل تغییر دهید. -*`HOME`* isn't usually considered customizable (too many other things depend on it), but it's where Git looks for the global configuration file. - If you want a truly portable Git installation, complete with global configuration, you can override `HOME` in the portable Git's shell profile. +*`PREFIX`* مشابه مورد قبلی است، اما برای تنظیمات سراسری سیستم. +Git فایل پیکربندی را در مسیر `$PREFIX/etc/gitconfig` جست‌وجو می‌کند. -*`PREFIX`* is similar, but for the system-wide configuration. - Git looks for this file at `$PREFIX/etc/gitconfig`. +*`GIT_CONFIG_NOSYSTEM`* اگر مقداردهی شود، استفاده از فایل پیکربندی سراسری سیستم را غیرفعال می‌کند. +این گزینه زمانی مفید است که تنظیمات سیستم با دستورات شما تداخل دارند، اما شما دسترسی برای تغییر یا حذف آن‌ها ندارید. -*`GIT_CONFIG_NOSYSTEM`*, if set, disables the use of the system-wide configuration file. - This is useful if your system config is interfering with your commands, but you don't have access to change or remove it. +*`GIT_PAGER`* برنامه‌ای را مشخص می‌کند که برای نمایش خروجی‌های چند صفحه‌ای در خط فرمان استفاده می‌شود. +اگر این متغیر تنظیم نشده باشد، Git از مقدار `PAGER` استفاده خواهد کرد. -*`GIT_PAGER`* controls the program used to display multi-page output on the command line. -If this is unset, `PAGER` will be used as a fallback. +*`GIT_EDITOR`* ویرایشگری را مشخص می‌کند که Git هنگام نیاز به ویرایش متن (مثل پیام کامیت) اجرا می‌کند. +اگر این متغیر تنظیم نشده باشد، Git از مقدار `EDITOR` استفاده خواهد کرد. -*`GIT_EDITOR`* is the editor Git will launch when the user needs to edit some text (a commit message, for example). -If unset, `EDITOR` will be used. +==== Repository Locations (موقعیت‌های مخزن) +Git از چندین متغیر محیطی استفاده می‌کند تا مشخص کند چگونه با مخزن فعلی تعامل داشته باشد. -==== Repository Locations +*`GIT_DIR`* مسیر پوشه `.git` را مشخص می‌کند. +اگر این مقدار تنظیم نشده باشد، Git به صورت بازگشتی درخت دایرکتوری را به سمت بالا پیمایش می‌کند و در هر مرحله به دنبال پوشه‌ای به نام `.git` می‌گردد، تا زمانی که به پوشه‌ی خانگی (`~`) یا ریشه‌ی فایل‌سیستم (`/`) برسد. -Git uses several environment variables to determine how it interfaces with the current repository. +*`GIT_CEILING_DIRECTORIES`* رفتار جستجوی پوشه .git را کنترل می‌کند. +اگر در مسیرهایی کار می‌کنید که بارگذاری آن‌ها کند است (مثل درایوهای نواری یا مسیرهای شبکه‌ای کند)، ممکن است بخواهید Git را طوری تنظیم کنید که زودتر از ادامه جستجو صرف‌نظر کند—مخصوصاً اگر Git هنگام ساختن prompt خط فرمان اجرا شود. -*`GIT_DIR`* is the location of the `.git` folder. -If this isn't specified, Git walks up the directory tree until it gets to `~` or `/`, looking for a `.git` directory at every step. +*`GIT_WORK_TREE`* مسیر ریشه‌ی دایرکتوری کاری برای یک مخزن غیر‌برهنه (non-bare) را مشخص می‌کند. +اگر `--git-dir` یا متغیر `GIT_DIR` تنظیم شده باشد اما هیچ‌کدام از `--work-tree،` `GIT_WORK_TREE` یا `core.worktree` مشخص نشده باشند، دایرکتوری جاری به عنوان بالاترین سطح دایرکتوری کاری در نظر گرفته می‌شود. -*`GIT_CEILING_DIRECTORIES`* controls the behavior of searching for a `.git` directory. -If you access directories that are slow to load (such as those on a tape drive, or across a slow network connection), you may want to have Git stop trying earlier than it might otherwise, especially if Git is invoked when building your shell prompt. +*`GIT_INDEX_FILE`* مسیر فایل ایندکس را مشخص می‌کند (فقط برای مخازن غیر‌برهنه). -*`GIT_WORK_TREE`* is the location of the root of the working directory for a non-bare repository. -If `--git-dir` or `GIT_DIR` is specified but none of `--work-tree`, `GIT_WORK_TREE` or `core.worktree` is specified, the current working directory is regarded as the top level of your working tree. +*`GIT_OBJECT_DIRECTORY`* می‌تواند برای مشخص کردن مکان دایرکتوری‌ای که معمولاً در .git/objects قرار دارد استفاده شود. -*`GIT_INDEX_FILE`* is the path to the index file (non-bare repositories only). +*`GIT_ALTERNATE_OBJECT_DIRECTORIES`* لیستی از مسیرهاست که با دو‌نقطه از هم جدا شده‌اند (مثل: `/dir/one:/dir/two:…`) و به Git می‌گوید اگر شیء مورد نظر در `GIT_OBJECT_DIRECTORY` یافت نشد، کجاهای دیگر را بررسی کند. +اگر پروژه‌های زیادی با فایل‌های حجیم و یکسان دارید، این روش می‌تواند از ذخیره چندباره‌ی آن فایل‌ها جلوگیری کند. -*`GIT_OBJECT_DIRECTORY`* can be used to specify the location of the directory that usually resides at `.git/objects`. +==== Pathspec (مسیرها) -*`GIT_ALTERNATE_OBJECT_DIRECTORIES`* is a colon-separated list (formatted like `/dir/one:/dir/two:…`) which tells Git where to check for objects if they aren't in `GIT_OBJECT_DIRECTORY`. -If you happen to have a lot of projects with large files that have the exact same contents, this can be used to avoid storing too many copies of them. +عبارت `pathspec` به نحوه‌ای اشاره دارد که در آن مسیر فایل‌ها را در Git مشخص می‌کنید، از جمله استفاده از کاراکترهای وایلدکارد (wildcards). +این ساختارها هم در فایل `.gitignore` استفاده می‌شوند و هم در دستورات خط فرمان مانند: +`git add *.c` +*`GIT_GLOB_PATHSPECS`* و *`GIT_NOGLOB_PATHSPECS`* رفتار پیش‌فرض استفاده از وایلدکاردها در pathspecs را کنترل می‌کنند. +اگر `GIT_GLOB_PATHSPECS` برابر با 1 تنظیم شده باشد، کاراکترهای وایلدکارد به صورت معمول عمل می‌کنند (که این رفتار پیش‌فرض است). اگر `GIT_NOGLOB_PATHSPECS` برابر با 1 تنظیم شود، کاراکترهای وایلدکارد تنها به خودشان تطابق دارند، به این معنی که چیزی مثل *.c فقط با فایلی که نامش دقیقاً *.c است تطابق خواهد داشت، نه هر فایلی که نامش با .c تمام شود. +شما می‌توانید این رفتار را در موارد خاص با شروع pathspec از `:(glob)` یا `:(literal)` تغییر دهید، مانند `:(glob)*.c`. -==== Pathspecs +*`GIT_LITERAL_PATHSPECS`* هر دو رفتار فوق را غیرفعال می‌کند؛ هیچ کاراکتر وایلدکاردی دیگر عمل نخواهد کرد و پیشوندهای override نیز غیرفعال خواهند شد. -A ``pathspec'' refers to how you specify paths to things in Git, including the use of wildcards. -These are used in the `.gitignore` file, but also on the command-line (`git add *.c`). +*`GIT_ICASE_PATHSPECS`* باعث می‌شود همه‌ی pathspec ها به صورت حساس به حروف کوچک و بزرگ کار کنند. -*`GIT_GLOB_PATHSPECS`* and *`GIT_NOGLOB_PATHSPECS`* control the default behavior of wildcards in pathspecs. -If `GIT_GLOB_PATHSPECS` is set to 1, wildcard characters act as wildcards (which is the default); if `GIT_NOGLOB_PATHSPECS` is set to 1, wildcard characters only match themselves, meaning something like `*.c` would only match a file _named_ ``*.c'', rather than any file whose name ends with `.c`. -You can override this in individual cases by starting the pathspec with `:(glob)` or `:(literal)`, as in `:(glob)*.c`. +==== Committing (کامیت کردن) -*`GIT_LITERAL_PATHSPECS`* disables both of the above behaviors; no wildcard characters will work, and the override prefixes are disabled as well. +در نهایت، ایجاد شیء commit در Git معمولاً توسط `git-commit-tree` انجام می‌شود که از این متغیرهای محیطی به عنوان منبع اصلی اطلاعات استفاده می‌کند و تنها در صورتی که این مقادیر موجود نباشند، به مقادیر تنظیمات پیکربندی رجوع می‌کند. -*`GIT_ICASE_PATHSPECS`* sets all pathspecs to work in a case-insensitive manner. +*`GIT_AUTHOR_NAME`* نام قابل خواندن انسانی برای فیلد `author` است. +*`GIT_AUTHOR_EMAIL`* ایمیل مربوط به فیلد `author` است. -==== Committing +*`GIT_AUTHOR_DATE`* زمان‌سنجی که برای فیلد `author` استفاده می‌شود. -The final creation of a Git commit object is usually done by `git-commit-tree`, which uses these environment variables as its primary source of information, falling back to configuration values only if these aren't present. +*`GIT_COMMITTER_NAME`* نام انسانی برای فیلد `committer` را تنظیم می‌کند. -*`GIT_AUTHOR_NAME`* is the human-readable name in the ``author'' field. +*`GIT_COMMITTER_EMAIL`* آدرس ایمیل مربوط به فیلد `committer` است. -*`GIT_AUTHOR_EMAIL`* is the email for the ``author'' field. +*`GIT_COMMITTER_DATE`* برای زمان‌سنجی در فیلد `committer` استفاده می‌شود. -*`GIT_AUTHOR_DATE`* is the timestamp used for the ``author'' field. +*`EMAIL`* آدرس ایمیل پشتیبان است که در صورتی که مقدار پیکربندی `user.email` تنظیم نشده باشد، از آن استفاده می‌شود. +اگر این مقدار نیز تنظیم نشده باشد، Git به نام‌های کاربری و میزبان سیستم باز می‌گردد. -*`GIT_COMMITTER_NAME`* sets the human name for the ``committer'' field. +==== Networking (شبکه) -*`GIT_COMMITTER_EMAIL`* is the email address for the ``committer'' field. +گیت از کتابخانه curl برای انجام عملیات شبکه‌ای بر روی HTTP استفاده می‌کند، بنابراین GIT_CURL_VERBOSE به گیت می‌گوید که تمام پیام‌های تولید شده توسط این کتابخانه را نمایش دهد. این مشابه اجرای دستور curl -v در خط فرمان است. -*`GIT_COMMITTER_DATE`* is used for the timestamp in the ``committer'' field. +*`GIT_SSL_NO_VERIFY`* به گیت می‌گوید که گواهی‌نامه‌های SSL را تأیید نکند. این گاهی اوقات لازم است اگر از گواهی‌نامه خود امضا شده برای سرویس‌دهی به مخازن گیت از طریق HTTPS استفاده می‌کنید، یا در حال راه‌اندازی یک سرور گیت هستید و هنوز گواهی‌نامه کامل نصب نکرده‌اید. -*`EMAIL`* is the fallback email address in case the `user.email` configuration value isn't set. -If _this_ isn't set, Git falls back to the system user and host names. +اگر سرعت داده یک عملیات HTTP کمتر از *`GIT_HTTP_LOW_SPEED_LIMIT`* بایت در ثانیه برای مدت زمان بیش از *`GIT_HTTP_LOW_SPEED_TIME`* ثانیه باشد، گیت آن عملیات را قطع می‌کند. این مقادیر بر تنظیمات پیکربندی http.lowSpeedLimit و http.lowSpeedTime ارجحیت دارند. +*`GIT_HTTP_USER_AGENT`* رشته `user-agent` مورد استفاده گیت را هنگام ارتباط از طریق HTTP تنظیم می‌کند. مقدار پیش‌فرض معمولاً چیزی شبیه به `git/2.0.0` است. -==== Networking +==== Diffing and Merging (تفاوت و ادغام) -Git uses the `curl` library to do network operations over HTTP, so *`GIT_CURL_VERBOSE`* tells Git to emit all the messages generated by that library. -This is similar to doing `curl -v` on the command line. +*`GIT_DIFF_OPTS`* کمی محدود است. تنها مقادیر معتبر برای این متغیر محیطی، `-u` یا `--unified=` هستند که تعداد خطوط زمینه‌ای (context lines) که در دستور `git diff` نمایش داده می‌شود را کنترل می‌کنند. -*`GIT_SSL_NO_VERIFY`* tells Git not to verify SSL certificates. -This can sometimes be necessary if you're using a self-signed certificate to serve Git repositories over HTTPS, or you're in the middle of setting up a Git server but haven't installed a full certificate yet. +*`GIT_EXTERNAL_DIFF`* به عنوان جایگزینی برای مقدار پیکربندی `diff.external` عمل می‌کند. اگر تنظیم شده باشد، گیت این برنامه را هنگام فراخوانی `git diff` اجرا خواهد کرد. +*`GIT_DIFF_PATH_COUNTER`* و *`GIT_DIFF_PATH_TOTAL`* بیشتر در داخل برنامه‌ای که توسط `GIT_EXTERNAL_DIFF` یا `diff.external` مشخص شده مفید هستند. -If the data rate of an HTTP operation is lower than *`GIT_HTTP_LOW_SPEED_LIMIT`* bytes per second for longer than *`GIT_HTTP_LOW_SPEED_TIME`* seconds, Git will abort that operation. -These values override the `http.lowSpeedLimit` and `http.lowSpeedTime` configuration values. + اولی نشان‌دهنده شماره فایل در یک دسته تفاوت است (شروع از 1). -*`GIT_HTTP_USER_AGENT`* sets the user-agent string used by Git when communicating over HTTP. -The default is a value like `git/2.0.0`. + دومی تعداد کل فایل‌ها در دسته است. +*`GIT_MERGE_VERBOSITY`* خروجی استراتژی ادغام (merge strategy) را کنترل می‌کند. مقادیر مجاز به شرح زیر است: -==== Diffing and Merging + * 0: هیچ چیزی را خروجی نمی‌دهد، به جز ممکن است یک پیام خطا. -*`GIT_DIFF_OPTS`* is a bit of a misnomer. -The only valid values are `-u` or `--unified=`, which controls the number of context lines shown in a `git diff` command. + * 1: فقط تضادها (conflicts) را نشان می‌دهد. -*`GIT_EXTERNAL_DIFF`* is used as an override for the `diff.external` configuration value. -If it's set, Git will invoke this program when `git diff` is invoked. + * 2: همچنین تغییرات فایل را نشان می‌دهد. -*`GIT_DIFF_PATH_COUNTER`* and *`GIT_DIFF_PATH_TOTAL`* are useful from inside the program specified by `GIT_EXTERNAL_DIFF` or `diff.external`. -The former represents which file in a series is being diffed (starting with 1), and the latter is the total number of files in the batch. + * 3: نشان می‌دهد که فایل‌ها به دلیل عدم تغییر نادیده گرفته شده‌اند. -*`GIT_MERGE_VERBOSITY`* controls the output for the recursive merge strategy. -The allowed values are as follows: + * 4: تمام مسیرها را در حین پردازش نشان می‌دهد. -* 0 outputs nothing, except possibly a single error message. -* 1 shows only conflicts. -* 2 also shows file changes. -* 3 shows when files are skipped because they haven't changed. -* 4 shows all paths as they are processed. -* 5 and above show detailed debugging information. + * 5 و بالاتر: اطلاعات اشکال‌زدایی دقیق‌تر را نشان می‌دهد. -The default value is 2. +مقدار پیش‌فرض برای این متغیر محیطی 2 است. -==== Debugging +==== Debugging (اشکال‌زدایی) -Want to _really_ know what Git is up to? -Git has a fairly complete set of traces embedded, and all you need to do is turn them on. -The possible values of these variables are as follows: +می‌خواهید _واقعاً_ بدانید گیت چه کار می‌کند؟ + گیت مجموعه‌ای نسبتاً کامل از ردیابی‌ها را در خود دارد و تنها کاری که باید انجام دهید این است که آن‌ها را فعال + کنید. + مقادیر ممکن این متغیرها به شرح زیر است: -* ``true'', ``1'', or ``2'' – the trace category is written to stderr. -* An absolute path starting with `/` – the trace output will be written to that file. +* `true`، `1`، یا `2` – دسته ردیابی به stderr نوشته می‌شود. +* یک مسیر مطلق که با `/` شروع می‌شود – خروجی ردیابی به آن فایل نوشته می‌شود. -*`GIT_TRACE`* controls general traces, which don't fit into any specific category. -This includes the expansion of aliases, and delegation to other sub-programs. +*`GIT_TRACE`* ردیابی‌های عمومی را کنترل می‌کند که در هیچ دسته خاصی قرار نمی‌گیرند. + این شامل گسترش مستعارها و واگذاری به سایر زیر برنامه‌ها است. [source,console] ---- @@ -145,8 +141,8 @@ $ GIT_TRACE=true git lga 20:12:49.899675 run-command.c:192 trace: exec: 'less' ---- -*`GIT_TRACE_PACK_ACCESS`* controls tracing of packfile access. -The first field is the packfile being accessed, the second is the offset within that file: + +*`GIT_TRACE_PACK_ACCESS`* کنترل می‌کند که آیا دسترسی به فایل‌های pack در گیت ردیابی شود یا نه. اولین فیلد، نام فایل pack را نشان می‌دهد که به آن دسترسی پیدا می‌شود، و دومین فیلد، آفست (مکان) داخل آن فایل را نشان می‌دهد. این تنظیم برای اشکال‌زدایی و بررسی عملکرد دسترسی به داده‌ها در فایل‌های pack مفید است. [source,console] ---- @@ -162,7 +158,7 @@ Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean ---- -*`GIT_TRACE_PACKET`* enables packet-level tracing for network operations. +*`GIT_TRACE_PACKET`* قابلیت رهگیری بسته‌ها در سطح شبکه را برای عملیات‌های گیت فعال می‌کند. [source,console] ---- @@ -175,8 +171,8 @@ $ GIT_TRACE_PACKET=true git ls-remote origin # […] ---- -*`GIT_TRACE_PERFORMANCE`* controls logging of performance data. -The output shows how long each particular `git` invocation takes. +*`GIT_TRACE_PERFORMANCE`* کنترل ثبت داده‌های عملکرد را بر عهده دارد. +خروجی نشان می‌دهد که هر فراخوانی خاص git چقدر زمان برده است. [source,console] ---- @@ -198,7 +194,7 @@ Checking connectivity: 170994, done. 20:18:25.233159 trace.c:414 performance: 6.112217000 s: git command: 'git' 'gc' ---- -*`GIT_TRACE_SETUP`* shows information about what Git is discovering about the repository and environment it's interacting with. +*`GIT_TRACE_SETUP`* اطلاعاتی را درباره آنچه گیت در حال کشف کردن در مورد مخزن و محیطی که با آن تعامل دارد، نمایش می‌دهد. [source,console] ---- @@ -212,26 +208,27 @@ Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean ---- -==== Miscellaneous +==== Miscellaneous (متفرقه) + -*`GIT_SSH`*, if specified, is a program that is invoked instead of `ssh` when Git tries to connect to an SSH host. -It is invoked like `$GIT_SSH [username@]host [-p ] `. -Note that this isn't the easiest way to customize how `ssh` is invoked; it won't support extra command-line parameters, so you'd have to write a wrapper script and set `GIT_SSH` to point to it. -It's probably easier just to use the `~/.ssh/config` file for that. +*`GIT_SSH`* ، اگر مشخص شده باشد، برنامه‌ای است که به جای `ssh` هنگام تلاش گیت برای اتصال به یک میزبان SSH فراخوانی می‌شود. +این به شکل `$GIT_SSH [username@]host [-p ] ` فراخوانی می‌شود. +توجه داشته باشید که این آسان‌ترین راه برای سفارشی کردن نحوه فراخوانی `ssh` نیست؛ این از پارامترهای اضافی خط فرمان پشتیبانی نمی‌کند، بنابراین شما باید یک اسکریپت wrapper بنویسید و `GIT_SSH` را به آن اشاره کنید. +احتمالاً بهتر است فقط از فایل `~/.ssh/config` برای این کار استفاده کنید. -*`GIT_ASKPASS`* is an override for the `core.askpass` configuration value. -This is the program invoked whenever Git needs to ask the user for credentials, which can expect a text prompt as a command-line argument, and should return the answer on `stdout`. -(See <> for more on this subsystem.) +*`GIT_ASKPASS`* یک بازنویسی برای مقدار پیکربندی `core.askpass` است. +این برنامه‌ای است که هر بار که گیت نیاز به درخواست اعتبارنامه از کاربر دارد، فراخوانی می‌شود و می‌تواند انتظار یک متن درخواست به عنوان آرگومان خط فرمان را داشته باشد و باید پاسخ را در `stdout` برگرداند. +(برای اطلاعات بیشتر در مورد این زیرسیستم، به <<_credential_caching#_credential_caching>> مراجعه کنید.) -*`GIT_NAMESPACE`* controls access to namespaced refs, and is equivalent to the `--namespace` flag. -This is mostly useful on the server side, where you may want to store multiple forks of a single repository in one repository, only keeping the refs separate. +*`GIT_NAMESPACE`* دسترسی به refs نام‌گذاری شده را کنترل می‌کند و معادل با پرچم `--namespace` است. +این بیشتر در سمت سرور مفید است، جایی که ممکن است بخواهید چندین فورک از یک مخزن واحد را در یک مخزن ذخیره کنید و فقط refs را جدا نگه دارید. -*`GIT_FLUSH`* can be used to force Git to use non-buffered I/O when writing incrementally to stdout. -A value of 1 causes Git to flush more often, a value of 0 causes all output to be buffered. -The default value (if this variable is not set) is to choose an appropriate buffering scheme depending on the activity and the output mode. +*`GIT_FLUSH`* می‌تواند برای مجبور کردن گیت به استفاده از I/O غیر بافر شده هنگام نوشتن به تدریج به stdout استفاده شود. +مقدار 1 باعث می‌شود گیت بیشتر flush کند، و مقدار 0 باعث می‌شود تمام خروجی بافر شود. +مقدار پیش‌فرض (اگر این متغیر تنظیم نشده باشد) انتخاب یک طرح بافر مناسب بسته به فعالیت و حالت خروجی است. -*`GIT_REFLOG_ACTION`* lets you specify the descriptive text written to the reflog. -Here's an example: +*`GIT_REFLOG_ACTION`* به شما اجازه می‌دهد متن توصیفی نوشته شده به reflog را مشخص کنید. +در اینجا یک مثال است: [source,console] ---- diff --git a/ch08-customizing-git.asc b/ch08-customizing-git.asc index 2af938c0..a422cd76 100644 --- a/ch08-customizing-git.asc +++ b/ch08-customizing-git.asc @@ -1,9 +1,7 @@ [[ch08-customizing-git]] -== Customizing Git +== Customizing Git (سفارشی‌سازی Git) -So far, we've covered the basics of how Git works and how to use it, and we've introduced a number of tools that Git provides to help you use it easily and efficiently. -In this chapter, we'll see how you can make Git operate in a more customized fashion, by introducing several important configuration settings and the hooks system. -With these tools, it's easy to get Git to work exactly the way you, your company, or your group needs it to. +تا اینجا، اصول اولیه نحوه کار Git و نحوه استفاده از آن را پوشش داده‌ایم و تعدادی ابزار که Git برای استفاده آسان و کارآمد ارائه می‌دهد را معرفی کرده‌ایم. در این فصل، خواهیم دید که چگونه می‌توانید Git را به صورت سفارشی‌تر تنظیم کنید، با معرفی چند تنظیمات پیکربندی مهم و سیستم hook‌ها. با این ابزارها، آسان است که Git را طوری تنظیم کنید که دقیقاً مطابق با نیاز شما، شرکت یا گروه شما عمل کند. include::book/08-customizing-git/sections/config.asc[] @@ -13,8 +11,6 @@ include::book/08-customizing-git/sections/hooks.asc[] include::book/08-customizing-git/sections/policy.asc[] -=== Summary +=== Summary (خلاصه) -We've covered most of the major ways that you can customize your Git client and server to best fit your workflow and projects. -You've learned about all sorts of configuration settings, file-based attributes, and event hooks, and you've built an example policy-enforcing server. -You should now be able to make Git fit nearly any workflow you can dream up. +ما بیشتر روش‌های اصلی که می‌توانید کلاینت و سرور Git خود را برای بهترین تطابق با جریان کار و پروژه‌هایتان سفارشی کنید پوشش داده‌ایم. شما در مورد انواع مختلف تنظیمات پیکربندی، ویژگی‌های مبتنی بر فایل و hook‌های رویداد یاد گرفته‌اید و یک سرور نمونه برای اجرای سیاست‌ها ساخته‌اید. اکنون باید قادر باشید Git را برای هر جریان کاری که تصور کنید، مناسب کنید. \ No newline at end of file diff --git a/ch09-git-and-other-systems.asc b/ch09-git-and-other-systems.asc index 43b0b359..e7f8b39f 100644 --- a/ch09-git-and-other-systems.asc +++ b/ch09-git-and-other-systems.asc @@ -1,20 +1,21 @@ [[ch09-git-and-other-systems]] -== Git and Other Systems +== Git and Other Systems (گیت و سایر سیستم ها) -The world isn't perfect. -Usually, you can't immediately switch every project you come in contact with to Git. -Sometimes you're stuck on a project using another VCS, and wish it was Git. -We'll spend the first part of this chapter learning about ways to use Git as a client when the project you're working on is hosted in a different system. +دنیا بی‌نقص نیست. +معمولاً نمی‌توانید بلافاصله تمام پروژه‌هایی که با آن‌ها در ارتباط هستید را به Git منتقل کنید. +گاهی اوقات در پروژه‌ای گرفتار می‌شوید که از یک سیستم کنترل نسخه‌ی دیگر استفاده می‌کند و آرزو می‌کنید ای کاش Git بود. +در بخش اول این فصل، به بررسی روش‌هایی می‌پردازیم که می‌توانید از Git به عنوان کلاینت استفاده کنید، حتی زمانی که پروژه‌ای که روی آن کار می‌کنید روی سیستمی دیگر میزبانی شده باشد. -At some point, you may want to convert your existing project to Git. -The second part of this chapter covers how to migrate your project into Git from several specific systems, as well as a method that will work if no pre-built import tool exists. +در مقطعی ممکن است بخواهید پروژه‌ی موجود خود را به Git منتقل کنید. +بخش دوم این فصل به چگونگی مهاجرت پروژه‌ از چند سیستم خاص به Git می‌پردازد، و همچنین روشی را پوشش می‌دهد که اگر ابزار آماده‌ای برای وارد کردن پروژه وجود نداشت، همچنان بتوانید مهاجرت را انجام دهید. -=== Git as a Client +=== Git as a Client (گیت به عنوان کلاینت) (((Git as a client))) -Git provides such a nice experience for developers that many people have figured out how to use it on their workstation, even if the rest of their team is using an entirely different VCS. -There are a number of these adapters, called ``bridges,'' available. -Here we'll cover the ones you're most likely to run into in the wild. +Git تجربه‌ی بسیار خوبی برای توسعه‌دهندگان فراهم می‌کند، تا حدی که بسیاری از افراد یاد گرفته‌اند چگونه از آن در سیستم شخصی خود استفاده کنند—even اگر باقی تیم‌شان از یک سیستم کنترل نسخه‌ی کاملاً متفاوت استفاده می‌کند. +برای این منظور، ابزارهای مختلفی به نام «bridge» یا «پل ارتباطی» وجود دارند که این امکان را فراهم می‌کنند. + +در این بخش، به بررسی رایج‌ترین این bridge‌ها می‌پردازیم—ابزارهایی که احتمالاً در دنیای واقعی با آن‌ها مواجه خواهید شد. include::book/09-git-and-other-scms/sections/client-svn.asc[] @@ -27,12 +28,15 @@ include::book/09-git-and-other-scms/sections/client-p4.asc[] include::book/09-git-and-other-scms/sections/client-tfs.asc[] [[_migrating]] -=== Migrating to Git +=== Migrating to Git (مهاجرت به گیت) (((Migrating to Git))) -If you have an existing codebase in another VCS but you've decided to start using Git, you must migrate your project one way or another. -This section goes over some importers for common systems, and then demonstrates how to develop your own custom importer. -You'll learn how to import data from several of the bigger professionally used SCM systems, because they make up the majority of users who are switching, and because high-quality tools for them are easy to come by. +اگر شما یک کدبیس موجود در یک VCS دیگر دارید اما تصمیم به استفاده از گیت گرفته‌اید، باید پروژه خود را به هر نحوی + مهاجرت کنید. + این بخش به بررسی برخی از واردکننده‌ها برای سیستم‌های رایج می‌پردازد و سپس نشان می‌دهد که چگونه می‌توانید یک + واردکننده سفارشی خود را توسعه دهید. + شما یاد خواهید گرفت که چگونه داده‌ها را از چندین سیستم SCM حرفه‌ای بزرگ وارد کنید، زیرا آن‌ها بخش عمده‌ای از + کاربرانی هستند که در حال تغییر هستند و ابزارهای با کیفیت برای آن‌ها به راحتی در دسترس است. include::book/09-git-and-other-scms/sections/import-svn.asc[] @@ -46,7 +50,7 @@ include::book/09-git-and-other-scms/sections/import-tfs.asc[] include::book/09-git-and-other-scms/sections/import-custom.asc[] -=== Summary +=== Summary (خلاصه) -You should feel comfortable using Git as a client for other version-control systems, or importing nearly any existing repository into Git without losing data. -In the next chapter, we'll cover the raw internals of Git so you can craft every single byte, if need be. +شما اکنون باید احساس راحتی داشته باشید که از Git به عنوان کلاینت برای سایر سیستم‌های کنترل نسخه استفاده کنید، یا تقریباً هر مخزن موجودی را بدون از دست دادن داده‌ها به Git وارد کنید. +در فصل بعد، به بررسی ساختار داخلی و خام Git خواهیم پرداخت تا در صورت نیاز، بتوانید حتی کوچک‌ترین جزئیات آن را به دلخواه خود بسازید و کنترل کنید. \ No newline at end of file