'\" t .\" Title: git-filter-repo .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 2024-11-27 .\" Manual: Git Manual .\" Source: Git 2.47.1.2.g787e9d71ae7.dirty .\" Language: Persian .\" .TH "GIT\-FILTER\-REPO" "1" "2024\-11\-27" "Git 2\&.47\&.1\&.2\&.g787e9d71" "Git Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "نام (NAME)" git-filter-repo \- بازنویسی همه‌کاره تاریخچه گیت .SH "خلاصه دستور (SYNOPSIS)" .sp .nf \fIgit filter\-repo\fR \-\-analyze \fIgit filter\-repo\fR [] [] [] [] [] [] [] [] .fi .sp .SH "توضیحات (DESCRIPTION)" .sp بازنویسی سریع کل تاریخچه مخزن با استفاده از فیلترهای مشخص‌شده توسط کاربر\&. این یک عملیات مخرب است که نباید ساده انگاشته شود؛ این دستور کامیت‌ها، درخت‌ها، تگ‌ها و blobهای جدید متناظر با اشیای اصلی مخزن (اما فیلترشده از آن‌ها) را می‌نویسد، سپس تاریخچه اصلی را حذف کرده و فقط تاریخچه جدید را باقی می‌گذارد\&. برای جزئیات بیشتر درباره پیامدهای استفاده از این ابزار، به بخش \(lqDISCUSSION\(rq مراجعه کنید\&. انواع مختلفی از بازنویسی تاریخچه امکان‌پذیر است؛ نمونه‌ها شامل (اما نه محدود به) موارد زیر هستند: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} حذف فایل‌های بزرگ (یا دایرکتوری‌های بزرگ یا پسوندهای بزرگ) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} حذف فایل‌های ناخواسته بر اساس مسیر .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} استخراج مسیرهای موردنظر و تاریخچه آن‌ها (و حذف هر چیز دیگر) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} تغییر ساختار چیدمان فایل‌ها (مانند انتقال تمام فایل‌ها به یک زیردایرکتوری برای آماده‌سازی ادغام با مخزنی دیگر، تبدیل یک زیردایرکتوری به دایرکتوری سطح بالای جدید، یا ادغام دو دایرکتوری با نام‌فایل‌های مستقل در یک دایرکتوری) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} تغییر نام تگ‌ها (همچنین اغلب برای آماده‌سازی جهت ادغام با مخزنی دیگر) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} جایگزینی یا حذف متن‌های حساس مانند گذرواژه‌ها .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} دائمی‌سازی بازنویسی نام‌های کاربری یا ایمیل‌ها توسط mailmap .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} دائمی‌سازی پیوندها (grafts) یا ارجاعات جایگزین (replacement refs) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} بازنویسی پیام‌های کامیت .RE .sp علاوه بر این، چندین مورد به طور خودکار مدیریت می‌شوند (بسیاری از این موارد را می‌توان لغو کرد، اما همگی به طور پیش‌فرض فعال هستند): .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} بازنویسی هش‌های (احتمالاً مخفف‌شده) در پیام‌های کامیت جهت ارجاع به هش کامیت‌های جدیدِ پس از بازنویسی .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} هرس کردن (pruning) کامیت‌هایی که به دلیل فیلترهای فوق خالی می‌شوند (همچنین حالت‌های مرزی مانند هرس کامیت‌های ادغامی که بی‌اثر و خالی شده‌اند را مدیریت می‌کند) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} بازنویسی نگه‌داشته‌ها (stashes) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} تثبیت تغییرات اعمال‌شده توسط ارجاعات refs/replace/ در تاریخچه دائمی و حذف ارجاعات جایگزین (replace refs) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} حذف تاریخچه اصلی برای جلوگیری از ترکیب تاریخچه قدیم و جدید .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} بسته‌بندی مجدد (repacking) مخزن پس از بازنویسی جهت کاهش حجم مخزن برای کاربر .RE .sp و امکانات اضافی دیگری از طریق یک گزینه پیکربندی در دسترس هستند: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} ایجاد replace\-refs (ببینید \fBgit-replace\fR(1)) برای هش‌های کامیت قدیمی، که در صورت push و fetch دستی به کاربران امکان می‌دهد با استفاده از شناسه‌های کامیت قدیمی (کامل و نامخفف)، همچنان به کامیت‌های جدید ارجاع دهند .RE .sp همچنین، شایان ذکر است که یک سازوکار ایمنی مهم وجود دارد: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} لغو عملیات در صورت اجرا در مخزنی که کلون تازه نیست (برای جلوگیری از دست رفتن تصادفی داده‌ها ناشی از بازنویسی تاریخچه محلی که در هیچ جای دیگری وجود ندارد)\&. به بخش \(lqFRESH CLONE SAFETY CHECK AND \-\-FORCE\(rq مراجعه کنید\&. .RE .sp برای کسانی که می‌دانند موارد ناخواسته و حجیمی در تاریخچه‌شان وجود دارد و برای یافتن آن‌ها کمک می‌خواهند، این دستور همچنین .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} گزینه‌ای را برای تحلیل یک مخزن و تولید گزارش‌هایی فراهم می‌کند که می‌توانند در تعیین موارد موردنیاز برای فیلتر کردن (یا در تشخیص موفقیت‌آمیز بودن یک دستور فیلترسازی جداگانه) مفید باشند\&. .RE .sp همچنین ببینید بخش‌های \(lqVERSATILITY\(rq، \(lqDISCUSSION\(rq، \(lqEXAMPLES\(rq و \(lqINTERNALS\(rq را\&. .SH "گزینه‌ها (OPTIONS)" .SS "گزینه‌های تحلیل (Analysis Options)" .PP \-\-analyze .RS 4 تحلیل تاریخچه مخزن و ایجاد گزارشی که ممکن است در تعیین موارد فیلتر در اجرای بعدی مفید باشد (یا در تشخیص اینکه آیا دستور فیلترسازی قبلی خواسته شما را برآورده کرده است یا خیر)\&. مخزن شما را تغییر نخواهد داد\&. .RE .SS "فیلتر کردن بر اساس مسیرها (همچنین \-\-filename\-callback را ببینید)" .sp این گزینه‌ها مسیرهای انتخابی را مشخص می‌کنند\&. توجه داشته باشید که همانند خود git، تغییر نام‌ها دنبال نمی‌شوند بنابراین ممکن است لازم باشد چندین مسیر را مشخص کنید، به عنوان مثال \fB\-\-path olddir/ \-\-path newdir/\fR .PP \-\-invert\-paths .RS 4 معکوس کردن انتخاب فایل‌ها از گزینه‌های \-\-path\-{match,glob,regex} مشخص‌شده در زیر، یعنی فقط انتخاب فایل‌هایی که با هیچ‌یک از آن گزینه‌ها مطابقت ندارند\&. .RE .PP \-\-path\-match , \-\-path .RS 4 مسیرهای دقیق (فایل‌ها یا دایرکتوری‌ها) برای گنجاندن در تاریخچه فیلترشده\&. برای دریافت اجتماع مسیرها می‌توان چندین گزینه \-\-path مشخص کرد\&. .RE .PP \-\-path\-glob .RS 4 الگوی glob مسیرها برای گنجاندن در تاریخچه فیلترشده\&. برای دریافت اجتماع مسیرها می‌توان چندین گزینه \-\-path\-glob مشخص کرد\&. .RE .PP \-\-path\-regex .RS 4 عبارت باقاعده (Regex) مسیرها برای گنجاندن در تاریخچه فیلترشده\&. برای دریافت اجتماع مسیرها می‌توان چندین گزینه \-\-path\-regex مشخص کرد\&. .RE .PP \-\-use\-base\-name .RS 4 تطبیق بر اساس نام پایه فایل (base name) به جای مسیر کامل از ریشه مخزن\&. با \-\-path\-rename و همچنین تطبیق در برابر نام‌های دایرکتوری ناسازگار است\&. .RE .SS "تغییر نام بر اساس مسیرها (همچنین \-\-filename\-callback را ببینید)" .sp نکته: اگر فیلتر کردن مسیر را با تغییر نام مسیر ترکیب کنید، توجه داشته باشید که دستور تغییر نام، مسیرها را انتخاب نمی‌کند، بلکه تنها چگونگی تغییر نام مسیرهایی را که با فیلترها انتخاب شده‌اند مشخص می‌کند\&. .PP \-\-path\-rename , \-\-path\-rename\-match .RS 4 مسیر برای تغییر نام؛ اگر نام فایل یا دایرکتوری با مطابقت داشته باشد، به تغییر نام می‌یابد\&. چندین گزینه \-\-path\-rename را می‌توان مشخص کرد\&. .RE .SS "میانبرهای مسیر (Path shortcuts)" .PP \-\-paths\-from\-file .RS 4 مشخص کردن چندین دستورالعمل فیلتر و تغییر نام مسیر، هر کدام در یک خط\&. خطوط دارای \fB==>\fR تغییر نام مسیرها را مشخص می‌کنند، و خطوط می‌توانند با \fBliteral:\fR (پیش‌فرض)، \fBglob:\fR، یا \fBregex:\fR شروع شوند تا شیوه‌های مختلف تطبیق را مشخص نمایند\&. خطوط خالی و خطوطی که با \fB#\fR شروع می‌شوند نادیده گرفته خواهند شد (اگر نام فایلی دارید که می‌خواهید آن را فیلتر کنید و با \fBliteral:\fR، \fB#\fR، \fBglob:\fR، یا \fBregex:\fR شروع می‌شود، پیشوند \fIliteral:\fR را به ابتدای خط اضافه کنید)\&. .RE .PP \-\-subdirectory\-filter .RS 4 تنها بررسی تاریخچه‌ای که زیردایرکتوری داده‌شده را لمس می‌کند و در نظر گرفتن آن دایرکتوری به عنوان ریشه پروژه\&. معادل استفاده از \fB\-\-path / \-\-path\-rename /:\fR .RE .PP \-\-to\-subdirectory\-filter .RS 4 در نظر گرفتن ریشه پروژه به گونه‌ای که گویی زیر قرار دارد\&. معادل استفاده از \fB\-\-path\-rename :/\fR .RE .SS "فیلترهای ویرایش محتوا (همچنین \-\-blob\-callback را ببینید)" .PP \-\-replace\-text .RS 4 فایلی حاوی عباراتی که در صورت یافت شدن، جایگزین خواهند شد\&. به طور پیش‌فرض، هر عبارت به عنوان متن صریح (literal) در نظر گرفته می‌شود، اما پیشوندهای \fBregex:\fR و \fBglob:\fR پشتیبانی می‌شوند\&. می‌توانید انتهای خط را با \fB==>\fR و متنی برای جایگزینی به پایان برسانید تا انتخابی به جز مقدار پیش‌فرض \fB***REMOVED***\fR برای جایگزینی تعیین کنید\&. .RE .PP \-\-strip\-blobs\-bigger\-than .RS 4 حذف blobها (فایل‌ها) بزرگتر از اندازه مشخص‌شده (مانند \fB5M\fR، \fB2G\fR و غیره) .RE .PP \-\-strip\-blobs\-with\-ids .RS 4 خواندن شناسه‌های شیء گیت (object id) از هر خط فایل داده‌شده، و حذف همه آن‌ها از تاریخچه .RE .SS "تغییر نام ارجاعات (همچنین \-\-refname\-callback را ببینید)" .PP \-\-tag\-rename .RS 4 تغییر نام تگ‌هایی که با شروع می‌شوند به گونه‌ای که با شروع شوند\&. به عنوان مثال، \-\-tag\-rename foo:bar تگ foo\-1\&.2\&.3 را به bar\-1\&.2\&.3 تغییر نام می‌دهد؛ هر یک از یا می‌تواند خالی باشد\&. .RE .SS "فیلتر کردن پیام‌های کامیت (همچنین \-\-message\-callback را ببینید)" .PP \-\-replace\-message .RS 4 فایلی با عباراتی که در صورت یافت شدن در پیام‌های کامیت یا تگ، جایگزین خواهند شد\&. این فایل از ساختار دستوری مشابه \-\-replace\-text استفاده می‌کند\&. .RE .PP \-\-preserve\-commit\-hashes .RS 4 به طور پیش‌فرض، از آنجا که کامیت‌ها بازنویسی شده و بنابراین هش‌های جدیدی دریافت می‌کنند، ارجاعات به هش کامیت‌های قدیمی در پیام‌های کامیت با هش کامیت‌های جدید (مخفف‌شده به همان طول ارجاع قدیمی) جایگزین می‌شوند\&. از این فلگ برای غیرفعال کردن به‌روزرسانی هش کامیت‌ها در پیام‌های کامیت استفاده کنید\&. .RE .PP \-\-preserve\-commit\-encoding .RS 4 عدم رمزگذاری مجدد پیام‌های کامیت به UTF\-8\&. به طور پیش‌فرض، اگر شیء کامیت یک کدگذاری برای پیام کامیت مشخص کرده باشد، پیام مجدداً به UTF\-8 کدگذاری می‌شود\&. .RE .SS "فیلتر کردن نام‌ها و ایمیل‌ها (همچنین \-\-name\-callback و \-\-email\-callback را ببینید)" .PP \-\-mailmap .RS 4 استفاده از فایل mailmap مشخص‌شده (برای جزئیات قالب به \fBgit-shortlog\fR(1) مراجعه کنید) هنگام بازنویسی نام‌ها و ایمیل‌های نویسنده (author)، ثبت‌کننده (committer) و تگ‌کننده (tagger)\&. اگر فایل مشخص‌شده بخشی از تاریخچه گیت باشد، نسخه‌های تاریخی فایل نادیده گرفته می‌شوند؛ تنها به محتوای فعلی رجوع می‌شود\&. .RE .PP \-\-use\-mailmap .RS 4 مشابه با: \fI\-\-mailmap \&.mailmap\fR .RE .SS "بازنویسی والدین (Parent rewriting)" .PP \-\-replace\-refs {delete\-no\-add, delete\-and\-add, update\-no\-add, update\-or\-add, update\-and\-add, old\-default} .RS 4 نحوه مدیریت ارجاعات جایگزین (replace refs، مراجعه کنید به git\-replace(1))\&. ارجاعات جایگزین را می‌توان در حین بازنویسی تاریخچه اضافه کرد تا به کاربران اجازه دهد شناسه‌های کامیت قدیمی (از قبل از اجرای git\-filter\-repo) را به دستورات گیت بدهند و گیت بداند چگونه آن شناسه‌های کامیت قدیمی را به شناسه‌های کامیت جدید (پس از بازنویسی) ترجمه کند\&. همچنین، ارجاعات جایگزینی که قبل از بازنویسی وجود داشته‌اند را می‌توان حذف یا به‌روزرسانی کرد\&. بنابراین گزینه‌های ارائه‌شده به \-\-replace\-refs باید هم تعیین‌کننده نحوه برخورد با ارجاعات موجود باشند و هم بازنویسی کامیت‌ها\&. بر این اساس \fIupdate\-and\-add\fR به معنی به‌روزرسانی ارجاعات جایگزین موجود است، و برای هر بازنویسی کامیت (حتی اگر از قبل توسط یک ارجاع جایگزین به آن اشاره شده باشد) یک ارجاع جدید refs/replace/ جهت نگاشت از شناسه کامیت قدیمی به شناسه کامیت جدید اضافه می‌کند\&. حالت پیش‌فرض update\-no\-add است، یعنی ارجاعات جایگزین موجود را به‌روزرسانی کن اما هیچ ارجاع جدیدی اضافه نکن\&. همچنین یک گزینه ویژه \fIold\-default\fR برای انتخاب حالت پیش‌فرضی که در نسخه‌های قبل از git\-filter\-repo\-2\&.45 استفاده می‌شد وجود دارد، یعنی \fIupdate\-and\-add\fR در اولین اجرای git\-filter\-repo در یک مخزن و \fIupdate\-or\-add\fR در صورت اجرای مجدد git\-filter\-repo روی یک مخزن\&. .RE .PP \-\-prune\-empty {always, auto, never} .RS 4 تعیین هرس کردن کامیت‌های خالی\&. \fIauto\fR (پیش‌فرض) به معنای هرس کردن تنها کامیت‌هایی است که خالی می‌شوند (نه کامیت‌هایی که در مخزن اصلی خالی بودند، مگر اینکه والد آن‌ها هرس شده باشد)\&. هنگامی که والد یک کامیت هرس می‌شود، اولین جد هرس‌نشده به والد جدید تبدیل می‌گردد\&. .RE .PP \-\-prune\-degenerate {always, auto, never} .RS 4 از آنجا که کامیت‌های ادغام برای توپولوژی تاریخچه ضروری هستند، معمولاً از هرس معاف می‌شوند\&. با این حال، آن‌ها با هرس شدن کامیت‌های دیگر می‌توانند بی‌اثر (degenerate) شوند (داشتن کمتر از دو والد، استفاده از یک کامیت به عنوان هر دو والد، یا بودن یک والد به عنوان جد والد دیگر)\&. اگر چنین کامیت‌های ادغامی تغییر فایلی نداشته باشند، می‌توان آن‌ها را هرس کرد\&. پیش‌فرض (\fIauto\fR) تنها هرس کردن کامیت‌های ادغام خالی است که بی‌اثر شده‌اند (نه آن‌هایی که از ابتدا به این صورت بوده‌اند)\&. .RE .PP \-\-no\-ff .RS 4 حتی اگر والد اول جدِ والد دیگری باشد یا بشود، آن را هرس نکن\&. این گزینه رفتار \-\-prune\-degenerate را تغییر می‌دهد و ممکن است در پروژه‌هایی که همیشه از merge \-\-no\-ff استفاده می‌کنند مفید باشد\&. .RE .SS "قطعه‌کدهای عمومی بازخوانی (Generic callback code snippets)" .PP \-\-filename\-callback .RS 4 بدنه کد پایتون برای پردازش نام فایل‌ها؛ مراجعه کنید به بخش \(lqCALLBACKS\(rq\&. .RE .PP \-\-message\-callback .RS 4 بدنه کد پایتون برای پردازش پیام‌ها (هم پیام‌های کامیت و هم پیام‌های تگ)؛ مراجعه کنید به بخش \(lqCALLBACKS\(rq\&. .RE .PP \-\-name\-callback .RS 4 بدنه کد پایتون برای پردازش نام افراد؛ مراجعه کنید به بخش \(lqCALLBACKS\(rq\&. .RE .PP \-\-email\-callback .RS 4 بدنه کد پایتون برای پردازش آدرس‌های ایمیل؛ مراجعه کنید به بخش \(lqCALLBACKS\(rq\&. .RE .PP \-\-refname\-callback .RS 4 بدنه کد پایتون برای پردازش نام ارجاعات (refnames)؛ مراجعه کنید به بخش \(lqCALLBACKS\(rq\&. .RE .PP \-\-file\-info\-callback .RS 4 بدنه کد پایتون برای پردازش ترکیب نام فایل، حالت (mode) و محتویات فایل مربوطه؛ ببینید <\&. توجه داشته باشید هنگامی که \-\-file\-info\-callback مشخص شده است، هرگونه جایگزینی مشخص‌شده توسط \-\-replace\-text به طور خودکار اعمال نخواهد شد؛ در عوض، شما در داخل \-\-file\-info\-callback این کنترل را دارید که انتخاب کنید این تبدیل‌ها روی کدام فایل‌ها اعمال شوند\&. .RE .PP \-\-blob\-callback .RS 4 بدنه کد پایتون برای پردازش اشیاء blob؛ مراجعه کنید به بخش \(lqCALLBACKS\(rq\&. .RE .PP \-\-commit\-callback .RS 4 بدنه کد پایتون برای پردازش اشیاء کامیت؛ مراجعه کنید به بخش \(lqCALLBACKS\(rq\&. .RE .PP \-\-tag\-callback .RS 4 بدنه کد پایتون برای پردازش اشیاء تگ؛ مراجعه کنید به بخش \(lqCALLBACKS\(rq\&. توجه داشته باشید که تگ‌های سبک‌وزن (lightweight tags) هیچ شیء تگی ندارند و بنابراین توسط این بازخوانی پردازش نمی‌شوند\&. تنها کاری که واقعاً می‌توانید با یک تگ سبک‌وزن انجام دهید تغییر نام آن است، اما برای این کار باید در عوض \-\-refname\-callback را ببینید\&. .RE .PP \-\-reset\-callback .RS 4 بدنه کد پایتون برای پردازش اشیاء reset؛ مراجعه کنید به بخش \(lqCALLBACKS\(rq\&. .RE .SS "حذف داده‌های حساس (Sensitive Data Removal)" .PP \-\-sensitive\-data\-removal, \-\-sdr .RS 4 هدف این بازنویسی، حذف داده‌های حساس از یک مخزن است\&. اطلاعات اضافی موردنیاز از بازنویسی جمع‌آوری می‌شود تا دستورالعمل‌های تکمیلی در مورد نحوه پاک‌سازی سایر نسخه‌ها ارائه گردد\&. این موارد عبارتند از: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} دریافت (fetch) تمام ارجاعات، به طوری که اگر ارجاعات خارج از شاخه‌ها و تگ‌ها نیز به داده‌های حساس ارجاع دارند، آن‌ها هم پاک‌سازی شوند .sp .if n \{\ .RS 4 .\} .nf توجه داشته باشید که اگر هرگونه تغییر صرفاً محلی (یعنی تغییرات push‌نشده) در مخزن خود بر روی هر شاخه یا ارجاعی دارید، این مرحله دریافت ممکن است آن‌ها را دور بریزد\&. کار کردن در یک کلون تازه از این مشکل جلوگیری می‌کند؛ همچنین اگر نمی‌خواهید با یک کلون تازه کار کنید و تغییرات مهم صرفاً محلی دارید، گزینه \-\-no\-fetch را ببینید\&. .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} ردیابی و گزارش‌دهی در مورد اولین کامیت(های) تغییریافته .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} ردیابی و گزارش‌دهی در این مورد که آیا شیء LFS در اثر بازنویسی یتیم (بی‌استفاده) شده است یا خیر، تا بتوان آن را حذف کرد .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} ارائه دستورالعمل‌های تکمیلی در پایان پیرامون نحوه پاک‌سازی مخزنی که از آن کلون گرفته‌اید، و سایر کلون‌های مخزن .RE .RE .PP \-\-no\-fetch .RS 4 اجتناب از مرحله "دریافت تمام ارجاعات" با \-\-sensitive\-data\-removal، و در نتیجه جلوگیری از رونویسی تغییرات صرفاً محلی در مخزن، اما با ریسک باقی ماندن داده‌های حساس در سایر ارجاعات مخزن مبدأ\&. این گزینه توسط \-\-partial یا هر فلگی که متضمن \-\-partial باشد فعال می‌شود\&. .RE .SS "مکان فیلترسازی از/به (Location to filter from/to)" .if n \{\ .sp .\} .RS 4 .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBنکته\fR .ps -1 .br .sp مشخص کردن مکان‌های مبدأ یا مقصد جایگزین، متضمن \-\-partial است\&. با این حال، بر خلاف کاربردهای عادی \-\-partial، این کار خطر ترکیب تاریخچه قدیم و جدید را به همراه ندارد زیرا تاریخچه‌های قدیم و جدید در مخازن متفاوتی قرار دارند\&. .sp .5v .RE .PP \-\-source .RS 4 مخزن گیت برای خواندن از آن .RE .PP \-\-target .RS 4 مخزن گیت برای بازنویسی با تاریخچه فیلترشده .RE .SS "گزینه‌های متفرقه (Miscellaneous options)" .PP \-\-help, \-h .RS 4 نمایش پیام راهنما و خروج\&. .RE .PP \-\-force, \-f .RS 4 نادیده گرفتن بررسی‌های کلون تازه و بازنویسی تاریخچه (عملیاتی غیرقابل بازگشت، به ویژه از آنجا که به طور پیش‌فرض با هرس فوری reflogها و اشیاء قدیمی به پایان می‌رسد)\&. مراجعه کنید به بخش \(lqFRESH CLONE SAFETY CHECK AND \-\-FORCE\(rq\&. توجه داشته باشید هنگام کلون کردن مخازن روی فایل‌سیستم محلی، بهتر است \fB\-\-no\-local\fR را به git clone بدهید تا اینکه \fB\-\-force\fR را به git\-filter\-repo پاس دهید\&. .RE .PP \-\-partial .RS 4 انجام بازنویسی جزئی تاریخچه، که منجر به ترکیب تاریخچه قدیم و جدید می‌شود\&. این گزینه بازنویسی refs/remotes/origin/* به refs/heads/* را غیرفعال می‌کند، حذف ریموت \fIorigin\fR را غیرفعال می‌کند، حذف ارجاعات صادرنشده (unexported) را غیرفعال می‌کند، منقضی شدن reflog را غیرفعال کرده و gc خودکار پس از فیلتر را نیز غیرفعال می‌سازد\&. همچنین، این گزینه رفتارهای \-\-tag\-rename و \-\-refname\-callback را به گونه‌ای تغییر می‌دهد که به جای جایگزینی ارجاعات قدیمی با نام‌های ارجاع جدید، ارجاعات جدید را ایجاد کرده و موارد قدیمی را حفظ می‌کند\&. با احتیاط استفاده شود\&. .RE .PP \-\-refs .RS 4 محدود کردن بازنویسی تاریخچه به ارجاعات مشخص‌شده\&. متضمن \-\-partial است\&. علاوه بر هشدارهای معمول \-\-partial (ترکیب تاریخچه قدیم و جدید، عدم نگاشت خودکار refs/remotes/origin/* به refs/heads/* و غیره)، این کار ممکن است در صورت مشخص شدن نسخه‌های منفی (negative revisions)، برای هرس کامیت‌های ادغام خالی و بی‌اثر نیز مشکلاتی ایجاد کند\&. .RE .PP \-\-dry\-run .RS 4 عدم ایجاد تغییر در مخزن\&. اجرای \fBgit fast\-export\fR و فیلتر کردن خروجی آن، و ذخیره هر دو نسخه اصلی و فیلترشده برای مقایسه\&. این گزینه همچنین بازنویسی پیام‌های کامیت را به دلیل ندانستن شناسه‌های کامیت جدید، و فیلتر کردن برخی کامیت‌های خالی را به دلیل عدم امکان استعلام از بک‌اند fast\-import غیرفعال می‌کند\&. .RE .PP \-\-debug .RS 4 چاپ اطلاعات بیشتر درباره عملیات در حال انجام و دستورات در حال اجرا\&. (اگر همراه با \-\-dry\-run استفاده شود، اطلاعات بیشتری درباره آنچه قرار است اجرا شود نمایش می‌دهد)\&. .RE .PP \-\-stdin .RS 4 به جای اجرای \fBgit fast\-export\fR و فیلتر کردن خروجی آن، جریان fast\-export را از ورودی استاندارد (stdin) فیلتر می‌کند\&. ورودی استاندارد باید در قالب ورودی مورد انتظار باشد (مثلاً باید شامل دستورالعمل‌های original\-oid باشد)\&. .RE .PP \-\-quiet .RS 4 ارسال \-\-quiet به سایر دستورات گیت که فراخوانی می‌شوند\&. .RE .SH "خروجی (OUTPUT)" .sp هر بار که filter\-repo اجرا می‌شود، فایل‌هایی در دایرکتوری \fB\&.git/filter\-repo/\fR ایجاد می‌شوند\&. این فایل‌ها با هر بار اجرا به‌روزرسانی یا رونویسی (overwrite) می‌شوند\&. .SS "نگاشت کامیت (Commit map)" .sp فایل \fB$GIT_DIR/filter\-repo/commit\-map\fR حاوی نگاشتی از نحوه تغییر یافتن (یا عدم تغییر) تمامی کامیت‌ها است\&. .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} یک سرآیند (header) خط اول با متن "old" و "new" است\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} نگاشت‌های کامیت ترتیب خاصی ندارند\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} تمامی کامیت‌ها در محدوده بازنویسی فهرست خواهند شد، حتی کامیت‌هایی که بدون تغییر مانده‌اند (به‌عنوان مثال، به این دلیل که زمان ایجاد کامیت قبل از زمانی بوده که فایل‌های حذف‌شده توسط عملیات فیلترسازی به مخزن اضافه شده‌اند)\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} یک هش تمام‌صفر، یا SHA پوچ (null SHA)، نمایانگر یک شیء ناموجود است\&. هنگامی که در ستون "new" قرار گیرد، به این معنی است که کامیت به‌طور کامل حذف شده است\&. .RE .SS "نگاشت ارجاعات (Reference map)" .sp فایل \fB$GIT_DIR/filter\-repo/ref\-map\fR حاوی نگاشتی از ارجاعات محلی تغییریافته (یا تغییرنیافته) است\&. .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} یک سرآیند خط اول با متن "old"، "new" و "ref" است\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} نگاشت‌های ارجاع بر اساس ref مرتب شده‌اند\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} یک هش تمام‌صفر، یا SHA پوچ، نمایانگر یک شیء ناموجود است\&. هنگامی که در ستون "new" قرار گیرد، به این معنی است که ارجاع به‌طور کامل حذف شده است\&. .RE .SS "ارجاعات تغییریافته (Changed References)" .sp فایل \fB$GIT_DIR/filter\-repo/changed\-refs\fR حاوی فهرستی از refهایی است که تغییر یافته‌اند\&. .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} هیچ سرآیندی ارائه نشده است\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} زیرمجموعه‌ای از refها را از ref\-map فهرست می‌کند که در آن‌ها old != new است\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اگرچه از آنجا که این فایل هیچ اطلاعات جدیدی نسبت به ref\-map ارائه نمی‌دهد غیرضروری است، اما تعیین سریع refهایی را که بر اثر بازنویسی تغییر یافته‌اند آسان‌تر می‌کند\&. .RE .SS "اولین کامیت‌های تغییریافته (First Changed Commits)" .sp فایل \fB$GIT_DIR/filter\-repo/first\-changed\-commits\fR حاوی فهرستی از اولین کامیت(هایی) است که توسط عملیات فیلترسازی تغییر یافته‌اند\&. این‌ها کامیت‌هایی هستند که بازنویسی شده‌اند و هیچ والدینی نداشتند که آن‌ها نیز بازنویسی شده باشند\&. .sp بنابراین، برای مثال اگر پیش از اجرای git\-filter\-repo کامیت‌های A1\-B1\-C1\-D1\-E1 را داشتید، و پس از آن کامیت‌های A1\-B2\-C2\-D2\-E2 را داشتید، فایل First Changed Commits فقط شامل یک خط خواهد بود، که هش B2 است\&. .sp در بیشتر موارد، تنها یک کامیت فهرست خواهد شد، اما اگر چندین کامیت ریشه یا یک تاریخچه غیرخطی داشته باشید که در آن کامیت‌های روی آن تاریخچه‌های واگرا اولین موارد اصلاح‌شده باشند، ممکن است چندین کامیت اولیه تغییریافته وجود داشته باشد و هر یک در خطوط جداگانه فهرست خواهند شد\&. .SS "قبلاً اجرا شده (Already Ran)" .sp فایل \fB$GIT_DIR/filter\-repo/already_ran\fR فایلی است که ثبت می‌کند git\-filter\-repo اجرا شده است\&. هنگامی که این فایل وجود داشته باشد، اجراهای بعدی به عنوان ادامه‌ای از عملیات فیلترسازی قبلی در نظر گرفته می‌شوند\&. .sp به‌طور ملموس، این به این معناست: * بررسی "کلون تازه" (Fresh Clone) دور زده می‌شود .sp .if n \{\ .RS 4 .\} .nf این کار به این دلیل انجام می‌شود که اجراهای قبلی باعث می‌شوند مخزن دیگر شبیه به یک کلون تازه به نظر نرسد، و بنابراین در بررسی کلون تازه رد شود، اما انجام فیلترسازی از طریق چندین بار فراخوانی git\-filter\-repo یک کاربرد موردنظر و پشتیبانی‌شده است\&. شما قبلاً در اجرای اولیه خود، بررسی "کلون تازه" را گذرانده یا دور زده‌اید\&. .fi .if n \{\ .RE .\} .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} فایل‌های commit\-map و ref\-map فوق به جای اینکه صرفاً دوباره نوشته شوند، به‌روزرسانی خواهند شد\&. .sp .if n \{\ .RS 4 .\} .nf به عبارت دیگر، اگر اولین فراخوانی filter\-repo کامیت A را به کامیت B بازنویسی کرده باشد، و دومین فراخوانی filter\-repo کامیت B را به کامیت C بازنویسی کند، دومین اجرا به جای ورودی "B C"، یک ورودی "A C" برای کامیت تغییریافته خواهد داشت\&. .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اولین کامیت(های) تغییریافته (که هنگام استفاده از گزینه \-\-sensitive\-data\-removal گزارش می‌شود) اولین کامیت اصلی اصلاح‌شده خواهد بود، نه اولین کامیت میانی اصلاح‌شده\&. .sp .if n \{\ .RS 4 .\} .nf با جزئیات بیشتر، اگر مخزن در ابتدا دارای کامیت‌های زیر بود: A1\-B1\-C1\-D1\-E1 و اولین فراخوانی filter\-repo این را تغییر داد به A1\-B1\-C2\-D2\-E2 آنگاه اولین اجرا "C1" را به عنوان اولین کامیت تغییریافته گزارش می‌کرد\&. اگر دومین اجرای filter\-repo این را بیشتر تغییر دهد به A1\-B1\-C2\-D3\-E3 آنگاه "C1" را به عنوان اولین کامیت تغییریافته گزارش خواهد داد، نه "D2"، زیرا با کامیت‌های اصلی مقایسه می‌کند نه با کامیت‌های میانی\&. .fi .if n \{\ .RE .\} .RE .sp با این حال، اگر فایل already_ran وجود داشته باشد اما هنگام فراخوانی git\-filter\-repo بیش از ۱ روز از عمر آن گذشته باشد، از کاربر پرسیده می‌شود که آیا اجرای جدید باید ادامه‌ای از اجرای قبلی در نظر گرفته شود یا خیر\&. اگر آن‌ها پاسخ مثبت ندهند، سه مورد فوق اعمال نخواهند شد\&. این اعلان به این دلیل وجود دارد که کاربران ممکن است یک بازنویسی تاریخچه در یک مخزن انجام دهند، آن را فراموش کنند و دایرکتوری $GIT_DIR/filter\-repo را رها نمایند، و سپس چند ماه یا چند سال بعد نیاز به انجام بازنویسی دیگری داشته باشند\&. اگر کامیت‌های ناشی از بازنویسی قبلی عمومی شده و به اشتراک گذاشته شده باشند، اجرای بعدی filter\-repo نباید ادامه‌ای از اجرای فیلترسازی قبلی در نظر گرفته شود\&. .SS "اشیاء LFS اصلی (Original LFS Objects)" .sp هنگام اجرا با فلگ \-\-sensitive\-data\-removal، و در صورتی که LFS توسط مخزن در حال استفاده باشد، فایل \fB$GIT_DIR/filter\-repo/original_lfs_objects\fR شامل فهرستی از اشیاء LFS است که قبل از بازنویسی توسط مخزن به آن‌ها ارجاع داده شده است، به ترتیب مرتب‌شده\&. .SS "اشیاء LFS یتیم (Orphaned LFS Objects)" .sp هنگام اجرا با فلگ \-\-sensitive\-data\-removal، و در صورتی که LFS توسط مخزن در حال استفاده باشد، فایل \fB$GIT_DIR/filter\-repo/orphaned_lfs_objects\fR شامل فهرستی از اشیاء LFS است که قبلاً توسط مخزن مورد ارجاع بودند اما پس از اجرای git\-filter\-repo دیگر ارجاعی به آن‌ها وجود ندارد\&. اشیاء به ترتیب مرتب‌شده ظاهر می‌شوند\&. .SH "بررسی ایمنی کلون تازه و \-\-FORCE (FRESH CLONE SAFETY CHECK AND \-\-FORCE)" .sp از آنجا که filter\-repo بازنویسی بازگشت‌ناپذیر تاریخچه را انجام می‌دهد، جلوگیری از ایجاد تغییرات در مخزنی که کاربر نسخه پشتیبان مناسبی از آن ندارد بسیار مهم است\&. سازوکار دفاعی اولیه، صرفاً آموزش کاربران و اتکا به آن‌هاست که به خوبی از داده‌های خود مراقبت کنند؛ بنابراین هشدارهای متعددی در مستندات درباره چگونگی بازنویسی تاریخچه توسط filter repo وجود دارد\&. .sp با این حال، به عنوان خدمتی به کاربران، می‌خواهیم یک بررسی ایمنی اضافی فراتر از مستندات ارائه دهیم\&. راه مناسبی برای بررسی اینکه آیا کاربر نسخه پشتیبان خوبی دارد یا نه وجود ندارد، اما می‌توانیم یک پرسش مرتبط مطرح کنیم که یک تقریب ناقص اما کاملاً منطقی است: "آیا این مخزن یک کلون تازه است؟" متأسفانه، این نیز سؤالی است که نمی‌توانیم پاسخی بی‌نقص برای آن دریافت کنیم؛ git هیچ راهی برای پاسخ به این پرسش فراهم نمی‌کند\&. با این حال، حدود ده مورد وجود دارد که متوجه شدم همواره در کلون‌های کاملاً جدید صادق به نظر می‌رسند (با این فرض که آن‌ها یا کلون‌هایی از مخازن ریموت هستند یا با فلگ \fB\-\-no\-local\fR ساخته شده‌اند)، و من همه آن‌ها را بررسی می‌کنم\&. .sp این بررسی‌ها می‌توانند هم مثبت کاذب و هم منفی کاذب داشته باشند\&. ممکن است فردی یک نسخه پشتیبان کاملاً مطمئن از مخزن خود داشته باشد بدون اینکه واقعاً یک کلون تازه باشد \(em اما راهی برای filter\-repo وجود ندارد که از این موضوع باخبر شود\&. برعکس، ممکن است فردی به تمام مواردی که filter\-repo در بررسی‌های ایمنی خود چک می‌کند نگاه کند و صرفاً مخزن بدون پشتیبان خود را طوری دستکاری نماید که آن شرایط را برآورده سازد (اگرچه این کار نیازمند تلاش قابل‌توجهی است، و از نظر آماری بسیار بعید است که مخزنی که یک کلون تازه نیست به‌طور تصادفی با تمامی این معیارها مطابقت داشته باشد)\&. در عمل، بررسی‌های ایمنی مورد استفاده filter\-repo در جلوگیری از اجرای تصادفی filter\-repo توسط افراد روی مخزنی که نباید آن را اجرا کنند، بسیار عالی عمل می‌کنند\&. این بررسی حتی یک‌بار جلوی خود من را گرفت، زمانی که واقعاً قصد اجرای filter\-repo را داشتم اما در دایرکتوری متفاوتی نسبت به آنچه تصور می‌کردم بودم\&. .sp به‌طور خلاصه، استفاده از \(oq\-\-force` برای نادیده گرفتن بررسی‌های ایمنی کاملاً مجاز است تا زمانی که با بازنویسی برگشت‌ناپذیر محتوای مخزن فعلی توسط filter\-repo مشکلی نداشته باشید\&. این ایده بسیار بدی است که همیشه به مشخص کردن \fB\-\-force\fR عادت کنید؛ اگر چنین کنید، روزی یکی از دستورات خود را مانند من در دایرکتوری اشتباهی اجرا خواهید کرد، و دیگر بررسی ایمنی نخواهید داشت تا به داد شما برسد\&. همچنین، قطعاً توصیه \fB\-\-force\fR در فروم‌ها، سایت‌های پرسش و پاسخ، یا در ایمیل‌ها به سایر کاربران بدون توضیح دقیق این موضوع که \fB\-\-force\fR به معنای به خطر انداختن داده‌های مخازن شماست، به‌هیچ‌وجه جایز نیست\&. من به‌ویژه از افرادی ناراحت می‌شوم که این فلگ را زمانی پیشنهاد می‌کنند که مشخصاً نیازی به آن نیست؛ آن‌ها بی‌دلیل داده‌های دیگران را به خطر می‌اندازند\&. .SH "انعطاف‌پذیری و کاربردها (VERSATILITY)" .sp ابزار filter\-repo دارای سلسله‌مراتبی از قابلیت‌ها در طیفی از فلگ‌های آسان و کاربردی که انواع از پیش تعریف‌شده فیلترسازی را انجام می‌دهند، تا گزینه‌هایی که انعطاف‌پذیری زیادی در کنترل نحوه انجام فیلترسازی فراهم می‌کنند است\&. این طیف شامل موارد زیر است: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} فلگ‌های کاربردی که انواع رایج بازنویسی تاریخچه را ساده می‌کنند (مانند \-\-path، \-\-strip\-blobs\-bigger\-than، \-\-replace\-text، \-\-mailmap) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} گزینه‌هایی که کوتاه‌شده گزینه‌های دیگر هستند یا کنترل بیشتری نسبت به دیگران ارائه می‌دهند (برای مثال \-\-subdirectory\-filter می‌تواند صرفاً با استفاده از هر دو فیلتر انتخاب مسیر (\-\-path) و تغییر نام مسیر (\-\-path\-rename) نوشته شود؛ \-\-paths\-from\-file می‌تواند تمامی گزینه‌های دیگر \-\-path* و حتی بیشتر از آن مانند تغییر نام مسیرها با عبارات باقاعده را مدیریت کند) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} کالبک‌های عمومی پایتون برای مدیریت نوع خاصی از داده‌ها (کالبک‌های filename، message، name، email، و refname) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} کالبک‌های عمومی پایتون برای مدیریت اشیاء بنیادی git، که امکان کنترل بیشتر بر ترکیب انواع داده‌هایی که شیء نگه می‌دارد را فراهم می‌کنند (کالبک‌های commit، tag، blob، و reset) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} توانایی ایمپورت کردن filter\-repo به عنوان یک ماژول در یک برنامه پایتون و استفاده از کلاس‌ها و توابع آن برای کنترل و انعطاف‌پذیری بیشتر ضمن بهره‌گیری از قابلیت‌های پایه‌ای فراوان\&. حتی می‌توان از این برای نوشتن ابزارهای جدید با یک رابط کاملاً متفاوت استفاده کرد\&. .RE .sp برای اطلاعات بیشتر درباره کالبک‌ها، به بخش موسوم به \(lqCALLBACKS\(rq مراجعه کنید\&. برای مثال‌هایی در مورد نوشتن برنامه‌های پایتون که filter\-repo را به عنوان یک ماژول ایمپورت می‌کنند تا ابزارهای جدید بازنویسی تاریخچه ایجاد نمایند، به دایرکتوری contrib/filter\-repo\-demos/ نگاه کنید\&. آن دایرکتوری در میان مثال‌های دیگر، شامل پیاده‌سازی مجدد git\-filter\-branch است که سریع‌تر از git\-filter\-branch کار می‌کند، و پیاده‌سازی مجدد BFG Repo Cleaner با چندین رفع باگ و قابلیت‌های جدید است\&. .SH "بحث و بررسی (DISCUSSION)" .sp استفاده از filter\-repo نسبتاً ساده است، اما بازنویسی تاریخچه بخشی از یک بحث بزرگ‌تر از نظر همکاری تیمی است\&. هنگامی که تاریخچه را بازنویسی می‌کنید، تاریخچه‌های قدیمی و جدید دیگر با یکدیگر سازگار نیستند؛ اگر این تاریخچه را به جایی پوش کنید تا دیگران ببینند، به نظر می‌رسد که گویی شما تمامی شاخه‌ها و تگ‌ها را ریبیس (rebase) کرده‌اید\&. علاوه بر این بخش، اطمینان حاصل کنید که پیش از ادامه، با بخش "RECOVERING FROM UPSTREAM REBASE" در \fBgit-rebase\fR(1) (و به‌ویژه "The hard case") آشنایی دارید\&. .sp مراحل استفاده از git\-filter\-repo به عنوان بخشی از تصویر بزرگ‌تر انجام بازنویسی تاریخچه تقریباً به شرح زیر است: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} یک کلون از مخزن خود ایجاد کنید\&. در صورت تمایل می‌توانید \fB\-\-bare\fR یا \fB\-\-mirror\fR را به \fBgit clone\fR ارسال کنید\&. اگر مخزنی که از آن کلون می‌گیرید روی فایل‌سیستم محلی قرار دارد، باید \fB\-\-no\-local\fR را ارسال نمایید\&. از سایر فلگ‌ها دوری کنید؛ برخی از آن‌ها ممکن است بررسی کلون تازه را دچار سردرگمی کنند، و برخی دیگر ممکن است باعث حذف بخش‌هایی از داده‌ها شوند که برای بازنویسی مورد نیاز است\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} (اختیاری) دستور \fBgit filter\-repo \-\-analyze\fR را اجرا کنید\&. این کار دایرکتوری‌ای از گزارش‌ها ایجاد می‌کند که به موارد متعددی اشاره دارد: (الف) مسیرهایی که در طول زمان در مخزن شما وجود داشته‌اند، (ب) تغییر نام‌هایی که در مخزن رخ داده است و (ج) اندازه اشیاء تجمیع‌شده بر اساس مسیر/دایرکتوری/پسوند/شناسه شیء حباب (blob\-id)\&. این اطلاعات ممکن است در انتخاب نحوه فیلترسازی مخزن شما مفید باشد\&. همچنین اجرای مجدد \-\-analyze پس از فیلترسازی برای تأیید اینکه تغییرات صحیح به نظر می‌رسند می‌تواند مفید باشد\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} پیش از بازنویسی تاریخچه نسخه محلی خود با git\-filter\-repo، مشخص کنید که پس از پایان کار، تاریخچه بازنویسی‌شده را به کجا پوش خواهید کرد\&. در حالت خاص که تلاش می‌کنید داده‌های حساس را از یک مخزن موجود حذف کنید، می‌خواهید آن را به همان جایی که از آن کلون کرده‌اید بازگردانید و پوش کنید، و همچنین تمامی کلون‌ها/نسخه‌های دیگر مخزن را پاک‌سازی نمایید\&. اگر قصد دارید به مخزنی که از آن کلون کرده‌اید پوش کنید، باید از گزینه \-\-sensitive\-data\-removal استفاده کنید و بخش "حذف داده‌های حساس" در زیر را مشاهده نمایید\&. در بیشتر مواردی که با حذف داده‌های حساس سروکار ندارند، ترجیح می‌دهید به یک مخزن جدید پوش کنید، زیرا: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} حتی پس از آنکه تاریخچه را بازنویسی کرده و به سرور بازگردانید، افراد دیگری که قبلاً از مخزن اصلی کلون کرده‌اند، تاریخچه قدیمی را خواهند داشت\&. اگر آن‌ها صرفاً دستور \fBgit pull && git push\fR را اجرا کنند، تاریخچه بازنویسی‌نشده با تاریخچه جدید ادغام خواهد شد، که منجر به پدیدار شدن چیزی شبیه به دو نسخه از هر کامیت درگیر در بازنویسی شما خواهد شد \(em یک نسخه جدید از هر کامیت که پاک‌سازی‌های انجام‌شده شما را دارد، و یک نسخه قدیمی از هر کامیت که پاک‌سازی نشده است \(em که با یکدیگر ادغام می‌شوند\&. این بدان معناست که هر آنچه با دقت برای حذف آن از مخزن تلاش کرده بودید، دوباره به سرور پوش شده است\&. اگر صرفاً یک URL مخزن جدید به آن‌ها بدهید و از آن‌ها بخواهید دوباره کلون کنند، احتمال بیشتری وجود دارد که موفق شوید مطمئن شوید داده‌های ناپاک را دوباره پوش نمی‌کنند\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} بازنویسی تاریخچه، تگ‌ها را نیز بازنویسی خواهد کرد؛ کسانی که قبلاً تگ‌ها را دانلود کرده‌اند، حتی اگر \fB\-\-tags\fR را برای \fBgit fetch\fR یا \fBgit pull\fR مشخص کنند، تگ‌های به‌روزرسانی‌شده را دریافت نخواهند کرد (به بخش "On Re\-tagging" در \fBgit-tag\fR(1) مراجعه کنید)\&. هر کاربری که تلاش می‌کند از یک کلون موجود استفاده کند باید تمام تگ‌هایی را که قبلاً دانلود کرده است \fIپیش از\fR دریافت مجدد آن‌ها، اجباراً حذف کند؛ شاید برای آن‌ها آسان‌تر باشد که صرفاً کلون جدیدی بگیرند، کاری که با یک URL کلون جدید احتمال بیشتری دارد انجام دهند\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} بازنویسی تاریخچه ممکن است برخی از refها را حذف کند (برای مثال شاخه‌هایی که تنها فایل‌هایی را داشتند که می‌خواستید از تاریخچه برداشته شوند)؛ مگر اینکه git push را با گزینه‌های \fB\-\-mirror\fR یا \fB\-\-prune\fR اجرا کنید، آن refها همچنان روی سرور وجود خواهند داشت\&. اگر افراد سپس این شاخه‌ها را در شاخه‌های دیگر ادغام کنند، تاریخچه قدیمی و جدید را با هم ترکیب خواهند کرد\&. اگر کاربران قبلاً این شاخه‌ها را کلون کرده باشند، حذف آن‌ها از روی سرور کافی نیست؛ لازم است همه کاربران هر شاخه محلی مبتنی بر این refها را حذف کنند و fetch را نیز با گزینه \fB\-\-prune\fR اجرا نمایند\&. صرفاً کلون‌گیری مجدد از یک URL جدید آسان‌تر است\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} سرور ممکن است اجازه ندهد که روی برخی از refها force push انجام دهید\&. برای مثال، سیستم‌های بازبینی کد ممکن است فضاهای نام ارجاع ویژه‌ای داشته باشند (مانند refs/changes/، refs/pull/، refs/merge\-requests/) که آن‌ها را قفل کرده‌اند، و شما باید به نحوی از ادغام آن تاریخچه‌های قفل‌شده (و بنابراین پاک‌سازی‌نشده) با تاریخچه پاک‌سازی‌شده خود توسط کاربران جلوگیری کنید\&. هر سیستم بازبینی کد نرم‌افزاری با این موضوع به شکل متفاوتی برخورد می‌کند (برای چند پیوند به بخش حذف داده‌های حساس مراجعه کنید)\&. .RE .RE .sp .RS 4 .ie n \{\ \h'-04' 4.\h'+01'\c .\} .el \{\ .sp -1 .IP " 4." 4.2 .\} دستور filter\-repo را با گزینه‌های فیلترسازی مورد نظر خود اجرا کنید\&. مثال‌های متعددی در بخش موسوم به \(lqEXAMPLES\(rq آمده است\&. برای موارد پیچیده‌تر، توجه داشته باشید که انجام فیلترسازی در چندین مرحله (با اجرای متوالی چندین فراخوانی filter\-repo) پشتیبانی می‌شود\&. اگر در این مرحله مشکلی پیش آمد، کافی است کلون خود را حذف کرده و دوباره شروع کنید\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 5.\h'+01'\c .\} .el \{\ .sp -1 .IP " 5." 4.2 .\} مخزن جدید خود را به مکان جدید آن پوش کنید (توجه داشته باشید که refs/remotes/origin/* در بخش اول filter\-repo به refs/heads/* منتقل شده‌اند، بنابراین می‌توانید به جای شاخه‌های ردیابی ریموت، صرفاً با شاخه‌های معمولی کار کنید)\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 6.\h'+01'\c .\} .el \{\ .sp -1 .IP " 6." 4.2 .\} (اختیاری) برخی ملاحظات اضافی .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} ابزار filter\-repo دارای یک گزینه \-\-replace\-refs است تا امکان ایجاد ارجاعات جایگزین (replace refs) را (به \fBgit-replace\fR(1) مراجعه کنید) برای هر شناسه کامیت بازنویسی‌شده فراهم سازد، که به شما امکان می‌دهد از هش‌های کامیت قدیمی (کامل و غیراختصاری) در خط فرمان git برای ارجاع به کامیت‌های جدیداً بازنویسی‌شده استفاده کنید\&. اگر می‌خواهید از این replace refها استفاده کنید، آن‌ها را به‌صورت دستی به URL کلون مربوطه پوش کنید و به کاربران بگویید که آن‌ها را به‌صورت دستی دریافت کنند (مثلاً با تنظیم refspec دریافت خود، \fBgit config \-\-add remote\&.origin\&.fetch +refs/replace/*:refs/replace/*\fR)\&. متأسفانه، replace refها هنوز به‌طور گسترده شناخته‌شده نیستند؛ پروژه‌هایی مانند jgit و libgit2 از آن‌ها پشتیبانی نمی‌کنند و سیستم‌های مدیریت مخزن موجود (مانند Gerrit، GitHub، GitLab) هنوز replace refها را پشتیبانی نمی‌کنند\&. بنابراین فرد نمی‌تواند از هش‌های کامیت قدیمی در رابط کاربری این سیستم‌های دیگر استفاده کند\&. این ممکن است در آینده تغییر کند، اما replace refها دست‌کم در محیط محلی درون رابط خط فرمان git به کاربران کمک می‌کنند\&. همچنین، آگاه باشید که گراف‌های کامیت (commit\-graphs) در ارتباط با replace refها بیش از حد محتاط عمل می‌کنند و در صورت وجود هر یک از آن‌ها کاملاً خاموش می‌شوند، بنابراین پس از گذشت زمان کافی که شناسه‌های کامیت قدیمی کمتر مورد توجه قرار گیرند، ممکن است کاربران بخواهند replace refها را به‌صورت محلی حذف کنند تا سرعت بالای حاصل از commit\-graphs را بازیابند\&. .RE .RE .SS "چرا origin من حذف شده است؟ (Why is my origin removed?)" .sp هنگامی که تاریخچه را بازنویسی می‌کنید، تمامی شناسه‌های کامیت (با شروع از اولین کامیتی که تغییرات در آن رخ داده است) تغییر می‌یابند\&. حتی اگر فکر می‌کنید یک کامیت میانی را تغییر نداده‌اید، این واقعیت که هر یک از اجداد آن را تغییر داده‌اید نیز تغییری محسوب می‌شود که اثرگذار است و باعث می‌شود شناسه آن کامیت نیز تغییر یابد\&. متأسفانه برای خود شما یا فرد دیگری بسیار آسان است که به‌طور تصادفی تاریخچه قدیمی و نامطلوبی را که سعی در بازنویسی آن داشتید با تاریخچه جدید ادغام کنید، که نه تنها باعث بازگشت تاریخچه قدیمی می‌شود، بلکه "دو نسخه" از هر کامیت (هم کامیت اصلی و هم جایگزین پاک‌سازی‌شده) ایجاد می‌کند، و در نتیجه تعداد کامیت‌های موجود در مخزن شما را دو برابر می‌سازد\&. به‌طور خلاصه، در نهایت با آشفتگی حتی بزرگ‌تری نسبت به آنچه شروع کرده بودید مواجه می‌شوید\&. .sp این اتفاق مکرراً برای افرادی که از \fBgit filter\-branch\fR یا \fBBFG repo cleaner\fR استفاده می‌کنند می‌افتد، و ممکن است برای کسانی که از \fBgit filter\-repo\fR استفاده می‌کنند نیز رخ دهد اگر اصرار داشته باشند که تغییرات را به مخزن اصلی بازگردانده و پوش کنند\&. نمونه راه‌هایی که می‌توانید از طریق آن‌ها به چنین تاریخچه حتی ناخوشایندتری برسید عبارتند از: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} در خط فرمان (یک کلون دیگر از همان مخزن از پیش از پاک‌سازی): \fBgit pull && git push\fR .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} در یک فورج نرم‌افزاری: "بازگشایی Pull\-Request/Merge\-Request/Code\-Review قدیمی و زدن دکمه merge/submit" .RE .sp حذف ریموت \fBorigin\fR و پیشنهاد دادن اینکه افراد به یک مخزن جدید پوش کنند (و اطمینان از اینکه به دیگران بگویند مخزن جدید را کلون کنند) معمولاً یک نیروی بازدارنده خوب برای جلوگیری از این مشکلات است\&. اما، اگر افراد علی‌رغم این هشدارها واقعاً بخواهند به مخزن اصلی پوش کنند، انجام آن بسیار ساده است؛ کافی است دستور زیر را اجرا کنید: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} \fBgit remote add origin $ORIGINAL_CLONE_URL\fR .RE .sp و سپس می‌توانید پوش کنید (مثلاً \fBgit push \-\-force \-\-branches \-\-tags \-\-prune\fR)\&. از آنجا که حذف آدرس origin روشی بسیار ارزان برای پیشگیری بالقوه از آشفتگی‌های بزرگ است، و دور زدن آن برای کسانی که واقعاً می‌خواهند روی تاریخچه اصلی بازنویسی کنند بسیار آسان است، حذف آدرس origin یک اقدام ایمنی فوق‌العاده است که من به کار می‌گیرم\&. .sp یک هشدار نهایی اگر واقعاً می‌خواهید تغییرات را به مخزن اصلی بازگردانید و پوش کنید: بخش بعدی در مورد حذف داده‌های حساس را ببینید\&. آن مراحل مواردی هستند که هنگام پوش کردن به مخزن اصلی لازم خواهند بود؛ آن‌ها به قدری دشوار و پردردسر هستند که فرض می‌کنم فقط زمانی ارزش انجام دارند که داده‌های حساس در میان باشد، اما شما می‌توانید تصمیم بگیرید که برای سایر انواع بازنویسی نیز از آن‌ها پیروی کنید\&. .SS "حذف داده‌های حساس (Sensitive Data Removals)" .sp حذف داده‌های حساس نوع خاصی از بازنویسی تاریخچه است\&. در حالی که ترکیب تاریخچه پاک‌سازی‌شده با تاریخچه پاک‌سازی‌نشده همیشه بسیار مشکل‌ساز است، برای حذف داده‌های حساس همچنین بد است که به دیگران اجازه داده شود به هر نحوی به مشاهده/کلون/دریافت تاریخچه پاک‌سازی‌نشده ادامه دهند؛ کاربران اغلب باید تلاش کنند تا تاریخچه قدیمی را نیز به‌طور کامل محو سازند\&. .sp توجه داشته باشید که اگر داده‌های حساس مورد بحث یک توکن/رمز عبور/اعتبارنامه/راز (token/password/credential/secret) است (که اغلب چنین است)، بسیار مهم است که ابتدا آن اعتبارنامه را ابطال (revoke) و تعویض (rotate) کنید\&. هنگامی که اعتبارنامه ابطال یا تعویض شود، دیگر نمی‌توان از آن برای دسترسی استفاده کرد\&. ابطال/تعویض ممکن است مشکل شما را بدون توسل به اقدام سنگین بازنویسی و پاک‌سازی تاریخچه حل کند\&. .sp برای بازنویسی تاریخچه جهت حذف داده‌های حساس، سه مرحله سطح‌بالا وجود دارد: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} مخزن را به‌صورت محلی با استفاده از git\-filter\-repo بازنویسی کنید .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اطمینان حاصل کنید که سایر نسخه‌ها پاک‌سازی شده‌اند، از جمله: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} سروری که از آن کلون کرده‌اید .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} سایر کلون‌هایی که وجود دارند، مانند کلون‌هایی که همکارانتان ساخته‌اند .RE .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} جلوگیری از تکرار و اجتناب از نشت داده‌های حساس در آینده .RE .sp هر یک از این موارد در زیر با جزئیات بیشتر بررسی خواهد شد\&. .sp یک نکته مهم که باید به آن توجه داشت این است که باید به دیگرانی که روی همان مخزن کار می‌کنند دستور داده شود تا زمانی که شما پاک‌سازی را انجام می‌دهید دست از کار بکشند؛ اگر آن‌ها در حین پاک‌سازی شما به توسعه ادامه دهند، احتمالاً مجبور خواهید شد یا تغییرات آن‌ها را دور بریزید یا پاک‌سازی خود را از نو شروع کنید\&. .sp .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBمخزن را به‌صورت محلی با استفاده از git-filter-repo بازنویسی کنید\fR .RS 4 .sp گام اول این است که نسخه‌ای از مخزن خود را به‌صورت محلی با استفاده از git\-filter\-repo بازنویسی کنید\&. دستورات دقیق برای اجرا بسته به اینکه داده‌های حساس در کجای مخزن شما یافت می‌شوند متفاوت خواهد بود، اما چند نکته کلی: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} از فلگ \-\-sensitive\-data\-removal استفاده کنید\&. این فلگ اطلاعات اضافی مفیدی را برای مراحل دیگر فراهم می‌کند\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اگر داده‌های حساس تمامی یک یا چند فایل است، و هیچ نسخه‌ای از آن فایل‌ها در طول تاریخچه نیازی به نگهداری در مخزن شما ندارد، فلگ \-\-invert\-paths همراه با یک یا چند آرگومان \-\-path می‌تواند بسیار مفید واقع شود\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اگر داده‌های حساس صرفاً یک رشته متنی است که در یک یا چند فایل یافت می‌شود و می‌خواهید آن رشته حساس را با چیز دیگری جایگزین کنید و در عین حال بقیه فایل(ها) دست‌نخورده باقی بماند، گزینه \-\-replace\-text می‌تواند بسیار مفید باشد\&. .RE .sp پس از بازنویسی تاریخچه به‌صورت محلی، حتماً آن را بررسی کنید تا مطمئن شوید داده‌های حساس حذف شده‌اند\&. برخی از دستوراتی که ممکن است برای بررسی مفید باشند عبارتند از: .sp .if n \{\ .RS 4 .\} .nf git log \-\-all \-\-name\-status \-\- ${PROBLEMATIC_FILE1} ${PROBLEMATIC_FILE2} .fi .if n \{\ .RE .\} .sp .sp یا .sp .if n \{\ .RS 4 .\} .nf git log \-S"${PROBLEMATIC_STRING}" \-\-all \-p \-\- .fi .if n \{\ .RE .\} .sp .sp اگر هر یک از این دستورات داده‌های حساس بیشتری را نشان داد، پیش از ادامه، دستورات اضافی git\-filter\-repo را برای پاک‌سازی داده‌های لازم اجرا کنید\&. .RE .sp .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBاطمینان حاصل کنید که سایر نسخه‌ها پاک‌سازی شده‌اند: سرور اصلی\fR .RS 4 .sp پاک‌سازی مخزنی که از آن کلون کرده‌اید مستلزم force push کردن تاریخچه بازنویسی‌شده شما روی تاریخچه اصلی است\&. شما باید تمامی refها را به‌صورت اجباری پوش کنید، نه فقط شاخه فعلی خود را\&. می‌توانید برای انجام این کار از دستور زیر استفاده کنید (قبل از اجرای آن، فهرست موارد بلافاصله بعد از این دستور را بخوانید): .sp .if n \{\ .RS 4 .\} .nf git push \-\-force \-\-mirror origin .fi .if n \{\ .RE .\} .sp .sp چندین نکته درباره این دستور: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اگر هر یک از همکاران شما از زمان شروع کار شما تغییری را پوش کرده باشند، این دستور force push تغییرات آن‌ها را دور خواهد ریخت\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} این force push احتمالاً در پوش کردن برخی از refها با شکست مواجه می‌شود، زیرا اکثر فورج‌ها (Gerrit، GitHub، GitLab، و غیره) مانع از به‌روزرسانی برخی refها می‌شوند (برای مثال \fBrefs/changes/*\fR، \fBrefs/pull/*\fR، \fBrefs/merge\-requests/*\fR)\&. لازم است دستورالعمل‌های آن فورج‌ها را دنبال کنید تا refهای باقی‌مانده به‌روزرسانی یا حذف شوند، و جمع‌آوری زباله (garbage collection) در سمت آن‌ها فعال شود\&. چند مثال: (\m[blue]\fBمستندات GitLab درباره کاهش اندازه مخزن\fR\m[]\&\s-2\u[1]\d\s+2، یا \m[blue]\fBبخش "Fully removing the data from GitHub" در مستندات GitHub\fR\m[]\&\s-2\u[2]\d\s+2)\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اگر گزینه \fB\-\-no\-fetch\fR را به git\-filter\-repo داده‌اید (یا با گزینه دیگری به‌طور ضمنی آن را فعال کرده‌اید)، باید یا (۱) گزینه \fB\-\-mirror\fR را حذف کنید و خودتان مشخص کنید کدام refها یا refspecها را پوش نمایید، یا (۲) از گزینه \fB\-\-mirror\fR استفاده کنید و خطر حذف هرگونه ref را که دریافت نکرده‌اید (fetch نکرده‌اید) بپذیرید\&. علاوه بر این، اگر فاقد برخی از refهایی بودید که سرور داشت و داده‌های حساس در تاریخچه آن‌ها وجود داشت، در این مرحله تنها گزینه‌های شما برای پاک‌سازی واقعی داده‌های حساس از سرور این است که یا بازنویسی خود را از ابتدا تکرار کنید (و مطمئن شوید که این بار refهای مربوطه گنجانده شده‌اند) یا آن refها را روی سرور حذف کنید\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} بله، می‌دانم که \-\-mirror متضمن \-\-force است و نیازی به آن نیست\&. من به هر حال \-\-force را به عنوان یک یادآوری بصری برای خوانندگان اضافه کردم تا نشان دهم این کار تغییرات روی سرور را رونویسی خواهد کرد\&. .RE .sp همچنین، اگر هر یک از اشیاء LFS در اثر بازنویسی شما یتیم (orphaned) شدند، آن اشیاء احتمالاً حاوی داده‌های حساس هستند و باید از سرور LFS حذف/پاک‌سازی شوند\&. باید از نگهدارنده سرور LFS که استفاده می‌کنید درباره نحوه حذف/پاک‌سازی آن‌ها روی سرور سؤال کنید\&. .RE .sp .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBاطمینان حاصل کنید که سایر نسخه‌ها پاک‌سازی شده‌اند: کلون‌های همکاران\fR .RS 4 .sp پس از اینکه سرور را پاک‌سازی کردید، ساده‌ترین راه برای پاک‌سازی سایر کلون‌ها این است که از همه بخواهید کلون‌های موجود خود را حذف کرده و دوباره کلون بگیرند\&. .sp اگر این یک گزینه نیست، باید با احتیاط پیش بروید زیرا یک دستور ساده \fBgit pull && git push\fR از هر کلون دیگری، مجدداً مخزن اصلی را آلوده خواهد کرد و آشفتگی را برای پاک‌سازی حتی دشوارتر می‌سازد\&. برای جلوگیری از این موضوع، قبل از پوش کردن از هر کلون دیگری، باید از آن‌ها بخواهید نسخه خود را طبق توضیحات زیر پاک‌سازی کنند\&. .sp با این حال، ابتدا اجازه دهید یادآوری کنم که شما \fBنباید\fR از سایر توسعه‌دهندگان بخواهید کلون خود را با اجرای همان دستورات \fBgit\-filter\-repo\fR که خودتان اجرا کردید پاک‌سازی کنند\&. در حالی که ممکن است این کار گاهی تصادفاً جواب دهد، اما به‌طور کلی قابل اعتماد نیست\&. اجرای همان دستورات \fBgit\-filter\-repo\fR، حتی در صورت یکسان بودن، می‌تواند منجر به دریافت هش‌های جدیدی برای کامیت‌ها شود که با هش‌های جدید شما تفاوت دارد، و در نهایت با آشفتگی‌ای شامل دو یا چند نسخه از هر کامیت مواجه خواهید شد\&. .sp در عوض، توسعه‌دهندگانی که کلون‌های دیگری از مخزن دارند، در صورتی که تمایلی به دور انداختن نسخه خود و کلون مجدد ندارند، باید مراحل زیر را برای پاک‌سازی نسخه خود دنبال کنند: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} تمام تگ‌ها را حذف کرده و دستور \fBgit fetch \-\-prune \-\-tags\fR را اجرا کنند\&. اجرای دستور fetch بدون حذف تگ‌ها در ابتدا باعث می‌شود تگ‌های قدیمی حفظ شوند، که داده‌های حساس را نگه خواهد داشت\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} هر تغییری را که در هر شاخه (یا ref دیگری) دارند بر روی تاریخچه جدید ریبیس کنند\&. برای دستورالعمل‌ها به بخش "RECOVERING FROM UPSTREAM REBASE" در \fBgit-rebase\fR(1) (و به‌ویژه "The hard case") مراجعه کنید\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} چند مرحله را برای پاک‌سازی تاریخچه قبل از ریبیس اجرا کنند (توجه داشته باشید که مرحله اول تمام reflogها از جمله تمام ورودی‌های stash را حذف می‌کند\&. این هزینه بالایی دارد، اما برای پاک‌سازی داده‌های حساس ضروری است): .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} git reflog expire \-\-expire=now \-\-all .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} git gc \-\-prune=now .RE .RE .sp پس از تکمیل این مراحل، همچنین باید بررسی کنید که کلون دیگر حاوی هیچ داده حساسی نباشد (از قلم انداختن چیزی واقعاً آسان است، که شما را در معرض خطر آلوده کردن مجدد سایر مخازن با داده‌های حساس قرار می‌دهد)\&. می‌توانید این کار را با اجرای دستور زیر انجام دهید: .sp .if n \{\ .RS 4 .\} .nf git cat\-file \-t ${HASH_OF_FIRST_CHANGED_COMMIT} .fi .if n \{\ .RE .\} .sp .sp جایی که \fB${HASH_OF_FIRST_CHANGED_COMMIT}\fR توسط git\-filter\-repo در انتهای اجرای آن چاپ شده بود (اگر بیش از یک "اولین کامیت تغییریافته" وجود داشت، این دستور را چندین بار، با هش هر کامیت اجرا کنید)\&. اگر این دستور یک خطای مهلک (fatal error) برگرداند، کامیت به‌درستی از این مخزن حذف شده است\&. اگر با "commit" پاسخ دهد، آن شیء همچنان وجود دارد و لازم است تگ‌ها را مجدداً حذف کنید، تمام شاخه‌ها/refهای لازم را دوباره ریبیس کنید، و مجدداً reflogها را منقضی کرده و gc را دوباره انجام دهید\&. اگر کنجکاو هستید که کدام شاخه‌ها یا refها شاخه‌های مشکل‌سازی بودند که \fB${HASH_OF_FIRST_CHANGED_COMMIT}\fR را نگه داشته بودند، با فرض اینکه کارهای انقضای reflog و gc فوق را انجام داده باشید، دستور زیر باید به شما در یافتن شاخه‌ها/refهای مشکل‌ساز کمک کند: .sp .if n \{\ .RS 4 .\} .nf git for\-each\-ref \-\-contains ${HASH_OF_FIRST_CHANGED_COMMIT} .fi .if n \{\ .RE .\} .sp .sp همچنین به یاد داشته باشید، دستور cat\-file باید برای هر \fB${HASH_OF_FIRST_CHANGED_COMMIT}\fR درگیر در صورتی که بیش از یکی داشته باشید، با یک خطای مهلک برگردد\&. .sp پس از انجام همه این موارد، اگر هر شیء LFS در اثر بازنویسی یتیم شده باشد (که باز هم اگر هنگام اجرای git\-filter\-repo از گزینه \-\-sensitive\-data\-removal استفاده کنید به شما گفته خواهد شد)، باید آن اشیاء LFS را نیز حذف کنید\&. آن‌ها را در چند دایرکتوری در زیر مسیر \&.git/lfs/objects/ پیدا کرده و حذف نمایید\&. .RE .sp .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBجلوگیری از تکرار و اجتناب از نشت داده‌های حساس در آینده\fR .RS 4 .sp اقدامات متعددی وجود دارد که می‌توانید برای کمک به جلوگیری از تکرار مشکلات انجام دهید\&. ممکن است همه آن‌ها برای مورد شما قابل اعمال نباشند، اما هرچه موارد بیشتری اعمال شوند، احتمال جلوگیری از مشکلات بیشتر است\&. .sp برای مقابله با نشت داده‌های حساس موجود: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} از آنجا که آلودگی مجدد مخزنی که از آن کلون کرده‌اید بسیار آسان است (تنها کافی است یک همکار دستور \fBgit pull && git push\fR را از کلون خود که قبل از پاک‌سازی شما ایجاد شده بود اجرا کند)، در انجام مراحل پاک‌سازی فوق برای سایر کلون‌ها هوشیاری فوق‌العاده‌ای به خرج دهید تا مطمئن شوید که همه آن‌ها پاک‌سازی شده‌اند\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اگر یک مخزن مرکزی دارید که همه به آن پوش می‌کنند، روش‌هایی را بررسی کنید تا اولین کامیت(های) تغییریافته از (re\-)push شدن به مخزن شما منع شوند\&. متأسفانه، در حال حاضر تعداد کمی از مدیران مخزن چنین قابلیت پیش‌فرضی دارند (برای یک نمونه به قابلیت ban\-commit در Gerrit در آدرس \m[blue]\fBhttps://gerrit\-review\&.googlesource\&.com/Documentation/cmd\-ban\-commit\&.html\fR\m[] مراجعه کنید)، اما تعداد کمی ممکن است به شما اجازه دهند قلاب‌های pre\-receive خود را بنویسید که پوش‌های حاوی این کامیت‌های بد را رد کنند\&. (ترفند حرفه‌ای برای نوشتن چنین قلاب pre\-receive: از \fBgit cat\-file \-t ${BAD_COMMIT}\fR به عنوان یک بررسی کم‌هزینه قبل از بررسی اینکه آیا هر محدوده بازبینی بین \fB\fR و \fB\fR شامل \fB${BAD_COMMIT}\fR است یا خیر استفاده کنید) .RE .sp اقداماتی برای کمک به جلوگیری از سایر نشت‌های داده‌های حساس در آینده: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اگر احتمال دارد داده‌های حساس در نام فایل‌های خاصی ظاهر شوند که اصلاً نباید در git ردیابی شوند، آن نام فایل‌ها را به \&.gitignore اضافه کنید تا خطر اضافه شدن تصادفی آن‌ها توسط دیگران کاهش یابد\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} از هاردکد کردن اطلاعات محرمانه در کد خودداری کنید\&. از متغیرهای محیطی، ابزارهای مدیریت پیکربندی، یا سرویس‌های مدیریت راز مانند Azure Key Vault، AWS Secrets Manager، یا HashiCorp Vault برای مدیریت و تزریق رازها در زمان اجرا استفاده کنید\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} یک قلاب pre\-commit ایجاد کنید تا داده‌های حساس را قبل از اینکه کامیت شوند یا به جایی پوش شوند بررسی کند، یا از یک ابزار شناخته‌شده در یک قلاب pre\-commit مانند git\-secrets یا gitleaks استفاده کنید\&. .RE .RE .SH "مثال‌ها (EXAMPLES)" .SS "فیلتر کردن بر اساس مسیر (Path based filtering)" .sp برای نگه داشتن تنها فایل \fIREADME\&.md\fR به همراه دایرکتوری‌های \fIguides\fR و \fItools/releases/\fR: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-path README\&.md \-\-path guides/ \-\-path tools/releases .fi .if n \{\ .RE .\} .sp .sp نام دایرکتوری‌ها را می‌توان با یا بدون اسلش پایانی مشخص کرد، و تمام نام‌های فایل نسبت به بالاترین سطح ریشه (toplevel) مخزن سنجیده می‌شوند\&. برای نگه داشتن تمامی فایل‌ها به جز این مسیرها، کافی است \fB\-\-invert\-paths\fR را اضافه کنید: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-path README\&.md \-\-path guides/ \-\-path tools/releases \-\-invert\-paths .fi .if n \{\ .RE .\} .sp .sp اگر می‌خواهید هم فیلتر گنجاندن (inclusion) و هم فیلتر استثنا کردن (exclusion) داشته باشید، کافی است filter\-repo را چندین بار اجرا کنید\&. به عنوان مثال، برای نگه‌داشتن زیردایرکتوری src/main اما حذف فایل‌های درون src/main با نام \fIdata\fR، اجرا کنید: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-path src/main/ git filter\-repo \-\-path\-glob \*(Aqsrc/*/data\*(Aq \-\-invert\-paths .fi .if n \{\ .RE .\} .sp .sp توجه داشته باشید که ستاره (\fB*\fR) در چندین دایرکتوری تطابق پیدا می‌کند، بنابراین دستور دوم مواردی مانند src/main/org/whatever/data را حذف خواهد کرد\&. همچنین دستور دوم به خودی خود مواردی مانند src/not\-main/foo/data را نیز حذف می‌کند، اما از آنجا که src/not\-main/ توسط دستور اول حذف شده است، این مسئله مشکلی ایجاد نمی‌کند\&. علاوه بر این، قرار دادن ستاره درون نقل‌قول گاهی برای جلوگیری از بسط سراسری (glob expansion) توسط پوسته حائز اهمیت است\&. .sp شما همچنین می‌توانید مسیرها را با عبارات باقاعده (regular expression) انتخاب کنید (ببینید \m[blue]\fBhttps://docs\&.python\&.org/3/library/re\&.html#regular\-expression\-syntax\fR\m[])\&. به عنوان مثال، برای اینکه فقط فایل‌هایی از مخزن گنجانده شوند که نام آن‌ها به فرمت YYYY\-MM\-DD\&.txt بوده و حداقل در دو زیردایرکتوری عمیق‌تر قرار دارند: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-path\-regex \*(Aq^\&.*/\&.*/[0\-9]{4}\-[0\-9]{2}\-[0\-9]{2}\&.txt$\*(Aq .fi .if n \{\ .RE .\} .sp .sp اگر می‌خواهید دو دایرکتوری تغییر نام پیدا کنند (و در صورتی که هر دو به یک مکان تغییر نام داده شوند، احتمالاً ادغام شوند)، از \-\-path\-rename استفاده کنید؛ به عنوان مثال، برای تغییر نام هر دوی \fIcmds/\fR و \fIsrc/scripts/\fR به \fItools/\fR: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-path\-rename cmds:tools \-\-path\-rename src/scripts/:tools/ .fi .if n \{\ .RE .\} .sp .sp مشابه با \fB\-\-path\fR، دایرکتوری‌ها برای \fB\-\-path\-rename\fR نیز می‌توانند با یا بدون اسلش پایانی مشخص شوند\&. .sp اگر با \fB\-\-path\-rename\fR تغییر نامی به سمتی انجام دهید که از قبل در حال استفاده بوده است، بدون هیچ هشداری رونویسی (overwrite) خواهد شد\&. با این حال، اگر سعی کنید چندین فایل را به یک مکان مشترک تغییر نام دهید (مثلاً هر دوی src/scripts/run_release\&.sh و cmds/run_release\&.sh با تغییر نام‌های بالا موجود بوده و محتوای متفاوتی داشتند)، به شما خطایی داده خواهد شد\&. اگر با چنین حالتی مواجه شدید، ممکن است بخواهید یک دستور تغییر نام دیگر اضافه کنید تا یکی از مسیرها را به جای دیگری منتقل نماید که تداخلی ایجاد نشود: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-path\-rename cmds/run_release\&.sh:tools/do_release\&.sh \e \-\-path\-rename cmds/:tools/ \e \-\-path\-rename src/scripts/:tools/ .fi .if n \{\ .RE .\} .sp .sp همچنین \fB\-\-path\-rename\fR مسائلی را در مورد ترتیب اعمال مطرح می‌کند؛ همه آرگومان‌های مسیر به ترتیب اعمال می‌شوند\&. بنابراین، دستوری مانند .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-path\-rename sources/:src/main/ \-\-path src/main/ .fi .if n \{\ .RE .\} .sp .sp منطقی خواهد بود اما جابجا کردن این دو آرگومان منطقی نیست (چون src/main/ با تغییر نام ایجاد می‌شود، بنابراین معکوس کردن ترتیب آن‌ها مخزنی خالی به شما تحویل می‌دهد)\&. همچنین دقت کنید که تغییر نام cmds/run_release\&.sh در دو مثال قبل، پیش از سایر تغییر نام‌ها انجام شد\&. .sp توجه داشته باشید که تغییر نام مسیرها، فیلتر کردن مسیرها را انجام نمی‌دهد؛ بنابراین دستور زیر .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-path src/main/ \-\-path\-rename tools/:scripts/ .fi .if n \{\ .RE .\} .sp .sp منجر به وجود آمدن دایرکتوری‌های tools یا scripts نخواهد شد، زیرا تک فیلترِ موجود تنها src/main/ را انتخاب کرده است\&. احتمالاً در عوض می‌خواهید این دستور را اجرا کنید: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-path src/main/ \-\-path tools/ \-\-path\-rename tools/:scripts/ .fi .if n \{\ .RE .\} .sp .sp اگر ترجیح می‌دهید فیلتر کردن را صرفاً بر اساس نام پایه (basename) انجام دهید، از فلگ \fB\-\-use\-base\-name\fR استفاده کنید (البته این گزینه با \fB\-\-path\-rename\fR ناسازگار است)\&. برای مثال، جهت گنجاندن فایل‌های README\&.md و Makefile از هر دایرکتوری: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-use\-base\-name \-\-path README\&.md \-\-path Makefile .fi .if n \{\ .RE .\} .sp .sp اگر می‌خواستید تمامی فایل‌های \&.DS_Store را در هر دایرکتوری حذف کنید، می‌توانید از این دستور: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-invert\-paths \-\-path \*(Aq\&.DS_Store\*(Aq \-\-use\-base\-name .fi .if n \{\ .RE .\} .sp .sp یا این دستور استفاده کنید: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-invert\-paths \-\-path\-glob \*(Aq*/\&.DS_Store\*(Aq \-\-path \*(Aq\&.DS_Store\*(Aq .fi .if n \{\ .RE .\} .sp .sp (گزینه \fB\-\-path\-glob\fR به تنهایی کافی نیست زیرا ممکن است فایل \&.DS_Store را در بالاترین سطح ریشه نادیده بگیرد؛ از طرف دیگر، عبارتی مانند \fB\-\-path\-glob \*(Aq*\&.DS_Store\*(Aq\fR هرچند آن مشکل را برطرف می‌کند اما فایل‌هایی با نام \fBfoo\&.DS_Store\fR یا \fBbar/baz\&.DS_Store\fR را نیز در بر می‌گیرد) .sp در نهایت، گزینه \fB\-\-filename\-callback\fR را نیز در بخشی با عنوان \(lqCALLBACKS\(rq ببینید\&. .SS "فیلتر کردن بر اساس مسیرهای متعدد (Filtering based on many paths)" .sp اگر فهرست بلندی از فایل‌ها، دایرکتوری‌ها، الگوهای سراسری (globs) یا عبارات باقاعده برای فیلتر کردن دارید، می‌توانید آن‌ها را در یک فایل قرار داده و از \fB\-\-paths\-from\-file\fR استفاده کنید؛ برای مثال با فایلی به نام stuff\-i\-want\&.txt و محتویات: .sp .if n \{\ .RS 4 .\} .nf # Blank lines and comment lines are ignored\&. # Examples similar to \-\-path: README\&.md guides/ tools/releases # An example that is like \-\-path\-glob: glob:*\&.py # An example that is like \-\-path\-regex: regex:^\&.*/\&.*/[0\-9]{4}\-[0\-9]{2}\-[0\-9]{2}\&.txt$ # An example of renaming a path tools/==>scripts/ # An example of using a regex to rename a path regex:(\&.*)/([^/]*)/([^/]*)\e\&.text$==>\e2/\e1/\e3\&.txt .fi .if n \{\ .RE .\} .sp .sp سپس می‌توانید دستور .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-paths\-from\-file stuff\-i\-want\&.txt .fi .if n \{\ .RE .\} .sp .sp را اجرا کنید تا مخزنی داشته باشید که تنها حاوی فایل README\&.md در بالاترین سطح، دایرکتوری‌های guides/ و tools/releases/، تمام فایل‌های پایتون و فایل‌هایی باشد که نام آن‌ها به شکل YYYY\-MM\-DD\&.txt در عمق حداقل دو زیردایرکتوری است، و همچنین tools/ را به scripts/ و فایل‌هایی مانند foo/bar/baz\&.text را به bar/foo/baz\&.txt تغییر نام دهد\&. به پیشوندهای خطی خاص \fBglob:\fR و \fBregex:\fR و رشته خاص \fB==>\fR برای مشخص کردن تغییر نام‌ها توجه کنید\&. .sp گاهی روشی برای تولید آسان فهرست تمام فایل‌های مد نظر خود دارید\&. به عنوان مثال، اگر می‌دانید که هیچ‌یک از فایل‌های ردگیری‌شده کنونی شامل خط جدید (newline) یا کاراکترهای خاص نیستند (مدخل core\&.quotePath را از \fBgit config \-\-help\fR ببینید) به گونه‌ای که \fBgit ls\-files\fR همه فایل‌ها را عیناً خط به خط چاپ می‌کند، و می‌دانستید که فقط می‌خواهید فایل‌های ردگیری‌شده فعلی را نگه دارید (و در نتیجه هر فایلی را که فقط در شاخه‌های دیگر یا در کامیت‌های قدیمی‌تر وجود دارد از کل تاریخچه کامیت‌ها حذف کنید)، در این صورت می‌توانید از جفت دستوراتی مانند این استفاده کنید: .sp .if n \{\ .RS 4 .\} .nf git ls\-files >\&.\&./paths\-i\-want\&.txt git filter\-repo \-\-paths\-from\-file \&.\&./paths\-i\-want\&.txt .fi .if n \{\ .RE .\} .sp .sp به طور مشابه، می‌توانید از \-\-paths\-from\-file برای حذف تعداد زیادی فایل استفاده کنید\&. برای مثال، می‌توانید \fBgit filter\-repo \-\-analyze\fR را برای دریافت گزارش‌ها اجرا کنید، یکی از آن‌ها مانند \&.git/filter\-repo/analysis/path\-deleted\-sizes\&.txt را بررسی کرده و نام تمامی فایل‌ها را در فایلی مانند /tmp/files\-i\-dont\-want\-anymore\&.txt کپی کنید و سپس دستور .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-invert\-paths \-\-paths\-from\-file /tmp/files\-i\-dont\-want\-anymore\&.txt .fi .if n \{\ .RE .\} .sp .sp را اجرا کنید تا همه آن‌ها را حذف نماید\&. .SS "میان‌برهای مبتنی بر دایرکتوری (Directory based shortcuts)" .sp فرض کنید ساختار دایرکتوری شما به این صورت باشد: .sp .if n \{\ .RS 4 .\} .nf module/ foo\&.c bar\&.c otherDir/ blah\&.config stuff\&.txt zebra\&.jpg .fi .if n \{\ .RE .\} .sp اگر فقط دایرکتوری module/ را می‌خواستید و تمایل داشتید که این دایرکتوری به ریشه جدید تبدیل شود، به طوری که ساختار دایرکتوری جدید شما به این شکل درآید: .sp .if n \{\ .RS 4 .\} .nf foo\&.c bar\&.c .fi .if n \{\ .RE .\} .sp در این صورت می‌توانید اجرا کنید: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-subdirectory\-filter module/ .fi .if n \{\ .RE .\} .sp .sp اگر تمامی فایل‌ها از مخزن اصلی را می‌خواستید، اما قصد داشتید همه چیز را به زیردایرکتوری به نام my\-module/ منتقل کنید، به طوری که ساختار جدید دایرکتوری شما به این صورت باشد: .sp .if n \{\ .RS 4 .\} .nf my\-module/ module/ foo\&.c bar\&.c otherDir/ blah\&.config stuff\&.txt zebra\&.jpg .fi .if n \{\ .RE .\} .sp در این صورت در عوض دستور زیر را اجرا می‌کردید: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-to\-subdirectory\-filter my\-module/ .fi .if n \{\ .RE .\} .sp .SS "فیلتر کردن بر اساس محتوا (Content based filtering)" .sp اگر می‌خواهید تمام فایل‌های بزرگتر از یک اندازه معین را فیلتر (حذف) کنید، می‌توانید از \fB\-\-strip\-blobs\-bigger\-than\fR به همراه مقدار اندازه (پسوندهای K، M و G شناخته می‌شوند) استفاده کنید، برای مثال: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-strip\-blobs\-bigger\-than 10M .fi .if n \{\ .RE .\} .sp .sp اگر می‌خواهید تمامی فایل‌های دارای شناسه شیء گیت (هش‌ها) مشخص را حذف کنید، هش‌ها را در یک فایل فهرست کرده و اجرا کنید: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-strip\-blobs\-with\-ids FILE_WITH_GIT_BLOB_IDS .fi .if n \{\ .RE .\} .sp .sp اگر می‌خواهید محتویات فایل‌ها را تغییر دهید، می‌توانید این کار را بر اساس فهرستی از عبارات در یک فایل، یک عبارت در هر خط، انجام دهید\&. به عنوان مثال، با فایلی به نام expressions\&.txt حاوی: .sp .if n \{\ .RS 4 .\} .nf p455w0rd foo==>bar glob:*666*==> regex:\ebdriver\eb==>pilot literal:MM/DD/YYYY==>YYYY\-MM\-DD regex:([0\-9]{2})/([0\-9]{2})/([0\-9]{4})==>\e3\-\e1\-\e2 .fi .if n \{\ .RE .\} .sp .sp سپس اجرای .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-replace\-text expressions\&.txt .fi .if n \{\ .RE .\} .sp .sp فایل‌ها را بررسی کرده و \fBp455w0rd\fR را با \fB***REMOVED***\fR، \fBfoo\fR را با \fBbar\fR، هر خط حاوی \fB666\fR را با یک خط خالی، کلمه \fBdriver\fR را با \fBpilot\fR (اما نه اگر حروفی قبل یا بعد از آن باشد؛ مثلاً \fBdrivers\fR بدون تغییر باقی می‌ماند)، متن دقیق \fBMM/DD/YYYY\fR را با \fBYYYY\-MM\-DD\fR و رشته‌های تاریخ با قالب MM/DD/YYYY را با قالب YYYY\-MM\-DD جایگزین خواهد کرد\&. در فایل عبارات، چند نکته قابل توجه وجود دارد: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} هر خط یک جایگزین دارد که با هر آنچه در سمت راست \fB==>\fR قرار دارد مشخص می‌شود\&. اگر \fB==>\fR در خط ظاهر نشود، جایگزین پیش‌فرض \fB***REMOVED***\fR است\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} خطوط می‌توانند با \fBliteral:\fR، \fBglob:\fR، یا \fBregex:\fR شروع شوند تا مشخص کنند که تطابق رشته‌ای عینی (literal)، تطابق با الگو (glob - ببینید \m[blue]\fBhttps://docs\&.python\&.org/3/library/fnmatch\&.html\fR\m[])، یا عبارات باقاعده (ببینید \m[blue]\fBhttps://docs\&.python\&.org/3/library/re\&.html#regular\-expression\-syntax\fR\m[]) انجام شود\&. اگر هیچ‌یک از این‌ها مشخص نشود، \fBliteral:\fR در نظر گرفته می‌شود\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اگر چندین مورد تطابق پیدا شود، همه آن‌ها جایگزین می‌شوند\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} الگوهای glob و regex روی کل فایل اعمال می‌شوند، اما بدون فعال بودن هیچ فلگ خاصی\&. ممکن است برخی افراد مایل باشند \fB(?m)\fR را به regex اضافه کنند تا حالت MULTILINE فعال شود، به طوری که \fB^\fR و \fB$\fR به جای ابتدا و انتهای فایل، با ابتدا و انتهای خطوط مطابقت داشته باشند\&. برای جزئیات به \m[blue]\fBhttps://docs\&.python\&.org/3/library/re\&.html\fR\m[] مراجعه کنید\&. .RE .sp همچنین گزینه \fB\-\-blob\-callback\fR را در بخشی با عنوان \(lqCALLBACKS\(rq ببینید\&. .SS "به‌روزرسانی پیام‌های کامیت/تگ (Updating commit/tag messages)" .sp اگر می‌خواهید پیام‌های کامیت یا تگ را ویرایش کنید، می‌توانید این کار را با همان ساختار نحوی \fB\-\-replace\-text\fR که در بالا توضیح داده شد انجام دهید\&. برای مثال با فایلی به نام expressions\&.txt حاوی: .sp .if n \{\ .RS 4 .\} .nf foo==>bar .fi .if n \{\ .RE .\} .sp .sp سپس اجرای .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-replace\-message expressions\&.txt .fi .if n \{\ .RE .\} .sp .sp عبارت \fBfoo\fR را در پیام‌های کامیت یا تگ با \fBbar\fR جایگزین خواهد کرد\&. .sp همچنین گزینه \fB\-\-message\-callback\fR را در بخشی با عنوان \(lqCALLBACKS\(rq ببینید\&. .SS "فیلتر کردن بر اساس نام مرجع (Refname based filtering)" .sp برای تغییر نام تگ‌ها، از \fB\-\-tag\-rename\fR استفاده کنید، برای مثال: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-tag\-rename foo:bar .fi .if n \{\ .RE .\} .sp .sp این کار هر تگی را که با \fBfoo\fR آغاز می‌شود تغییر نام می‌دهد تا از این پس با \fBbar\fR شروع شود\&. هر یک از طرفین دو‌نقطه می‌تواند خالی باشد، برای مثال: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-tag\-rename \*(Aq\*(Aq:\*(Aqmy\-module\-\*(Aq .fi .if n \{\ .RE .\} .sp .sp برای تغییرات عمومی‌تر نام مراجع، \fB\-\-refname\-callback\fR را در بخشی با عنوان \(lqCALLBACKS\(rq ببینید\&. .SS "فیلتر کردن بر اساس کاربر و ایمیل (User and email based filtering)" .sp برای تغییر نام کاربری و ایمیل‌های کامیت‌ها، می‌توانید یک فایل mailmap در قالبی که توسط \fBgit-shortlog\fR(1) پذیرفته می‌شود ایجاد کنید\&. به عنوان مثال، اگر فایلی به نام my\-mailmap دارید، می‌توانید اجرا کنید: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-mailmap my\-mailmap .fi .if n \{\ .RE .\} .sp .sp و اگر محتویات فعلی آن فایل به شرح زیر باشد (در صورتی که فایل mailmap مشخص‌شده تحت کنترل نسخه باشد، نسخه‌های پیشین آن در تاریخچه نادیده گرفته می‌شوند): .sp .if n \{\ .RS 4 .\} .nf Name For User New Name And New Name And Old Name And .fi .if n \{\ .RE .\} .sp .sp در این صورت می‌توان نام کاربری و/یا ایمیل‌ها را بر اساس نگاشت مشخص‌شده به‌روزرسانی کرد\&. .sp همچنین \fB\-\-name\-callback\fR و \fB\-\-email\-callback\fR را در بخشی با عنوان \(lqCALLBACKS\(rq ببینید\&. .SS "بازنویسی والد (Parent rewriting)" .sp برای جایگزین کردن $commit_A با $commit_B (مثلاً برای اینکه تمامی کامیت‌هایی که $commit_A والد آن‌ها بوده، در عوض $commit_B را به عنوان والد داشته باشند) و بازنویسی تاریخچه برای دائمی کردن آن: .sp .if n \{\ .RS 4 .\} .nf git replace $commit_A $commit_B git filter\-repo \-\-proceed .fi .if n \{\ .RE .\} .sp .sp برای ایجاد یک کامیت جدید با همان محتویات $commit_A اما با والد(های) متفاوت، و سپس جایگزین کردن $commit_A با کامیت جدید و بازنویسی تاریخچه جهت دائمی کردن آن: .sp .if n \{\ .RS 4 .\} .nf git replace \-\-graft $commit_A $new_parent_or_parents git filter\-repo \-\-proceed .fi .if n \{\ .RE .\} .sp .sp گزینه \fB\-\-proceed\fR برای جلوگیری از رد شدن در بررسی «هیچ آرگومانی مشخص نشده است» (no arguments specified) لازم است\&. توجه داشته باشید که نسخه‌های قدیمی‌تر git\-filter\-repo نیاز داشتند پس از ایجاد پیوند (graft) گزینه \fB\-\-force\fR ارسال شود تا از فعال شدن بررسی not\-a\-fresh\-clone جلوگیری شود؛ آن بررسی اصلاح شده است تا این استفاده بیش از حد از \fB\-\-force\fR برطرف گردد\&. .SS "بازنویسی‌های جزئی تاریخچه (Partial history rewrites)" .sp برای بازنویسی تاریخچه تنها روی یک شاخه (که ممکن است باعث شود دیگر هیچ تاریخچه مشترکی با سایر شاخه‌ها نداشته باشد)، از \fB\-\-refs\fR استفاده کنید\&. برای مثال جهت حذف فایلی با نام \fIextraneous\&.txt\fR از شاخه \fImaster\fR: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-invert\-paths \-\-path extraneous\&.txt \-\-refs master .fi .if n \{\ .RE .\} .sp .sp برای بازنویسی صرفاً تعدادی از کامیت‌های اخیر: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-invert\-paths \-\-path extraneous\&.txt \-\-refs master~3\&.\&.master .fi .if n \{\ .RE .\} .sp .SH "فراخوانی‌های بازگشتی (CALLBACKS)" .sp برای انعطاف‌پذیری بیشتر، filter\-repo به شما امکان می‌دهد توابعی را در خط فرمان مشخص کنید تا تمام تغییرات را فیلتر نمایید\&. لطفاً توجه داشته باشید که هشدارهایی درباره سازگاری API در ارتباط با این فراخوانی‌های بازگشتی وجود دارد که باید پیش از استفاده از آن‌ها آگاه باشید؛ به توضیح "API BACKWARD COMPATIBILITY CAVEAT" در نزدیکی بالای کد منبع git\-filter\-repo مراجعه کنید\&. .sp بیشتر توابع فراخوانی بازگشتی دارای فرمت کلی یکسانی هستند (\-\-file\-info\-callback یک استثنا است که بعداً به آن اشاره خواهد شد)\&. برای یک آرگومان خط فرمان مانند .sp .if n \{\ .RS 4 .\} .nf \-\-foo\-callback \*(AqBODY\*(Aq .fi .if n \{\ .RE .\} .sp .sp کد زیر کامپایل و فراخوانی خواهد شد: .sp .if n \{\ .RS 4 .\} .nf def foo_callback(foo): BODY .fi .if n \{\ .RE .\} .sp .sp بنابراین، تنها کافی است اطمینان حاصل کنید که \fIBODY\fR شما \fIfoo\fR را به درستی تغییر داده و بازمی‌گرداند\&. یک نکته مهم برای تمام فراخوانی‌های بازگشتی این است که filter\-repo در همه جا به جای رشته‌ها از رشته‌های بایتی (bytestrings \- به \m[blue]\fBhttps://docs\&.python\&.org/3/library/stdtypes\&.html#bytes\fR\m[] مراجعه کنید) استفاده می‌کند\&. .sp چهار فراخوانی بازگشتی وجود دارد که به شما امکان می‌دهد مستقیماً روی اشیای خام حاوی داده‌هایی که نوشتن آن‌ها در قالب \fBgit-fast-import\fR(1) آسان است، کار کنید: .sp .if n \{\ .RS 4 .\} .nf \-\-blob\-callback \-\-commit\-callback \-\-tag\-callback \-\-reset\-callback .fi .if n \{\ .RE .\} .sp .sp ما بعداً به این موارد بازخواهیم گشت زیرا معمولاً سایر فراخوانی‌های بازگشتی راحت‌تر هستند\&. فراخوانی‌های بازگشتی دیگر روی بخش کوچکی از اشیای خام عمل می‌کنند یا روی بخش‌هایی در انواع مختلف اشیای خام کار می‌کنند (مانند نام نویسنده و نام کامیت‌کننده و نام برچسب‌گذار در میان کامیت‌ها و برچسب‌ها، یا نام‌های ارجاع (refnames) در کامیت‌ها، برچسب‌ها و ریست‌ها، یا پیام‌ها در کامیت‌ها و برچسب‌ها)\&. فراخوانی‌های بازگشتی آسان‌تر عبارتند از: .sp .if n \{\ .RS 4 .\} .nf \-\-filename\-callback \-\-message\-callback \-\-name\-callback \-\-email\-callback \-\-refname\-callback \-\-file\-info\-callback .fi .if n \{\ .RE .\} .sp .sp در هر یک از آن‌ها انتظار می‌رود که صرفاً مقدار جدیدی را بر اساس مقدار ارسالی بازگردانید\&. برای نمونه، .sp .if n \{\ .RS 4 .\} .nf git\-filter\-repo \-\-name\-callback \*(Aqreturn name\&.replace(b"Wiliam", b"William")\*(Aq .fi .if n \{\ .RE .\} .sp .sp منجر به فراخوانی تابع زیر خواهد شد: .sp .if n \{\ .RS 4 .\} .nf def name_callback(name): return name\&.replace(b"Wiliam", b"William") .fi .if n \{\ .RE .\} .sp .sp فراخوانی بازگشتی ایمیل نیز بسیار مشابه است: .sp .if n \{\ .RS 4 .\} .nf git\-filter\-repo \-\-email\-callback \*(Aqreturn email\&.replace(b"\&.cm", b"\&.com")\*(Aq .fi .if n \{\ .RE .\} .sp .sp فراخوانی بازگشتی نام ارجاع (refname) نیز مشابه است، اما توجه داشته باشید که نام ارجاع ارسالی و بازگردانده شده باید کامل (fully qualified) باشند (مانند b"refs/heads/master" به جای صرفاً b"master" و b"refs/tags/v1\&.0\&.7" به جای b"1\&.0\&.7"): .sp .if n \{\ .RS 4 .\} .nf git\-filter\-repo \-\-refname\-callback \*(Aq # Change e\&.g\&. refs/heads/master to refs/heads/prefix\-master rdir,rpath = os\&.path\&.split(refname) return rdir + b"/prefix\-" + rpath\*(Aq .fi .if n \{\ .RE .\} .sp .sp فراخوانی بازگشتی پیام بسیار شبیه به سه فراخوانی بازگشتی پیشین است، هرچند روی رشته‌ای بایتی عمل می‌کند که احتمالاً بیش از یک خط است: .sp .if n \{\ .RS 4 .\} .nf git\-filter\-repo \-\-message\-callback \*(Aq if b"Signed\-off\-by:" not in message: message += b"\enSigned\-off\-by: Me My " return re\&.sub(b"[Ee]\-?[Mm][Aa][Ii][Ll]", b"email", message)\*(Aq .fi .if n \{\ .RE .\} .sp .sp فراخوانی بازگشتی نام فایل (filename) کمی جالب‌تر است\&. بازگرداندن None به این معنی است که فایل باید از تمام کامیت‌ها حذف شود، بازگرداندن نام فایل به صورت دست‌نخورده نشان‌دهنده نگه‌داشتن فایل است، و بازگرداندن یک نام متفاوت به این معنی است که فایل باید تغییر نام یابد\&. یک مثال: .sp .if n \{\ .RS 4 .\} .nf git\-filter\-repo \-\-filename\-callback \*(Aq if b"/src/" in filename: # Remove all files with a directory named "src" in their path # (except when "src" appears at the toplevel)\&. return None elif filename\&.startswith(b"tools/"): # Rename tools/ \-> scripts/misc/ return b"scripts/misc/" + filename[6:] else: # Keep the filename and do not rename it return filename \*(Aq .fi .if n \{\ .RE .\} .sp .sp فراخوانی بازگشتی اطلاعات فایل (file\-info callback) پیچیده‌تر است\&. این فراخوانی برای مواردی طراحی شده است که فیلترسازی به هر دو مورد نام فایل و محتویات (و احتمالاً حالت دسترسی یا mode) بستگی دارد\&. این تابع برای تغییرات فایل غیر از حذف‌ها فراخوانی می‌شود (زیرا عملیات حذف محتوای فایلی برای کار کردن ندارد)\&. فراخوانی بازگشتی اطلاعات فایل چهار پارامتر دریافت می‌کند (filename، mode، blob_id و value) و انتظار می‌رود سه مقدار را بازگرداند (filename، mode، blob_id)\&. نام فایل به شکلی مشابه با فراخوانی بازگشتی نام فایل مدیریت می‌شود؛ می‌توان از آن برای تغییر نام فایل استفاده کرد (یا برای صرف‌نظر از تغییر، آن را روی None تنظیم نمود)\&. حالت دسترسی (mode) یک رشته بایتی ساده است (b"100644" برای فایل‌های عادی غیرقابل اجرا، b"100755" برای فایل‌ها/اسکریپت‌های قابل اجرا، b"120000" برای پیوندهای نمادین، و b"160000" برای زیرماژول‌ها)\&. پارامتر blob_id بیشترین کاربرد را در کنار پارامتر value دارد\&. پارامتر value نمونه‌ای از کلاسی است که شامل توابع زیر است: value\&.get_contents_by_identifier(blob_id) \(-> contents (bytestring) و value\&.get_size_by_identifier(blob_id) \(-> size_of_blob (int) و value\&.insert_file_with_contents(contents) \(-> blob_id و value\&.is_binary(contents) \(-> bool و value\&.apply_replace_text(contents) \(-> new_contents (bytestring) و دارای داده عضوی زیر است که می‌توانید در آن بنویسید: value\&.data (dict)\&. این توابع به شما امکان می‌دهند محتویات فایل یا اندازه آن را به دست آورید، فایل جدیدی را در جریان ایجاد کنید که blob_id آن را می‌توانید بازگردانید، بررسی کنید که آیا محتویات مشخص‌شده باینری است یا خیر (با استفاده از روش ابتکاری دستور grep(1))، و قوانین جایگزینی از \-\-replace\-text را اعمال کنید (توجه داشته باشید که \-\-file\-info\-callback باعث می‌شود تغییرات حاصل از \-\-replace\-text به‌طور خودکار اعمال نشوند)\&. برای نمونه می‌توانید از این مورد برای اعمال تغییرات از \-\-replace\-text فقط روی انواع خاصی از فایل‌ها و تغییر همزمان نام فایل‌هایی که این تغییرات روی آن‌ها اعمال می‌شود استفاده کنید: .sp .if n \{\ .RS 4 .\} .nf git\-filter\-repo \-\-file\-info\-callback \*(Aq if not filename\&.endswith(b"\&.config"): # Make no changes to the file; return as\-is return (filename, mode, blob_id) new_filename = filename[0:\-7] + b"\&.cfg" contents = value\&.get_contents_by_identifier(blob_id) new_contents = value\&.apply_replace_text(contents) new_blob_id = value\&.insert_file_with_contents(new_contents) return (new_filename, mode, new_blob_id) .fi .if n \{\ .RE .\} .sp .sp توجه داشته باشید که اگر تاریخچه شامل چندین بازنگری با فایل یکسان باشد (برای نمونه در چندین شاخه cherry\-picked شده باشد یا تعدادی revert وجود داشته باشد)، آنگاه \-\-file\-info\-callback چندین بار فراخوانی خواهد شد\&. اگر می‌خواهید از پردازش چندباره یک فایل یکسان جلوگیری کنید، می‌توانید نتایج تبدیل را در دیکشنری value\&.data ذخیره نمایید\&. برای نمونه، می‌توانیم مثال بالا را تغییر دهیم تا تبدیل‌ها را فقط روی blob_idهایی اعمال کند که قبلاً ندیده‌ایم: .sp .if n \{\ .RS 4 .\} .nf git\-filter\-repo \-\-file\-info\-callback \*(Aq if not filename\&.endswith(b"\&.config"): # Make no changes to the file; return as\-is return (filename, mode, blob_id) new_filename = filename[0:\-7] + b"\&.cfg" if blob_id in value\&.data: return (new_filename, mode, value\&.data[blob_id]) contents = value\&.get_contents_by_identifier(blob_id) new_contents = value\&.apply_replace_text(contents) new_blob_id = value\&.insert_file_with_contents(new_contents) value\&.data[blob_id] = new_blob_id return (new_filename, mode, new_blob_id) .fi .if n \{\ .RE .\} .sp .sp یک مثال دیگر برای \-\-file\-info\-callback این است که تمام فایل‌های \&.sh قابل اجرا شوند و یک خط جدید اضافی به انتهای فایل‌های \&.sh افزوده شود: .sp .if n \{\ .RS 4 .\} .nf git\-filter\-repo \-\-file\-info\-callback \*(Aq if not filename\&.endswith(b"\&.sh"): # Make no changes to the file; return as\-is return (filename, mode, blob_id) # There are only 4 valid modes in git: # \- 100644, for regular non\-executable files # \- 100755, for executable files/scripts # \- 120000, for symlinks # \- 160000, for submodules new_mode = b"100755" contents = value\&.get_contents_by_identifier(blob_id) new_contents = contents + b"\en" new_blob_id = value\&.insert_file_with_contents(new_contents) return (filename, new_mode, new_blob_id) .fi .if n \{\ .RE .\} .sp .sp برخلاف انواع فراخوانی‌های بازگشتی پیشین، از فراخوانی‌های بازگشتی blob، reset، tag و commit انتظار نمی‌رود مقداری را بازگردانند، بلکه در عوض انتظار می‌رود شیء ارسال‌شده را اصلاح کنند\&. فیلدهای اصلی برای این اشیاء عبارتند از (مشروط به هشدارهای سازگاری عقبرو API که پیش‌تر ذکر شد): .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Blob: \fBoriginal_id\fR (هش اصلی) و \fBdata\fR .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Reset: \fBref\fR (نام ارجاع) و \fBfrom_ref\fR (هش یا علامت عدد صحیح) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Tag: \fBref\fR، \fBfrom_ref\fR، \fBoriginal_id\fR، \fBtagger_name\fR، \fBtagger_email\fR، \fBtagger_date\fR، \fBmessage\fR .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} Commit: \fBbranch\fR، \fBoriginal_id\fR، \fBauthor_name\fR، \fBauthor_email\fR، \fBauthor_date\fR، \fBcommitter_name\fR، \fBcommitter_email\fR، \fBcommitter_date\fR، \fBmessage\fR، \fBfile_changes\fR (فهرستی از اشیای FileChange، که هر یک شامل یک \fBtype\fR، \fBfilename\fR، \fBmode\fR و \fBblob_id\fR است)، \fBparents\fR (فهرستی از هش‌ها یا علامت‌های عدد صحیح) .RE .sp نمونه‌ای برای هر کدام: .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-blob\-callback \*(Aq if len(blob\&.data) > 25: # Mark this blob for removal from all commits blob\&.skip() else: blob\&.data = blob\&.data\&.replace(b"Hello", b"Goodbye") \*(Aq .fi .if n \{\ .RE .\} .sp .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-reset\-callback \*(Aqreset\&.ref = reset\&.ref\&.replace(b"master", b"dev")\*(Aq .fi .if n \{\ .RE .\} .sp .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-tag\-callback \*(Aq if tag\&.tagger_name == b"Jim Williams": # Omit this tag tag\&.skip() else: tag\&.message = tag\&.message + b"\en\enTag of %s by %s on %s" % (tag\&.ref, tag\&.tagger_email, tag\&.tagger_date)\*(Aq .fi .if n \{\ .RE .\} .sp .sp .if n \{\ .RS 4 .\} .nf git filter\-repo \-\-commit\-callback \*(Aq # Remove executable files with three 6s in their name (including # from leading directories)\&. # Also, undo deletion of sources/foo/bar\&.txt (change types are # either b"D" (deletion) or b"M" (add or modify); renames are # handled by deleting the old file and adding a new one) commit\&.file_changes = [ change for change in commit\&.file_changes if not (change\&.mode == b"100755" and change\&.filename\&.count(b"6") == 3) and not (change\&.type == b"D" and change\&.filename == b"sources/foo/bar\&.txt")] # Mark all \&.sh files as executable; modes in git are always one of # 100644 (normal file), 100755 (executable), 120000 (symlink), or # 160000 (submodule) for change in commit\&.file_changes: if change\&.filename\&.endswith(b"\&.sh"): change\&.mode = b"100755" \*(Aq .fi .if n \{\ .RE .\} .sp .SH "ساختار درونی (INTERNALS)" .sp احتمالاً نیازی به خواندن این بخش ندارید، مگر اینکه بسیار کنجکاو باشید یا بخواهید بازنویسی بسیار پیچیده‌ای در تاریخچه انجام دهید\&. .SS "نحوه کارکرد filter\-repo" .sp به‌طور کلی، filter\-repo با اجرای دستور زیر کار می‌کند .sp .if n \{\ .RS 4 .\} .nf git fast\-export | filter | git fast\-import .fi .if n \{\ .RE .\} .sp .sp که در آن filter\-repo نه تنها کل خط لوله را اجرا می‌کند بلکه به عنوان \fIfilter\fR در میانه نیز عمل می‌نماید\&. با این حال، filter\-repo چند کار اضافی دیگر نیز انجام می‌دهد تا به ابزاری کامل برای فیلترسازی تبدیل شود\&. ترتیبی که با دقت بیشتری آنچه را filter\-repo اجرا می‌کند نشان می‌دهد به شرح زیر است: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} اطمینان از اینکه در یک کلون تازه (fresh clone) هستیم .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} \fBgit fetch \-u \&. refs/remotes/origin/*:refs/heads/*\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} \fBgit remote rm origin\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 4.\h'+01'\c .\} .el \{\ .sp -1 .IP " 4." 4.2 .\} \fBgit fast\-export \-\-show\-original\-ids \-\-reference\-excluded\-parents \-\-fake\-missing\-tagger \-\-signed\-tags=strip \-\-tag\-of\-filtered\-object=rewrite \-\-use\-done\-feature \-\-no\-data \-\-reencode=yes \-\-mark\-tags \-\-all | filter | git \-c core\&.ignorecase=false fast\-import \-\-date\-format=raw\-permissive \-\-force \-\-quiet\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 5.\h'+01'\c .\} .el \{\ .sp -1 .IP " 5." 4.2 .\} \fBgit update\-ref \-\-no\-deref \-\-stdin\fR، همراه با فهرستی از ارجاع‌ها برای حذف کامل، و فهرستی از ارجاع‌های جایگزین برای حذف، ایجاد یا به‌روزرسانی\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 6.\h'+01'\c .\} .el \{\ .sp -1 .IP " 6." 4.2 .\} \fBgit reset \-\-hard\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 7.\h'+01'\c .\} .el \{\ .sp -1 .IP " 7." 4.2 .\} \fBgit reflog expire \-\-expire=now \-\-all\fR .RE .sp .RS 4 .ie n \{\ \h'-04' 8.\h'+01'\c .\} .el \{\ .sp -1 .IP " 8." 4.2 .\} \fBgit gc \-\-prune=now\fR .RE .sp چند نکته یا استثنا درباره هر یک از موارد فوق: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} اگر در یک کلون تازه نباشیم، کاربران در صورت استفاده از دستور اشتباه یا اجرا در مخزن اشتباه قادر به بازیابی نخواهند بود\&. (اگرچه \fB\-\-force\fR این بررسی را نادیده می‌گیرد، و اگر قبلاً یک بار filter\-repo را در این مخزن اجرا کرده باشید نیز این بررسی غیرفعال است\&.) .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} از نظر فنی، ما در واقع از دستور \fBgit update\-ref\fR همراه با ورودی‌های بسیار استفاده می‌کنیم، زیرا کاربران می‌توانند از \fB\-\-force\fR استفاده کنند در حالی که ممکن است شاخه‌های محلی با شاخه‌های دوردست همخوانی نداشته باشند\&. اما این دستور fetch مقصود را به طور مختصرتری بیان می‌کند\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} ما نمی‌خواهیم کاربران به طور تصادفی به مخزن اصلی push کنند، همان‌طور که در بخش موسوم به \(lqبحث (DISCUSSION)\(rq توضیح داده شد\&. همچنین این موضوع به کاربران یادآوری می‌کند که چون تاریخچه بازنویسی شده است، این مخزن دیگر با نسخه اصلی سازگار نیست\&. در نهایت، مزیت جزئی دیگر این است که به کاربران اجازه می‌دهد با گزینه \fB\-\-mirror\fR به مقصد جدید خود push کنند بدون اینکه شاخه‌های ردگیری دوردست به طور تصادفی ارسال شوند\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 4.\h'+01'\c .\} .el \{\ .sp -1 .IP " 4." 4.2 .\} برخی از این فلگ‌ها همیشه استفاده می‌شوند اما برخی دیگر در واقع مشروط هستند\&. برای نمونه، گزینه‌های \fB\-\-replace\-text\fR و \fB\-\-blob\-callback\fR در filter\-repo نیاز دارند که روی blobها کار کنند، بنابراین \fB\-\-no\-data\fR را نمی‌توان به fast\-export فرستاد\&. اما هنگامی که نیازی به کار روی blobها نداریم، ارسال \fB\-\-no\-data\fR سرعت کار را بالا می‌برد\&. همچنین، فلگ‌های دیگر نیز ممکن است ساختار خط لوله را تغییر دهند (مانند \fB\-\-dry\-run\fR و \fB\-\-debug\fR) .RE .sp .RS 4 .ie n \{\ \h'-04' 5.\h'+01'\c .\} .el \{\ .sp -1 .IP " 5." 4.2 .\} ما از این مرحله برای نوشتن ارجاع‌های جایگزین (replace refs) جهت دسترسی به هش‌های کامیت‌های تازه نوشته‌شده با استفاده از نام‌های قبلی‌شان استفاده می‌کنیم\&. همچنین اگر ارجاع‌ها طی مراحل گوناگون تغییر نام یافته باشند، باید نام‌های ارجاع قدیمی را حذف کنیم تا از آمیخته شدن تاریخچه جدید و قدیم جلوگیری شود\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 6.\h'+01'\c .\} .el \{\ .sp -1 .IP " 6." 4.2 .\} کاربران همچنین نسخه‌های قدیمی فایل‌ها را در درخت کاری (working tree) و نمایه (index) خود دارند؛ ما می‌خواهیم آن‌ها نیز پاک‌سازی شوند تا با تاریخچه بازنویسی‌شده مطابقت داشته باشند\&. توجه داشته باشید که این مرحله در مخازن bare نادیده گرفته می‌شود\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 7.\h'+01'\c .\} .el \{\ .sp -1 .IP " 7." 4.2 .\} گزارش‌های ارجاع (Reflogs) تاریخچه قدیمی را نگه می‌دارند، بنابراین باید آن‌ها را منقضی کنیم\&. .RE .sp .RS 4 .ie n \{\ \h'-04' 8.\h'+01'\c .\} .el \{\ .sp -1 .IP " 8." 4.2 .\} ما برای جلوگیری از آمیخته شدن تاریخچه جدید و قدیم نیاز به اجرای gc داریم\&. همچنین حجم مخزن را برای کاربران کاهش می‌دهد تا نیازی به انجام کار اضافی نداشته باشند\&. (احتمال زیاد این است که آن‌ها تنها درخت‌ها و کامیت‌ها و شاید چند blob را بازنویسی کرده باشند، بنابراین \fB\-\-aggressive\fR لازم نیست و بیش از حد کند خواهد بود\&.) .RE .sp اطلاعات مربوط به این مراحل زمانی که \fB\-\-debug\fR به filter\-repo داده شود چاپ می‌شود\&. هنگام انجام بازنویسی تاریخچه با \fB\-\-partial\fR، مراحل ۲، ۳، ۷ و ۸ بدون قید و شرط نادیده گرفته می‌شوند، مرحله ۵ در صورتی که \fB\-\-replace\-refs\fR برابر با \fBupdate\-no\-add\fR باشد نادیده گرفته می‌شود، و تنها بخش nuke\-unused\-refs از مرحله ۵ در صورتی که \fB\-\-replace\-refs\fR مقدار دیگری داشته باشد نادیده گرفته خواهد شد\&. .SS "محدودیت‌ها" .sp .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBمحدودیت‌های به ارث رسیده\fR .RS 4 .sp از آنجا که git filter\-repo برای انجام بخش زیادی از کارهای سنگین، fast\-export و fast\-import را فراخوانی می‌کند، محدودیت‌هایی را از آن سامانه‌ها به ارث می‌برد: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} سرفصل‌های گسترش‌یافته کامیت (extended commit headers)، در صورت وجود، حذف می‌شوند .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} کامیت‌ها بازنویسی می‌شوند که به معنای داشتن هش‌های جدید است؛ بنابراین امضاهای روی کامیت‌ها و برچسب‌ها دیگر نمی‌توانند کار کنند و در عوض صرفاً حذف می‌شوند (در نتیجه برچسب‌های امضاشده به برچسب‌های یادداشت‌دار تبدیل می‌شوند) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} برچسب‌های کامیت‌ها پشتیبانی می‌شوند\&. قبل از git\-2\&.24\&.0، برچسب‌های مربوط به blobها و برچسب‌های مربوط به سایر برچسب‌ها پشتیبانی نمی‌شدند (fast\-export روی چنین برچسب‌هایی متوقف می‌شد)\&. برچسب‌های مربوط به درخت‌ها (trees) در هیچ نسخه‌ای از گیت پشتیبانی نمی‌شوند (زیرا fast\-export برچسب‌های درخت‌ها را با یک هشدار نادیده می‌گیرد و fast\-import هیچ راهی برای وارد کردن آن‌ها ارائه نمی‌دهد)\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} برچسب‌های یادداشت‌دار و امضاشده خارج از فضای نام refs/tags/ پشتیبانی نمی‌شوند (موقعیت آن‌ها به شکل‌های عجیبی به‌هم می‌ریزد) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} ابزار fast\-import روی انواع گوناگون ورودی‌های نامعتبر، مانند منطقه زمانی با بیش از چهار رقم، از کار می‌افتد .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} ابزار fast\-export نمی‌تواند پیام‌های کامیت را در صورتی که پیام کامیت در رمزگذاری مشخص‌شده‌اش معتبر نباشد به UTF\-8 بازکدگذاری کند (در چنین مواردی، پیام کامیت و سرفصل رمزگذاری را دست‌نخورده باقی می‌گذارد)\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} به کامیت‌های فاقد نویسنده (author)، نویسنده‌ای مطابق با کامیت‌کننده (committer) داده می‌شود .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} به برچسب‌های فاقد برچسب‌گذار، یک برچسب‌گذار ساختگی اختصاص داده خواهد شد .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} ارجاع‌هایی که شامل چرخه‌های کامیت (commit cycles) در تاریخچه خود هستند (که می‌توان با \fBgit-replace\fR(1) آن‌ها را ایجاد کرد) به عنوان خطا به کاربر اعلام نمی‌شوند، بلکه بدون سر و صدا توسط fast\-export حذف می‌شوند، درست مانند اینکه شاخه یا برچسب حاوی هیچ فایل جالبی نبوده است .RE .sp همچنین به دلیل طراحی این سامانه‌ها محدودیت‌هایی وجود دارد: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} تلاش برای درج فایل‌های اضافی در جریان (stream) می‌تواند چالش‌برانگیز باشد؛ زیرا fast\-export تغییرات فایل در یک ادغام را تنها نسبت به والد نخست آن فهرست می‌کند، بنابراین اگر فایل‌های اضافی را در کامیتی که در تاریخچه والد دوم (یا سوم یا چهارم) یک ادغام قرار دارد درج کنید، باید آن را به صورت دستی به ادغام نیز بیفزایید\&. (مشابهاً، اگر والدی را که والد نخست در یک کامیت ادغام است تغییر دهید، باید فهرست تغییرات فایل را به صورت دستی به‌روزرسانی کنید تا نسبت به والد نخست جدید تنظیم شود\&.) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} ابزارهای fast\-export و fast\-import با محتویات دقیق فایل‌ها کار می‌کنند، نه با وصله‌ها (patches)\&. (برای نمونه "محتوای فعلی این فایل هرچه باشد، آن را به‌روزرسانی کن تا اکنون این محتویات را داشته باشد") به همین دلیل، حذف تغییرات ایجاد شده در یک کامیت منفرد یا درج تغییرات اضافی در یک فایل در برخی کامیت‌ها و انتظار انتشار آن‌ها به جلو، چیزی نیست که بتوان با این ابزارها انجام داد\&. برای این کار از \fBgit-rebase\fR(1) استفاده کنید\&. .RE .RE .sp .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBمحدودیت‌های ذاتی\fR .RS 4 .sp برخی از انواع فیلترسازی محدودیت‌هایی دارند که بر هر ابزاری که تلاش کند آن‌ها را انجام دهد اثر می‌گذارد؛ بیشترین کاری که هر ابزاری می‌تواند انجام دهد این است که هنگام شناسایی یک مشکل، تلاش کند به کاربر اطلاع دهد: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} هنگام بازنویسی هش‌های کامیت در پیام‌های کامیت، موارد گوناگونی وجود دارد که در آن‌ها هش به‌روزرسانی نخواهد شد (هر زمان که این اتفاق بیفتد، یادداشتی در \fB\&.git/filter\-repo/suboptimal\-issues\fR نوشته می‌شود): .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اگر یک هش کامیت با کامیتی در مخزن قدیمی مطابقت نداشته باشد .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اگر یک هش کامیت با کامیتی مطابقت داشته باشد که هرس (prune) می‌شود .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} اگر یک هش اختصاری یکتا نباشد .RE .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} هرس کردن کامیت‌های خالی می‌تواند باعث شود یک کامیت ادغام یک خط اجدادی کامل را از دست بدهد و به یک کامیت غیرادغامی تبدیل شود\&. اگر کامیت ادغام تغییری نداشته باشد می‌تواند هرس نیز شود، اما اگر همچنان تغییراتی داشته باشد باید نگه داشته شود\&. این ممکن است سردرگمی جزئی ایجاد کند زیرا کامیت احتمالاً پیام کامیتی دارد که آن را شبیه یک کامیت ادغام جلوه می‌دهد، اگرچه دیگر چنین نیست\&. (هر زمان که یک کامیت ادغام به یک کامیت غیرادغامی تبدیل شود، یادداشتی در \fB\&.git/filter\-repo/suboptimal\-issues\fR نوشته می‌شود) .RE .RE .sp .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBمشکلات ویژه filter-repo\fR .RS 4 .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} مخازن متعددی در عمل دیده شده‌اند که از منطقه زمانی ساختگی (\fB+051800\fR) استفاده می‌کنند؛ جستجو در گوگل گزارش‌هایی را به شما نشان خواهد داد\&. منطقه زمانی مورد نظر واضح نبوده یا همیشه یکسان نبوده است\&. با یک منطقه زمانی ساختگی دیگر که fast\-import آن را بپذیرد جایگزین کنید (\fB+0261\fR)\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} گزینه \fB\-\-path\-rename\fR می‌تواند منجر به تداخل نام مسیرها شود؛ برای جلوگیری از مصرف حافظه بیش از حد جهت ردگیری اینکه کدام فایل‌ها در همه کامیت‌ها قرار دارند یا بررسی اینکه چه فایل‌هایی در هر کامیت یا با هر بار استفاده از \-\-path\-rename وجود دارند، ما صرفاً به کاربر اعلام می‌کنیم که اگر مراقب نباشد ممکن است تغییرات دیگر را رونویسی (clobber) کند\&. ما می‌توانیم بدون سربار زیاد بررسی کنیم که آیا این رونویسی از یک \-\-path\-rename دیگر ناشی می‌شود یا خیر\&. (شاید در آینده ارزش داشته باشد که یک حالت آهسته به \-\-path\-rename اضافه شود که بررسی‌های جامع‌تری را انجام دهد؟) .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} هیچ سازوکاری برای کنترل مستقیم اینکه کدام فلگ‌ها به fast\-export (یا fast\-import) فرستاده شوند وجود ندارد؛ تنها فلگ‌های از پیش تعریف‌شده می‌توانند به عنوان یک اثر جانبی ناشی از گزینه‌های دیگر فعال یا غیرفعال شوند\&. کنترل مستقیم چندان منطقی نخواهد بود زیرا برخی گزینه‌ها مانند \fB\-\-full\-tree\fR نیازمند کد اضافی در filter\-repo هستند (برای پردازش دستورالعمل‌های جدید)، و گزینه‌های دیگر مانند \fB\-M\fR یا \fB\-C\fR فرضیات استفاده‌شده در سایر بخش‌های filter\-repo را بر هم می‌زنند\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} فیلترسازی بخشی از مخزن (Partial\-repo filtering)، با اینکه پشتیبانی می‌شود، در تضاد با طراحی «جلوگیری از آمیخته شدن تاریخچه قدیم و جدید» در filter\-repo است\&. این پشتیبانی نیازمند بهبودهایی در هسته گیت نیز بوده است (برای نمونه به گزینه \fB\-\-reference\-excluded\-parents\fR در fast\-export وابسته است که به‌طور خاص برای این کاربرد در filter\-repo افزوده شد)\&. گزینه‌های \fB\-\-partial\fR و \fB\-\-refs\fR همچنان پشتیبانی خواهند شد زیرا افرادی هستند که مواردی برای استفاده از آن‌ها دارند؛ با این حال، نگرانم که این ناسازگاری درباره آمیختن تاریخچه قدیم و جدید احتمالاً به اشتباهات کاربران بینجامد\&. فعلاً، فقط امیدوارم توضیحات طولانی هشدارها در مستندات این گزینه‌ها برای مهار چنین مشکلاتی کافی باشد\&. .RE .RE .sp .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br .ps +1 \fBنکاتی درباره برگشت‌پذیری\fR .RS 4 .sp برخی افراد به برگشت‌پذیری یک بازنویسی علاقه‌مند هستند؛ به عنوان مثال بازنویسی تاریخچه، احتمالاً افزودن چند کامیت، سپس لغو بازنویسی و بازگرداندن تاریخچه اصلی به همراه چند کامیت جدید «بازنویسی‌نشده»\&. بدیهی است در صورتی که بازنویسی شما شامل دور ریختن اطلاعات باشد (مانند فیلتر کردن و حذف فایل‌ها یا جایگزینی چندین رشته متفاوت با \fB***REMOVED***\fR)، این امر غیرممکن است، اما ممکن است با برخی بازنویسی‌ها امکان‌پذیر باشد\&. ابزار filter\-repo احتمالاً به چند دلیل برای این نوع از گردش کار مناسب نخواهد بود: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} بیشتر محدودیت‌های به ارث رسیده از fast\-export و fast\-import از نوعی هستند که باعث بروز مشکلات در برگشت‌پذیری می‌شوند .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} پیوندها (grafts) و ارجاع‌های جایگزین (replace refs)، در صورت وجود، در بازنویسی اعمال شده و دائمی می‌شوند .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} بازنویسی هش‌های کامیت احتمالاً برگشت‌پذیر خواهد بود، اما این امکان وجود دارد که هش‌های اختصاری بازنویسی‌شده یکتا نباشند، حتی اگر هش‌های اختصاری اصلی یکتا بوده باشند\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} ابزار filter\-repo به طور پیش‌فرض اشکال مختلفی از بازنویسی‌های غیرقابل برگشت دارد که ممکن است نیاز داشته باشید آن‌ها را خاموش کنید (مانند دو مورد آخر ذکرشده در بالا یا بازکدگذاری پیام‌های کامیت به UTF\-8)؛ این احتمال وجود دارد که در آینده اشکال دیگری از بازنویسی‌های برگشت‌ناپذیر نیز افزوده شوند\&. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ .sp -1 .IP \(bu 2.3 .\} فرض من این است که افراد از filter\-repo برای تبدیلات یک‌باره استفاده می‌کنند، نه برای انتقال مداوم داده‌ها\&. من صریحاً حق تغییر هرگونه API در filter\-repo را بر اساس این فرض برای خود محفوظ می‌دارم (و یادداشتی با همین مضمون در چندین جای کد و مثال‌ها یافت می‌شود)\&. به شما هشدار داده شد\&. .RE .RE .SH "همچنین ببینید (SEE ALSO)" .sp \fBgit-rebase\fR(1)، \fBgit-filter-branch\fR(1) .SH "گیت (GIT)" .sp بخشی از مجموعه \fBgit\fR(1) .SH "یادداشت‌ها (NOTES)" .IP " 1." 4 مستندات گیت‌لب (GitLab) درباره کاهش حجم مخزن .RS 4 \%https://docs.gitlab.com/ee/user/project/repository/reducing_the_repo_size_using_git.html .RE .IP " 2." 4 بخش "Fully removing the data from GitHub" از مستندات گیت‌هاب (GitHub) .RS 4 \%https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository#fully-removing-the-data-from-github .RE