| GIT-READ-TREE(1) | دستورات عمومی کاربر | GIT-READ-TREE(1) |
نام (NAME)
git-read-tree - خواندن اطلاعات درخت به درون شاخص
خلاصه دستور (SYNOPSIS)
git read-tree [(-[--rivial] [--ggressive] | --eset | --refix=<prefix>)
[-u | -i]] [--index-output=<file>] [--0-sparse-checkout]
(--\mpty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])
توضیحات (DESCRIPTION)
اطلاعات درخت دادهشده توسط <tree-ish> را به درون شاخص (index) میخواند، اما در عمل هیچیک از فایلهایی را که "کَش" میکند بهروزرسانی نمیکند. (ببینید: git-checkout-index(1))
بهصورت اختیاری، میتواند با پرچم -m یک درخت را در شاخص ادغام کند، یک ادغام روبهجلو (یعنی ۲-طرفه) انجام دهد، یا یک ادغام ۳-طرفه را به سرانجام برساند. هنگامی که همراه با -m استفاده شود، پرچم -u باعث میشود فایلهای موجود در درخت کاری (work tree) نیز با نتیجه ادغام بهروزرسانی شوند.
تنها ادغامهای بدیهی (trivial merges) توسط خود git read-tree انجام میشوند. هنگامی که git read-tree بازمیگردد، تنها مسیرهای دارای تداخل در وضعیت ادغامنشده (unmerged) باقی خواهند ماند.
گزینهها (OPTIONS)
-m
--eset
-u
-i
-n, --ry-run
-v
--rivial
--ggressive
--refix=<prefix>
--index-output=<file>
--ecurse-submodules, --0-recurse-submodules
--0-sparse-checkout
--\mpty
-q, --quiet
<tree-ish#>
ادغام (MERGING)
اگر -m مشخص شده باشد، git read-tree میتواند ۳ نوع ادغام انجام دهد: ادغام تکدرختی در صورتی که فقط ۱ درخت داده شده باشد، ادغام روبهجلو با ۲ درخت، یا یک ادغام ۳-طرفه در صورتی که ۳ یا چند درخت ارائه شده باشد.
Single Tree Merge
اگر تنها ۱ درخت مشخص شود، 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 استفاده میشود.
Two Tree Merge
معمولاً این دستور بهصورت git read-tree -m $H $M فراخوانی میشود، که در آن H$ کامیت head مخزن فعلی است، و M$ سربرگ یک درخت بیگانه است که صرفاً جلوتر از H$ قرار دارد (یعنی ما در یک وضعیت ادغام روبهجلو یا fast-forward هستیم).
هنگامی که دو درخت مشخص میشوند، کاربر موارد زیر را به git read-tree میگوید:
در این حالت، دستور 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$ یکسان باشند حفظ میشود.
3-Way Merge
هر مدخل "شاخص" دارای دو بیت وضعیت "مرحله" (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 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 با صدای بلند اعتراض کرده و بدون تغییر هیچچیز با شکست مواجه میشود). در چنین حالتی، میتوانید به سادگی به انجام کاری که در میانه آن بودید ادامه دهید، و هنگامی که درخت کاری شما آماده شد (یعنی کارهای در حال پیشرفت خود را تمام کردید)، ادغام را دوباره امتحان کنید.
دریافت پراکنده (SPARSE CHECKOUT)
نکته: قابلیتهای 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 را فعال کنید.
همچنین ببینید (SEE ALSO)
git-write-tree(1), git-ls-files(1), gitignore(5), git-sparse-checkout(1)
گیت (GIT)
بخشی از مجموعه git(1)
| 2026-06-29 | Git 2.55.0 |