GIT-READ-TREE(1) دستورات عمومی کاربر GIT-READ-TREE(1)

git-read-tree - خواندن اطلاعات درخت به درون شاخص

git read-tree [(-[--rivial] [--ggressive] | --eset | --refix=<prefix>)
                [-u | -i]] [--index-output=<file>] [--0-sparse-checkout]
                (--\mpty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])

اطلاعات درخت داده‌شده توسط <tree-ish> را به درون شاخص (index) می‌خواند، اما در عمل هیچ‌یک از فایل‌هایی را که "کَش" می‌کند به‌روزرسانی نمی‌کند. (ببینید: git-checkout-index(1))

به‌صورت اختیاری، می‌تواند با پرچم -m یک درخت را در شاخص ادغام کند، یک ادغام روبه‌جلو (یعنی ۲-طرفه) انجام دهد، یا یک ادغام ۳-طرفه را به سرانجام برساند. هنگامی که همراه با -m استفاده شود، پرچم -u باعث می‌شود فایل‌های موجود در درخت کاری (work tree) نیز با نتیجه ادغام به‌روزرسانی شوند.

تنها ادغام‌های بدیهی (trivial merges) توسط خود git read-tree انجام می‌شوند. هنگامی که git read-tree بازمی‌گردد، تنها مسیرهای دارای تداخل در وضعیت ادغام‌نشده (unmerged) باقی خواهند ماند.

-m

انجام یک ادغام و نه صرفاً یک خواندن ساده. در صورتی که فایل شاخص شما دارای مدخل‌های ادغام‌نشده باشد (که نشان‌دهنده عدم اتمام ادغام قبلی است که شروع کرده‌اید)، دستور از اجرا خودداری خواهد کرد.

--eset

مشابه -m، به جز اینکه مدخل‌های ادغام‌نشده به‌جای شکست عملیات دور ریخته می‌شوند. هنگامی که همراه با -u استفاده شود، به‌روزرسانی‌هایی که منجر به از دست رفتن تغییرات درخت کاری یا فایل‌ها یا پوشه‌های ردیابی‌نشده می‌شوند، عملیات را متوقف نخواهند کرد.

-u

پس از یک ادغام موفقیت‌آمیز، فایل‌های موجود در درخت کاری را با نتیجه ادغام به‌روزرسانی می‌کند.

-i

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

-n, --ry-run

بررسی می‌کند که آیا دستور با خطا مواجه می‌شود یا خیر، بدون اینکه شاخص یا فایل‌های موجود در درخت کاری را در عمل به‌روزرسانی کند.

-v

نمایش پیشرفت واکشی و استخراج فایل‌ها.

--rivial

ادغام سه‌طرفه توسط git read-tree را محدود می‌کند تا تنها در صورتی انجام شود که هیچ ادغامی در سطح فایل لازم نباشد، به‌جای اینکه موارد بدیهی را حل کرده و فایل‌های متداخل را در شاخص حل‌نشده باقی بگذارد.

--ggressive

معمولاً یک ادغام سه‌طرفه توسط git read-tree ادغام را برای موارد واقعاً بدیهی حل می‌کند و سایر موارد را در شاخص حل‌نشده رها می‌سازد تا رابط‌های کاربری (porcelains) بتوانند سیاست‌های ادغام متفاوتی را پیاده‌سازی کنند. این پرچم باعث می‌شود که دستور چند مورد دیگر را نیز به‌صورت داخلی حل کند:
•هنگامی که یک طرف مسیری را حذف می‌کند و طرف دیگر مسیر را بدون تغییر باقی می‌گذارد. راه‌حل حذف آن مسیر است.
•هنگامی که هر دو طرف مسیری را حذف می‌کنند. راه‌حل حذف آن مسیر است.
•هنگامی که هر دو طرف مسیری را به‌صورت یکسان اضافه می‌کنند. راه‌حل افزودن آن مسیر است.

--refix=<prefix>

محتویات شاخص فعلی را حفظ کرده و محتویات tree-ish نام‌برده را زیر پوشه‌ای در <prefix> می‌خواند. دستور از بازنویسی مدخل‌هایی که از قبل در فایل شاخص اصلی وجود داشته‌اند خودداری خواهد کرد.

--index-output=<file>

به‌جای نوشتن نتایج در $GIT_INDEX_FILE، شاخص حاصل را در فایل نام‌برده می‌نویسد. در حین اجرای دستور، فایل شاخص اصلی با همان سازوکار معمول قفل می‌شود. فایل باید اجازه تغییر نام (rename(2)) از یک فایل موقت که در کنار فایل شاخص معمول ایجاد می‌شود را داشته باشد؛ معمولاً این بدان معنی است که باید روی همان فایل‌سیستمی باشد که خود فایل شاخص در آن قرار دارد، و شما به پوشه‌هایی که فایل شاخص و فایل خروجی شاخص در آن‌ها قرار دارند دسترسی نوشتن داشته باشید.

--ecurse-submodules, --0-recurse-submodules

استفاده از --ecurse-submodules محتوای تمام زیرماژول‌های فعال را مطابق با کامیت ثبت‌شده در ابرپروژه (superproject) با فراخوانی بازگشتی read-tree به‌روزرسانی می‌کند، و همچنین HEAD زیرماژول‌ها را روی آن کامیت به‌صورت جداشده (detached) تنظیم می‌نماید.

--0-sparse-checkout

غیرفعال‌سازی پشتیبانی از دریافت پراکنده (sparse checkout) حتی اگر core.sparseCheckout برابر با true باشد.

--\mpty

به‌جای خواندن شیء(های) درخت به درون شاخص، صرفاً آن را خالی می‌کند.

-q, --quiet

حالت بی‌صدا، پیام‌های بازخورد را پنهان می‌کند.

<tree-ish#>

شناسه شیء(های) درختی که قرار است خوانده یا ادغام شوند.

اگر -m مشخص شده باشد، git read-tree می‌تواند ۳ نوع ادغام انجام دهد: ادغام تک‌درختی در صورتی که فقط ۱ درخت داده شده باشد، ادغام روبه‌جلو با ۲ درخت، یا یک ادغام ۳-طرفه در صورتی که ۳ یا چند درخت ارائه شده باشد.

اگر تنها ۱ درخت مشخص شود، git read-tree به‌گونه‌ای عمل می‌کند که گویی کاربر -m را مشخص نکرده است، به جز اینکه اگر شاخص اصلی دارای مدخلی برای یک نام‌مسیر داده‌شده باشد، و محتویات مسیر با درخت در حال خوانده‌شدن مطابقت داشته باشد، از اطلاعات stat شاخص استفاده می‌شود. (به عبارت دیگر، اطلاعات stat() شاخص بر درخت ادغام‌شده اولویت دارد).

این بدان معناست که اگر شما دستور git read-tree -m <newtree> را اجرا کنید و به دنبال آن git checkout-index -f -u -a را فراخوانی نمایید، دستور git checkout-index تنها مواردی را استخراج می‌کند که واقعاً تغییر کرده‌اند.

این امر برای جلوگیری از هشدارهای نادرست غیرضروری هنگام اجرای git diff-files پس از git read-tree استفاده می‌شود.

معمولاً این دستور به‌صورت git read-tree -m $H $M فراخوانی می‌شود، که در آن H$ کامیت head مخزن فعلی است، و M$ سربرگ یک درخت بیگانه است که صرفاً جلوتر از H$ قرار دارد (یعنی ما در یک وضعیت ادغام روبه‌جلو یا fast-forward هستیم).

هنگامی که دو درخت مشخص می‌شوند، کاربر موارد زیر را به git read-tree می‌گوید:

1.شاخص فعلی و درخت کاری از H$ مشتق شده‌اند، اما کاربر ممکن است تغییرات محلی پس از H$ در آن‌ها داشته باشد.
2.کاربر می‌خواهد به M$ پیشروی سریع (fast-forward) کند.

در این حالت، دستور git read-tree -m $H $M اطمینان حاصل می‌کند که هیچ تغییر محلی در نتیجه این "ادغام" از بین نرود. در اینجا قوانین "انتقال به جلو" آورده شده است، که در آن "I" نشان‌دهنده شاخص است، "clean" به این معنی است که شاخص و درخت کاری یکسان هستند، و "exists"/"nothing" به حضور یک مسیر در کامیت مشخص‌شده اشاره دارد:

   I                   H        M        Result
  -------------------------------------------------------
0  nothing             nothing  nothing  (does not happen)
1  nothing             nothing  exists   use M
2  nothing             exists   nothing  remove path from index
3  nothing             exists   exists,  use M if "initial checkout",
                                H == M   keep index otherwise
                                exists,  fail
                                H != M
   clean I==H  I==M
  ------------------
4  yes   N/A   N/A     nothing  nothing  keep index
5  no    N/A   N/A     nothing  nothing  keep index
6  yes   N/A   yes     nothing  exists   keep index
7  no    N/A   yes     nothing  exists   keep index
8  yes   N/A   no      nothing  exists   fail
9  no    N/A   no      nothing  exists   fail
10 yes   yes   N/A     exists   nothing  remove path from index
11 no    yes   N/A     exists   nothing  fail
12 yes   no    N/A     exists   nothing  fail
13 no    no    N/A     exists   nothing  fail
   clean (H==M)
  ------
14 yes                 exists   exists   keep index
15 no                  exists   exists   keep index
   clean I==H  I==M (H!=M)
  ------------------
16 yes   no    no      exists   exists   fail
17 no    no    no      exists   exists   fail
18 yes   no    yes     exists   exists   keep index
19 no    no    yes     exists   exists   keep index
20 yes   yes   no      exists   exists   use M
21 no    yes   no      exists   exists   fail

در تمام موارد "keep index"، مدخل شاخص همانند فایل شاخص اصلی باقی می‌ماند. اگر مدخل به‌روز نباشد، git read-tree در حین کار با پرچم u-، کپی موجود در درخت کاری را دست‌نخورده نگه می‌دارد.

هنگامی که این فرم از git read-tree با موفقیت بازمی‌گردد، می‌توانید با اجرای git diff-index --ached $M ببینید کدام یک از "تغییرات محلی" شما به جلو منتقل شده‌اند. توجه داشته باشید که این لزوماً با آنچه git diff-index --ached $H قبل از چنین ادغام دو درختی تولید می‌کرد مطابقت ندارد. این به دلیل موارد ۱۸ و ۱۹ است — اگر قبلاً تغییرات موجود در M$ را داشتید (مثلاً شاید آن را از طریق ایمیل در قالب یک وصله دریافت کرده‌اید)، دستور git diff-index --ached $H پیش از این ادغام شما را از تغییر آگاه می‌کرد، اما در خروجی git diff-index --ached $M پس از ادغام دو درختی نمایش داده نخواهد شد.

مورد ۳ کمی پیچیده است و نیاز به توضیح دارد. نتیجه این قاعده از نظر منطقی باید حذف مسیر باشد اگر کاربر حذف مسیر را در مرحله صحنه‌بندی (stage) قرار داده و سپس به یک شاخه جدید تغییر وضعیت دهد. با این حال این امر مانع از استخراج اولیه می‌شود، بنابراین این قاعده اصلاح شده است تا تنها زمانی از M (درخت جدید) استفاده کند که محتوای شاخص خالی باشد. در غیر این صورت، حذف مسیر تا زمانی که H$ و M$ یکسان باشند حفظ می‌شود.

هر مدخل "شاخص" دارای دو بیت وضعیت "مرحله" (stage) است. مرحله ۰ مرحله معمولی است و تنها مرحله‌ای است که در هر نوع استفاده عادی مشاهده می‌کنید.

با این حال، هنگامی که git read-tree را با سه درخت اجرا می‌کنید، "مرحله" از ۱ شروع می‌شود.

این بدان معناست که می‌توانید دستور زیر را اجرا کنید:

$ git read-tree -m <tree1> <tree2> <tree3>

و در نهایت با یک شاخص مواجه خواهید شد که تمام مدخل‌های <tree1> در "stage1"، تمام مدخل‌های <tree2> در "stage2" و تمام مدخل‌های <tree3> در "stage3" قرار دارند. هنگام انجام ادغام یک شاخه دیگر در شاخه فعلی، ما از درخت جد مشترک به عنوان <tree1>، سربرگ شاخه فعلی به عنوان <tree2>، و سربرگ شاخه دیگر به عنوان <tree3> استفاده می‌کنیم.

علاوه بر این، git read-tree دارای منطق حالت خاصی است که می‌گوید: اگر فایلی را مشاهده کردید که در تمام جنبه‌ها در حالت‌های زیر مطابقت دارد، به حالت "stage0" برمی‌گردد و جمع می‌شود:

•مرحله ۲ و ۳ یکسان هستند؛ یکی یا دیگری را در نظر بگیرید (تفاوتی ندارد - کار یکسانی روی شاخه ما در مرحله ۲ و شاخه آن‌ها در مرحله ۳ انجام شده است)
•مرحله ۱ و ۲ یکسان هستند و مرحله ۳ متفاوت است؛ مرحله ۳ را در نظر بگیرید (شاخه ما در مرحله ۲ کاری پس از جد مشترک در مرحله ۱ انجام نداده در حالی که شاخه آن‌ها در مرحله ۳ روی آن کار کرده است)
•مرحله ۱ و ۳ یکسان هستند و مرحله ۲ متفاوت است؛ مرحله ۲ را در نظر بگیرید (ما کاری انجام داده‌ایم در حالی که آن‌ها کاری نکرده‌اند)

دستور git write-tree از نوشتن یک درخت بی‌معنی خودداری می‌کند، و اگر حتی یک مدخل پیدا کند که در مرحله ۰ نباشد، در مورد مدخل‌های ادغام‌نشده هشدار می‌دهد و متوقف می‌شود.

خوب، این‌ها همه شبیه به مجموعه‌ای از قوانین کاملاً گیج‌کننده به نظر می‌رسند، اما در واقع دقیقاً همان چیزی هستند که برای انجام یک ادغام سریع می‌خواهید. مراحل مختلف نشان‌دهنده "درخت نتیجه" (مرحله ۰، یا "merged")، درخت اصلی (مرحله ۱، یا "orig")، و دو درختی هستند که در تلاش برای ادغام آن‌ها هستید (به ترتیب مرحله ۲ و ۳).

ترتیب مراحل ۱، ۲ و ۳ (و در نتیجه ترتیب سه آرگومان خط فرمان <tree-ish>) زمانی اهمیت دارد که ادغام ۳-طرفه را با یک فایل شاخصی که از قبل پر شده است آغاز کنید. در اینجا خلاصه‌ای از نحوه عملکرد این الگوریتم آمده است:

•اگر فایلی در قالبی یکسان در هر سه درخت وجود داشته باشد، به‌طور خودکار توسط git read-tree به وضعیت "merged" تغییر حالت می‌دهد.
•فایلی که هرگونه تفاوتی در سه درخت داشته باشد، به عنوان مدخل‌های جداگانه در شاخص باقی می‌ماند. این بر عهده "سیاست رابط کاربری" (porcelain policy) است که تعیین کند چگونه مراحل غیر صفر حذف شده و یک نسخه ادغام‌شده درج شود.
•فایل شاخص با تمام این اطلاعات ذخیره و بازیابی می‌شود، بنابراین می‌توانید موارد را به‌صورت افزایشی ادغام کنید، اما تا زمانی که دارای مدخل‌هایی در مراحل ۱/۲/۳ باشد (یعنی "مدخل‌های ادغام‌نشده")، نمی‌توانید نتیجه را بنویسید. بنابراین اکنون الگوریتم ادغام بسیار ساده خواهد بود:
•شاخص را به ترتیب پیمایش می‌کنید و تمام مدخل‌های مرحله ۰ را نادیده می‌گیرید، زیرا قبلاً پردازش شده‌اند.
•اگر یک "stage1" پیدا کردید، اما هیچ "stage2" یا "stage3" منطبقی وجود نداشت، می‌دانید که از هر دو درخت حذف شده است (فقط در درخت اصلی وجود داشته) و آن مدخل را حذف می‌کنید.
•اگر درخت "stage2" و "stage3" منطبق پیدا کردید، یکی از آن‌ها را حذف کرده و دیگری را به یک مدخل "stage0" تبدیل می‌کنید. هر مدخل منطبق "stage1" را نیز در صورت وجود حذف کنید. .. همه قوانین بدیهی و معمول ..

شما معمولاً از git merge-index به همراه git merge-one-file ارائه‌شده برای انجام این مرحله آخر استفاده می‌کنید. این اسکریپت فایل‌های موجود در درخت کاری را هنگام ادغام هر مسیر و در پایان یک ادغام موفقیت‌آمیز به‌روزرسانی می‌کند.

هنگامی که یک ادغام ۳-طرفه را با فایل شاخصی آغاز می‌کنید که از قبل پر شده است، فرض بر این است که نشان‌دهنده وضعیت فایل‌ها در درخت کاری شماست، و حتی می‌توانید فایل‌هایی با تغییرات ثبت‌نشده در فایل شاخص داشته باشید. علاوه بر این فرض می‌شود که این وضعیت از درخت مرحله ۲ "مشتق شده" است. اگر ادغام ۳-طرفه مدخلی را در فایل شاخص اصلی پیدا کند که با مرحله ۲ مطابقت ندارد، از اجرا خودداری می‌کند.

این کار برای جلوگیری از، از بین رفتن کارهای در حال پیشرفت شما و مخلوط شدن تغییرات تصادفی شما در یک کامیت ادغام نامرتبط انجام می‌شود. برای نشان دادن این موضوع، فرض کنید از آخرین کامیت ثبت‌شده در مخزن خود شروع می‌کنید:

$ JC=`git rev-parse --
$ git checkout-index -f -u -a $JC

شما ویرایش‌های تصادفی انجام می‌دهید، بدون اینکه git update-index را اجرا کنید. و سپس متوجه می‌شوید که نوک درخت "بالادست" (upstream) شما از زمانی که از آن pull کرده‌اید جلو رفته است:

$ git fetch git://.... linus
$ LT=`git rev-parse FETCH_HEAD`

درخت کاری شما همچنان بر اساس HEAD شما ($JC) است، اما از آن زمان ویرایش‌هایی داشته‌اید. ادغام سه‌طرفه مطمئن می‌شود که از زمان $JC مدخل‌های شاخص را اضافه یا تغییر نداده‌اید، و اگر چنین کاری نکرده باشید، کار درست را انجام می‌دهد. بنابراین با توالی زیر:

$ git read-tree -m -u `git merge-base $JC $LT` $JC $LT
$ git merge-index git-merge-one-file -a
$ echo "Merge with Linus" | \
  git commit-tree `git write-tree` -p $JC -p $LT

آنچه کامیت می‌کنید یک ادغام خالص بین $JC و $LT بدون تغییرات کارهای در حال پیشرفت شما خواهد بود، و درخت کاری شما به نتیجه ادغام به‌روزرسانی می‌شود.

با این حال، اگر تغییرات محلی در درخت کاری داشته باشید که توسط این ادغام بازنویسی شوند، git read-tree از اجرا خودداری می‌کند تا از، از بین رفتن تغییرات شما جلوگیری کند.

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

نکته: قابلیت‌های skip-worktree در git-update-index(1) و read-tree پیش از معرفی دستور git-sparse-checkout(1) وجود داشته‌اند. به کاربران توصیه می‌شود برای نیازهای مرتبط با دریافت پراکنده/skip-worktree به‌جای این دستورات لوله‌کشی (plumbing)، از دستور sparse-checkout استفاده کنند. با این حال، اطلاعات زیر ممکن است برای کاربرانی که تلاش می‌کنند سبک الگوی استفاده‌شده در حالت غیرمخروطی (non-cone mode) دستور sparse-checkout را درک کنند مفید باشد.

قابلیت "دریافت پراکنده" امکان پر کردن پراکنده پوشه کاری را فراهم می‌کند. این قابلیت از بیت skip-worktree (به git-update-index(1) مراجعه کنید) استفاده می‌کند تا به گیت بگوید آیا یک فایل در پوشه کاری ارزش بررسی دارد یا خیر.

دستور git read-tree و سایر دستورات مبتنی بر ادغام (git merge، git checkout و غیره) می‌توانند به نگهداری بیت‌مپ skip-worktree و به‌روزرسانی پوشه کاری کمک کنند. فایل $GIT_DIR/info/sparse-checkout برای تعریف بیت‌مپ مرجع skip-worktree استفاده می‌شود. هنگامی که git read-tree نیاز به به‌روزرسانی پوشه کاری دارد، بیت skip-worktree را در شاخص بر اساس این فایل (که از نحوی مشابه فایل‌های gitignore. استفاده می‌کند) بازنشانی می‌کند. اگر یک مدخل با الگویی در این فایل مطابقت داشته باشد، یا مدخل مربوط به فایلی باشد که در پوشه کاری وجود دارد، آنگاه بیت skip-worktree روی آن مدخل تنظیم نخواهد شد. در غیر این صورت، skip-worktree تنظیم می‌شود.

سپس مقدار جدید skip-worktree را با مقدار قبلی مقایسه می‌کند. اگر skip-worktree از حالت تنظیم‌شده به تنظیم‌نشده تغییر کند، فایل مربوطه را بازمی‌گرداند. اگر از تنظیم‌نشده به تنظیم‌شده تغییر کند، آن فایل حذف خواهد شد.

در حالی که $GIT_DIR/info/sparse-checkout معمولاً برای مشخص کردن فایل‌های موجود استفاده می‌شود، می‌توانید با استفاده از الگوهای نفی مشخص کنید چه فایل‌هایی نباید موجود باشند. به عنوان مثال، برای حذف فایل unwanted:

/*
!unwanted

مورد پیچیده دیگر، پر کردن مجدد کامل پوشه کاری در زمانی است که دیگر نیازی به دریافت پراکنده ندارید. شما نمی‌توانید صرفاً "دریافت پراکنده" را غیرفعال کنید زیرا بیت‌های skip-worktree هنوز در شاخص هستند و پوشه کاری شما همچنان به‌صورت پراکنده پر شده است. شما باید پوشه کاری را با محتوای فایل $GIT_DIR/info/sparse-checkout به شرح زیر مجدداً پر کنید:

/*

سپس می‌توانید دریافت پراکنده را غیرفعال کنید. پشتیبانی از دریافت پراکنده در git read-tree و دستورات مشابه به‌طور پیش‌فرض غیرفعال است. برای داشتن پشتیبانی از دریافت پراکنده، باید core.sparseCheckout را فعال کنید.

git-write-tree(1), git-ls-files(1), gitignore(5), git-sparse-checkout(1)

بخشی از مجموعه git(1)

2026-06-29 Git 2.55.0