'\" t .\" Title: git-subtree .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 2026-06-29 .\" Manual: Git Manual .\" Source: Git 2.55.0 .\" Language: English .\" .TH "GIT\-SUBTREE" "1" "2026\-06\-29" "Git 2\&.55\&.0" "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-subtree \- ادغام زیردرخت‌ها با یکدیگر و تقسیم مخزن به زیردرخت‌ها .SH "خلاصه دستور (SYNOPSIS)" .sp .nf \fIgit subtree\fR [] \-P [\-S[]] add \fIgit subtree\fR [] \-P [\-S[]] add \fIgit subtree\fR [] \-P [\-S[]] merge [] \fIgit subtree\fR [] \-P [\-S[]] split [] .fi .sp .sp .nf \fIgit subtree\fR [] \-P [\-S[]] pull \fIgit subtree\fR [] \-P [\-S[]] push .fi .sp .SH "توضیحات (DESCRIPTION)" .sp زیردرخت‌ها (subtrees) اجازه می‌دهند زیرپروژه‌ها در یک زیرپوشه از پروژه اصلی گنجانده شوند، و به صورت اختیاری تمام تاریخچه زیرپروژه را نیز در بر گیرند\&. .sp به عنوان مثال، می‌توانید کد منبع یک کتابخانه را به عنوان یک زیرپوشه از برنامه کاربردی خود اضافه کنید\&. .sp زیردرخت‌ها نباید با زیرماژول‌ها (submodules) که برای هدفی مشابه در نظر گرفته شده‌اند، اشتباه گرفته شوند\&. بر خلاف زیرماژول‌ها، زیردرخت‌ها به هیچ ساختار ویژه‌ای (مانند فایل‌های \fI\&.gitmodules\fR یا gitlinks) در مخزن شما نیاز ندارند و کاربران نهایی مخزن شما را وادار نمی‌کنند کار خاصی انجام دهند یا نحوه کار زیردرخت‌ها را یاد بگیرند\&. یک زیردرخت تنها یک زیرپوشه است که می‌توان مانند هر بخش دیگری از پروژه روی آن کامیت زد، شاخه ایجاد کرد و آن را ادغام نمود\&. .sp همچنین نباید آن‌ها را با استفاده از راهبرد ادغام زیردرخت (subtree merge strategy) اشتباه گرفت\&. تفاوت اصلی در این است که علاوه بر ادغام پروژه دیگر به عنوان یک زیرپوشه، می‌توانید کل تاریخچه یک زیرپوشه را از پروژه خود استخراج کرده و آن را به یک پروژه مستقل تبدیل کنید\&. بر خلاف راهبرد ادغام زیردرخت، می‌توانید به صورت رفت‌وبرگشتی بین این دو عملیات جابه‌جا شوید\&. اگر کتابخانه مستقل به‌روزرسانی شود، می‌توانید به صورت خودکار تغییرات را در پروژه خود ادغام کنید؛ اگر کتابخانه را درون پروژه خود به‌روزرسانی کنید، می‌توانید تغییرات را دوباره تفکیک (split) کرده و مجدداً در پروژه کتابخانه ادغام نمایید\&. .sp برای مثال، اگر کتابخانه‌ای که برای یک برنامه کاربردی ساخته‌اید در جای دیگری نیز مفید واقع شود، می‌توانید کل تاریخچه آن را استخراج کرده و به عنوان مخزن گیت مستقل منتشر کنید، بدون اینکه به اشتباه تاریخچه پروژه اصلی شما با آن آمیخته شود\&. .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 به منظور تمیز نگه داشتن پیام‌های کامیت، توصیه می‌کنیم تا حد امکان کامیت‌های خود را بین زیردرخت‌ها و پروژه اصلی تفکیک کنید\&. به عبارت دیگر، اگر تغییری ایجاد می‌کنید که هم روی کتابخانه و هم روی برنامه اصلی تأثیر می‌گذارد، آن را در دو کامیت جداگانه ثبت کنید\&. به این ترتیب، زمانی که بعداً کامیت‌های کتابخانه را تفکیک می‌کنید، توضیحات آن‌ها همچنان با مفهوم خواهند بود\&. اما اگر این موضوع برای شما اهمیتی ندارد، انجام آن \fBضروری\fR نیست\&. دستور \fIgit subtree\fR به سادگی بخش‌های غیرمرتبط با کتابخانه در کامیت را هنگام تفکیک آن به زیرپروژه نادیده می‌گیرد\&. .sp .5v .RE .SH "دستورها (COMMANDS)" .PP add , add .RS 4 زیردرخت را با وارد کردن محتویات آن از داده‌شده یا از و مشخص‌شده ایجاد می‌کند\&. یک کامیت جدید به صورت خودکار ایجاد می‌شود که تاریخچه پروژه واردشده را با تاریخچه شما پیوند می‌دهد\&. با \fI\-\-squash\fR, به جای کل تاریخچه، تنها یک کامیت منفرد از زیرپروژه وارد می‌شود\&. .RE .PP merge [] .RS 4 تغییرات اخیر تا را در زیردرخت ادغام می‌کند\&. مانند \fIgit merge\fR معمولی، این کار تغییرات محلی خودتان را حذف نمی‌کند؛ بلکه تنها آن تغییرات را با جدیدترین ادغام می‌نماید\&. با \fI\-\-squash\fR, به جای ادغام کل تاریخچه، تنها یک کامیت حاوی تمام تغییرات ایجاد می‌شود\&. .sp اگر از \fI\-\-squash\fR استفاده کنید، جهت ادغام همواره نیازی نیست رو به جلو باشد؛ برای مثال، می‌توانید از این دستور برای بازگشت در زمان از v2\&.5 به v2\&.4 استفاده کنید\&. اگر ادغام شما باعث ایجاد تداخل شود، می‌توانید آن را به روش‌های معمول برطرف کنید\&. .sp هنگام استفاده از \fI\-\-squash\fR, اگر ادغام قبلی با \fI\-\-squash\fR یک برچسب نشانه‌دار (annotated tag) از مخزن زیردرخت را ادغام کرده باشد، آن برچسب باید به صورت محلی در دسترس باشد\&. اگر داده شود، برچسب مفقود به صورت خودکار از آن مخزن واکشی خواهد شد\&. .RE .PP split [] [] .RS 4 یک تاریخچه جدید و مصنوعی از تاریخچه زیردرخت در یا در صورت مشخص نشدن از HEAD استخراج می‌کند\&. تاریخچه جدید فقط شامل کامیت‌هایی (شامل ادغام‌ها) است که روی تأثیر داشته‌اند، و هر یک از این کامیت‌ها اکنون محتویات را به جای یک زیرپوشه، در ریشه پروژه قرار می‌دهند\&. بدین ترتیب، تاریخچه جدید ایجادشده برای صدور به عنوان یک مخزن گیت مستقل مناسب خواهد بود\&. .sp پس از تفکیک موفق، یک شناسه کامیت منفرد در خروجی استاندارد چاپ می‌شود\&. این شناسه متناظر با HEAD درخت ایجادشده جدید است که می‌توانید آن را به هر نحو دلخواه مدیریت کنید\&. .sp تفکیک‌های مکرر بر روی دقیقاً همان تاریخچه تضمین می‌شود که یکسان باشند (یعنی شناسه‌های کامیت یکسانی تولید کنند) تا زمانی که تنظیمات ارائه‌شده به \fIsplit\fR (مانند \fI\-\-annotate\fR) یکسان باشند\&. به همین دلیل، اگر کامیت‌های جدیدی اضافه کنید و مجدداً تفکیک نمایید، کامیت‌های جدید به عنوان کامیت‌هایی روی تاریخچه تولیدشده قبلی پیوست می‌شوند، بنابراین \fIgit merge\fR و دستورهای مرتبط همان‌طور که انتظار می‌رود کار خواهند کرد\&. .sp هنگامی که یک ادغام قبلی با \fI\-\-squash\fR یک برچسب نشانه‌دار از مخزن زیردرخت را ادغام کرده باشد، آن برچسب باید به صورت محلی در دسترس باشد\&. اگر مشخص شده باشد، برچسب مفقود به صورت خودکار از آن مخزن دریافت خواهد شد\&. .RE .PP pull .RS 4 دقیقاً مشابه \fImerge\fR عمل می‌کند، اما مانند \fIgit pull\fR ارجاع داده‌شده را از مخزن ریموت مشخص‌شده واکشی می‌نماید\&. .RE .PP push [+][:] .RS 4 یک عملیات \fIsplit\fR را با استفاده از زیردرخت در اجرا می‌کند و سپس با اجرای \fIgit push\fR نتیجه را به و ارسال می‌نماید\&. از این قابلیت می‌توان برای ارسال زیردرخت خود به شاخه‌های مختلف مخزن ریموت استفاده کرد\&. دقیقاً همانند \fIsplit\fR, اگر داده نشود، از HEAD استفاده می‌شود\&. علامت ابتدایی و اختیاری \fI+\fR نادیده گرفته می‌شود\&. .RE .SH "گزینه‌ها برای همه دستورها (OPTIONS FOR ALL COMMANDS)" .PP \-q, \-\-quiet .RS 4 پیام‌های خروجی غیرضروری را در stderr سرکوب می‌کند\&. .RE .PP \-d, \-\-debug .RS 4 پیام‌های خروجی خطایابی بیشتری را در stderr تولید می‌کند\&. .RE .PP \-P , \-\-prefix= .RS 4 مسیر زیردرخت مورد نظر را در مخزن مشخص می‌کند\&. این گزینه برای تمامی دستورها الزامی است\&. .RE .PP \-S[], \-\-gpg\-sign[=], \-\-no\-gpg\-sign .RS 4 کامیت‌ها را با GPG امضا می‌کند\&. آرگومان keyid اختیاری است و به طور پیش‌فرض از هویت ثبت‌کننده کامیت استفاده می‌شود؛ \-\-no\-gpg\-sign برای لغو گزینه \-\-gpg\-sign که قبلاً در خط فرمان داده شده، کاربرد دارد\&. .RE .SH "گزینه‌ها برای ADD و MERGE (همچنین: PULL، SPLIT \-\-REJOIN، و PUSH \-\-REJOIN)" .sp این گزینه‌ها برای \fIadd\fR و \fImerge\fR همچنین می‌توانند به \fIpull\fR (که \fImerge\fR را پوشش می‌دهد)، \fIsplit \-\-rejoin\fR (که بسته به مورد \fIadd\fR یا \fImerge\fR را پوشش می‌دهد)، و \fIpush \-\-rejoin\fR (که \fIsplit \-\-rejoin\fR را پوشش می‌دهد) داده شوند\&. .PP \-\-squash .RS 4 به جای ادغام کل تاریخچه از پروژه زیردرخت، تنها یک کامیت منفرد حاوی تمام تغییراتی که می‌خواهید ادغام شوند ایجاد می‌کند و سپس آن کامیت جدید را در پروژه شما ادغام می‌نماید\&. .sp استفاده از این گزینه به کاهش شلوغی گزارش تاریخچه (log) کمک می‌کند\&. کاربران به ندرت می‌خواهند همه تغییراتی را که بین نسخه v1\&.0 و v1\&.1 کتابخانه رخ داده است ببینند، زیرا هیچ‌یک از نسخه‌های میانی هرگز در برنامه آن‌ها گنجانده نشده است\&. .sp استفاده از \fI\-\-squash\fR همچنین به جلوگیری از مشکلاتی کمک می‌کند که در آن‌ها یک زیرپروژه یکسان چندین بار در یک پروژه اضافه شده یا حذف و مجدداً اضافه می‌شود\&. در چنین حالتی، ترکیب تاریخچه‌ها در هر صورت منطقی نیست، زیرا مشخص نیست کدام بخش از تاریخچه به کدام زیردرخت تعلق دارد\&. .sp علاوه بر این، با \fI\-\-squash\fR, می‌توانید بین نسخه‌های مختلف یک زیردرخت به جلو و عقب جابه‌جا شوید، نه صرفاً رو به جلو\&. دستور \fIgit subtree merge \-\-squash\fR همیشه زیردرخت را دقیقاً مطابق با کامیت مشخص‌شده تنظیم می‌کند، حتی اگر رسیدن به آن کامیت مستلزم بازگرداندن تغییراتی باشد که قبلاً اضافه شده بودند\&. .sp چه از \fI\-\-squash\fR استفاده کنید یا خیر، تغییرات ایجادشده در مخزن محلی شما دست‌نخورده باقی می‌مانند و می‌توان بعداً آن‌ها را تفکیک کرده و به بالادست به زیرپروژه ارسال نمود\&. .RE .PP \-m , \-\-message= .RS 4 مقدار را به عنوان پیام کامیت برای کامیت ادغام مشخص می‌کند\&. .RE .SH "گزینه‌ها برای SPLIT (همچنین: PUSH)" .sp این گزینه‌ها برای \fIsplit\fR همچنین می‌توانند به \fIpush\fR (که \fIsplit\fR را پوشش می‌دهد) داده شوند\&. .PP \-\-annotate= .RS 4 هنگام ایجاد تاریخچه ترکیبی، عبارت را به عنوان پیشوند به هر پیام کامیت اضافه می‌کند\&. از آنجا که ما کامیت‌های جدیدی با همان پیام کامیت اما احتمالاً با محتوای متفاوت نسبت به کامیت‌های اصلی ایجاد می‌کنیم، این گزینه می‌تواند به تفکیک آن‌ها و جلوگیری از سردرگمی کمک کند\&. .sp هر بار که عملیات تفکیک را انجام می‌دهید، باید از همان یکسان استفاده کنید؛ در غیر این صورت تضمینی وجود ندارد که تاریخچه بازتولیدشده جدید با تاریخچه قبلی یکسان باشد\&. این موضوع مانع از کارکرد صحیح عملیات ادغام خواهد شد\&. ابزار git subtree تلاش می‌کند تا در هر صورت کار را پیش ببرد، به ویژه اگر از \fI\-\-rejoin\fR استفاده کنید، اما ممکن است همیشه کارساز نباشد\&. .RE .PP \-b , \-\-branch= .RS 4 پس از ایجاد تاریخچه ترکیبی، شاخه جدیدی به نام حاوی تاریخچه جدید ایجاد می‌کند\&. این شاخه برای ارسال مستقیم و فوری به بالادست مناسب است\&. شاخه نباید از قبل وجود داشته باشد\&. .RE .PP \-\-ignore\-joins .RS 4 اگر از \fI\-\-rejoin\fR استفاده کنید، git subtree تلاش می‌کند بازسازی تاریخچه خود را بهینه‌سازی کند تا فقط کامیت‌های جدید پس از آخرین \fI\-\-rejoin\fR تولید شوند\&. \fI\-\-ignore\-joins\fR این رفتار را غیرفعال کرده و آن را مجبور می‌کند کل تاریخچه را دوباره تولید نماید\&. در یک پروژه بزرگ، این کار ممکن است زمان زیادی ببرد\&. .RE .PP \-\-onto= .RS 4 اگر زیردرخت شما در ابتدا با روشی غیر از git subtree وارد شده باشد، ممکن است تاریخچه آن با آنچه git subtree انتظار دارد مطابقت نداشته باشد\&. در این حالت، می‌توانید شناسه کامیت را که متناظر با اولین بازبینی واردشده از تاریخچه زیرپروژه به پروژه شماست مشخص کنید، و git subtree تلاش خواهد کرد تاریخچه خود را از آن نقطه بسازد\&. .sp اگر از \fIgit subtree add\fR استفاده کرده‌اید، هرگز به این گزینه نیاز نخواهید داشت\&. .RE .PP \-\-rejoin .RS 4 پس از تفکیک، تاریخچه ترکیبی جدید ایجادشده را دوباره در پروژه اصلی شما ادغام می‌کند\&. به این ترتیب، تفکیک‌های بعدی می‌توانند فقط بخشی از تاریخچه را جستجو کنند که پس از جدیدترین \fI\-\-rejoin\fR اضافه شده است\&. .sp اگر کامیت‌های تفکیک‌شده شما در نهایت در زیرپروژه بالادست ادغام شوند و سپس بخواهید آخرین نسخه بالادست را دریافت کنید، این امر به الگوریتم ادغام گیت اجازه می‌دهد هوشمندانه‌تر از تداخل‌ها جلوگیری کند (چرا که می‌داند این کامیت‌های ترکیبی از قبل بخشی از مخزن بالادست هستند)\&. .sp متأسفانه، استفاده از این گزینه باعث می‌شود \fIgit log\fR یک نسخه اضافی از هر کامیت جدید ایجادشده (نسخه اصلی و نسخه ترکیبی) را نمایش دهد\&. .sp اگر تمام ادغام‌های خود را با \fI\-\-squash\fR انجام می‌دهید، مطمئن شوید که هنگام اجرای \fIsplit \-\-rejoin\fR نیز از \fI\-\-squash\fR استفاده می‌کنید\&. .RE .SH "مثال ۱\&. دستور ADD" .sp فرض کنید یک مخزن محلی دارید و می‌خواهید یک کتابخانه خارجی را به آن اضافه کنید\&. در این مثال، مخزن git\-subtree را به عنوان یک زیرپوشه از مخزن موجود git\-extensions در مسیر ~/git\-extensions/ اضافه می‌کنیم: .sp .if n \{\ .RS 4 .\} .nf $ git subtree add \-\-prefix=git\-subtree \-\-squash \e git://github\&.com/apenwarr/git\-subtree\&.git master .fi .if n \{\ .RE .\} .sp عبارت \fImaster\fR باید یک ارجاع ریموت معتبر باشد و می‌تواند نام شاخه دیگری باشد\&. .sp می‌توانید از پرچم \fI\-\-squash\fR صرف‌نظر کنید، اما انجام این کار تعداد کامیت‌های موجود در مخزن محلی شما را افزایش می‌دهد\&. .sp اکنون در مخزن git\-extensions خود، یک پوشه ~/git\-extensions/git\-subtree داریم که حاوی کدهای شاخه master از git://github\&.com/apenwarr/git\-subtree\&.git است\&. .SH "مثال ۲\&. استخراج یک زیردرخت با استفاده از COMMIT، MERGE و PULL" .sp بیایید از مخزن کد منبع git به عنوان مثال استفاده کنیم\&. ابتدا، نسخه خود را از مخزن git\&.git دریافت کنید: .sp .if n \{\ .RS 4 .\} .nf $ git clone git://git\&.kernel\&.org/pub/scm/git/git\&.git test\-git $ cd test\-git .fi .if n \{\ .RE .\} .sp ابزار gitweb (کامیت 1130ef3) از زمان کامیت 0a8f4f0 در git ادغام شد و پس از آن دیگر به طور مستقل نگهداری نشد\&. اما فرض کنید که به طور مستقل نگهداری می‌شد و ما می‌خواستیم تغییرات گیت در gitweb را از آن زمان به بعد استخراج کنیم تا با پروژه بالادست به اشتراک بگذاریم\&. می‌توانید این کار را انجام دهید: .sp .if n \{\ .RS 4 .\} .nf $ git subtree split \-\-prefix=gitweb \-\-annotate=\*(Aq(split) \*(Aq \e 0a8f4f0^\&.\&. \-\-onto=1130ef3 \-\-rejoin \e \-\-branch gitweb\-latest $ gitk gitweb\-latest $ git push git@github\&.com:whatever/gitweb\&.git gitweb\-latest:master .fi .if n \{\ .RE .\} .sp (ما از \fI0a8f4f0^\&.\&.\fR استفاده می‌کنیم زیرا به معنای «تمام تغییرات از 0a8f4f0 تا نسخه فعلی، شامل خود 0a8f4f0» است\&.) .sp اگر gitweb در ابتدا با استفاده از \fIgit subtree add\fR ادغام شده بود (یا یک تفکیک قبلی با مشخص کردن \fI\-\-rejoin\fR انجام شده بود)، آن‌گاه می‌توانستید تمام تفکیک‌های خود را بدون نیاز به به خاطر سپردن شناسه‌های نامتعارف کامیت انجام دهید: .sp .if n \{\ .RS 4 .\} .nf $ git subtree split \-\-prefix=gitweb \-\-annotate=\*(Aq(split) \*(Aq \-\-rejoin \e \-\-branch gitweb\-latest2 .fi .if n \{\ .RE .\} .sp و می‌توانید تغییرات را به همان سادگی از پروژه بالادستی ادغام کنید: .sp .if n \{\ .RS 4 .\} .nf $ git subtree pull \-\-prefix=gitweb \e git@github\&.com:whatever/gitweb\&.git master .fi .if n \{\ .RE .\} .sp یا با استفاده از \fI\-\-squash\fR، می‌توانید در واقع به نسخه قبلی gitweb برگردید: .sp .if n \{\ .RS 4 .\} .nf $ git subtree merge \-\-prefix=gitweb \-\-squash gitweb\-latest~10 .fi .if n \{\ .RE .\} .sp سپس تغییراتی اعمال کنید: .sp .if n \{\ .RS 4 .\} .nf $ date >gitweb/myfile $ git add gitweb/myfile $ git commit \-m \*(Aqcreated myfile\*(Aq .fi .if n \{\ .RE .\} .sp و دوباره به جلو حرکت سریع (fast-forward) انجام دهید: .sp .if n \{\ .RS 4 .\} .nf $ git subtree merge \-\-prefix=gitweb \-\-squash gitweb\-latest .fi .if n \{\ .RE .\} .sp و مشاهده کنید که تغییرات شما همچنان دست‌نخورده باقی مانده است: .sp .if n \{\ .RS 4 .\} .nf $ ls \-l gitweb/myfile .fi .if n \{\ .RE .\} .sp و می‌توانید آن را تفکیک کرده و تغییرات خود را نسبت به gitweb استاندارد مشاهده کنید: .sp .if n \{\ .RS 4 .\} .nf git log gitweb\-latest\&.\&.$(git subtree split \-\-prefix=gitweb) .fi .if n \{\ .RE .\} .SH "مثال ۳\&. استخراج یک زیردرخت با استفاده از یک شاخه" .sp فرض کنید یک دایرکتوری سورس با فایل‌ها و زیرپوشه‌های فراوان دارید و می‌خواهید دایرکتوری lib را به پروژه گیت مستقل خود تبدیل کنید\&. روش سریعی برای انجام این کار در ادامه آورده شده است: .sp ابتدا، مخزن جدید را در هر مکانی که می‌خواهید ایجاد کنید: .sp .if n \{\ .RS 4 .\} .nf $ $ git init \-\-bare .fi .if n \{\ .RE .\} .sp بازگشت به دایرکتوری اصلی شما: .sp .if n \{\ .RS 4 .\} .nf $ git subtree split \-\-prefix=lib \-\-annotate="(split)" \-b split .fi .if n \{\ .RE .\} .sp سپس شاخه جدید را به مخزن خالی جدید ارسال کنید: .sp .if n \{\ .RS 4 .\} .nf $ git push split:master .fi .if n \{\ .RE .\} .SH "نویسنده (AUTHOR)" .sp نوشته‌شده توسط Avery Pennarun <\m[blue]\fBapenwarr@gmail\&.com\fR\m[]\&\s-2\u[1]\d\s+2> .SH "GIT" .sp بخشی از مجموعه \fBgit\fR(1) .SH "نکات (NOTES)" .IP " 1." 4 apenwarr@gmail.com .RS 4 \%mailto:apenwarr@gmail.com .RE