українська мова ▾ Topics ▾ Latest version ▾ git-read-tree last updated in 2.43.0

НАЗВА

git-read-tree - Зчитує інформацію про дерево в індекс

СИНОПСИС

git read-tree [(-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>)
		[-u | -i]] [--index-output=<file>] [--no-sparse-checkout]
		(--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])

ОПИС

Зчитує інформацію про дерево, надану <tree-ish>, в індекс, але фактично не оновлює жодного з файлів, які він "кешує". (див.: git-checkout-index[1])

За бажанням, він може об’єднати дерево з індексом, виконати швидке перемотування вперед (тобто двостороннє) злиття або тристороннє злиття з прапорцем -m. При використанні з -m, прапорець -u також призводить до оновлення файлів у робочому дереві результатом злиття.

Тільки тривіальні злиття виконує сам «git read-tree». Тільки конфліктуючі шляхи будуть у необ’єднаному стані, коли «git read-tree» поверне значення.

ОПЦІЇ

-m

Виконайте об’єднання, а не просто читання. Команда відмовиться виконуватися, якщо ваш індексний файл містить необ’єднані записи, що вказує на те, що ви не завершили попереднє розпочате об’єднання.

--reset

Те саме, що й -m, за винятком того, що необ’єднані записи відкидаються, а не призводять до невдачі. При використанні з -u оновлення, що призводять до втрати змін робочого дерева або невідстежуваних файлів чи каталогів, не перервуть операцію.

-u

Після успішного об’єднання оновіть файли в робочому дереві результатом об’єднання.

-i

Зазвичай для злиття потрібно, щоб індексний файл, а також файли в робочому дереві були оновлені відповідно до поточного головного коміту, щоб не втратити локальні зміни. Цей прапорець вимикає перевірку з робочим деревом і призначений для використання під час створення злиття дерев, які не пов’язані безпосередньо з поточним станом робочого дерева, у тимчасовий індексний файл.

-n
--dry-run

Перевірте, чи команда не призведе до помилки без оновлення індексу або файлів у робочому дереві.

-v

Відображати перебіг вилучення файлів.

--trivial

Обмежити тристороннє злиття за допомогою git read-tree лише за умови відсутності потреби у злитті на рівні файлів, замість вирішення злиття для тривіальних випадків та залишення конфліктуючих файлів невирішеними в індексі.

--aggressive

Зазвичай тристороннє злиття за допомогою git read-tree вирішує злиття для справді тривіальних випадків та залишає інші випадки невирішеними в індексі, щоб porcelains могли реалізувати різні політики злиття. Цей прапорець змушує команду вирішувати ще кілька випадків внутрішньо:

  • коли одна сторона видаляє шлях, а інша сторона залишає його незмінним. Рішення полягає у видаленні цього шляху.

  • коли обидві сторони прибирають шлях. Рішення полягає в тому, щоб прибрати цей шлях.

  • коли обидві сторони додають однаковий шлях. Рішення полягає в тому, щоб додати цей шлях.

--prefix=<prefix>

Зберегти поточний вміст індексу та прочитати вміст іменованого дерева в каталозі за адресою <префікс>. Команда відмовиться перезаписувати записи, які вже існували в оригінальному файлі індексу.

--index-output=<file>

Замість запису результатів у $GIT_INDEX_FILE, запишіть результуючий індекс у названий файл. Під час виконання команди оригінальний індексний файл блокується тим самим механізмом, що й зазвичай. Файл має дозволяти перейменування(2) з тимчасового файлу, який створюється поруч зі звичайним індексним файлом; зазвичай це означає, що він має бути в тій самій файловій системі, що й сам індексний файл, і вам потрібен дозвіл на запис до каталогів, у яких розташовані індексний файл та вихідний файл індексу.

--[no-]recurse-submodules

Використання --recurse-submodules оновить вміст усіх активних підмодулів відповідно до коміту, записаного в суперпроекті, шляхом рекурсивного виклику read-tree, а також встановить відключення HEAD підмодулів під час цього коміту.

--no-sparse-checkout

Вимкнути підтримку розрідженого оформлення замовлення, навіть якщо core.sparseCheckout має значення true.

--empty

Замість того, щоб читати об’єкти дерева в індекс, просто очистіть його.

-q
--quiet

Тихі, придушені повідомлення зворотного зв’язку.

<tree-ish#>

Ідентифікатор об’єкта(ів) дерева, який(і) потрібно прочитати/об’єднати.

ЗЛИТТЯ

Якщо вказано -m, git read-tree може виконати 3 види злиття: злиття одного дерева, якщо вказано лише 1 дерево, прискорене злиття з 2 деревами або злиття трьох дерев, якщо вказано 3 або більше дерев.

Злиття одного дерева

Якщо вказано лише 1 дерево, git read-tree працює так, ніби користувач не вказав -m, за винятком того, що якщо оригінальний індекс має запис для заданого шляху, і вміст шляху збігається з деревом, яке зчитується, використовується статистика з індексу. (Іншими словами, stat() індексу мають пріоритет над stat() об’єднаного дерева).

Це означає, що якщо ви виконаєте команду git read-tree -m <нове дерево>, а потім git checkout-index -f -u -a, то git checkout-index перевіряє лише ті речі, які дійсно змінилися.

Це використовується для уникнення непотрібних помилкових збігів, коли «git diff-files» виконується після «git read-tree».

Злиття двох дерев

Зазвичай це викликається як git read-tree -m $H $M, де $H — це головний коміт поточного репозиторію, а $M — це заголовок стороннього дерева, який знаходиться просто перед $H (тобто ми знаходимося в ситуації швидкого перемотування вперед).

Коли вказано два дерева, користувач повідомляє git read-tree наступне:

  1. Поточний індекс та робоче дерево походять від $H, але користувач може мати локальні зміни в них з моменту $H.

  2. Користувач хоче перемотати вперед до $M.

У цьому випадку команда 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

У всіх випадках "збереження індексу" запис індексу залишається таким, як у вихідному файлі індексу. Якщо запис не оновлений, git read-tree зберігає копію в робочому дереві недоторканою під час роботи з прапорцем -u.

Коли ця форма git read-tree успішно поверне результат, ви зможете побачити, які з внесених вами "локальних змін" були перенесені далі за допомогою запуску git diff-index --cached $M. Зауважте, що це не обов’язково збігається з тим, що створив би git diff-index --cached $H до такого злиття двох дерев. Це пов’язано з випадками 18 та 19 — якщо у вас вже були зміни в $M (наприклад, можливо, ви отримали їх електронною поштою у формі патча), git diff-index --cached $H повідомив би вам про зміну до цього злиття, але вона не відобразиться у виводі git diff-index --cached $M після злиття двох дерев.

Випадок 3 дещо складний і потребує пояснення. Результатом цього правила логічно має бути видалення шляху, якщо користувач виконав поетапне видалення шляху, а потім перейшов на нову гілку. Однак це запобіжить початковому перевірці, тому правило змінюється таким чином, щоб використовувати M (нове дерево) лише тоді, коли вміст індексу порожній. В іншому випадку видалення шляху зберігається, поки $H та $M однакові.

3-стороннє злиття

Кожен запис "індексу" має два біти стану "stage". stage 0 є звичайним станом, і це єдиний стан, який ви побачите під час будь-якого нормального використання.

Однак, коли ви виконуєте git read-tree з трьома деревами, "стадія" починається з 1.

Це означає, що ви можете зробити

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

і ви отримаєте індекс з усіма записами <tree1> у "stage1", усіма записами <tree2> у "stage2" та всіма записами <tree3> у "stage3". Під час виконання злиття іншої гілки з поточною гілкою ми використовуємо дерево спільного предка як <tree1>, поточну гілку як <tree2> та іншу гілку як <tree3>.

Крім того, git read-tree має логіку для спеціальних випадків, яка говорить: якщо ви бачите файл, який відповідає всім наступним станам, він "згортається" назад до "stage0":

  • етапи 2 та 3 однакові; візьміть один або інший (різниці немає — та сама робота була виконана над нашою гілкою на етапі 2 та їхньою гілкою на етапі 3)

  • етап 1 та етап 2 однакові, а етап 3 відрізняється; візьмемо етап 3 (наша гілка на етапі 2 нічого не робила з часів предка на етапі 1, поки їхня гілка на етапі 3 працювала над цим)

  • етап 1 та етап 3 однакові, а етап 2 відрізняється, візьмемо етап 2 (ми щось зробили, а вони нічого не зробили)

Команда git write-tree відмовляється записувати безглузде дерево та скаржитися на необ’єднані записи, якщо побачить один запис, який не є етапом 0.

Гаразд, все це звучить як набір абсолютно безглуздих правил, але насправді це саме те, що вам потрібно для швидкого об’єднання. Різні етапи представляють "дерево результатів" (етап 0, також відоме як "об’єднане"), початкове дерево (етап 1, також відоме як "оригінал") та два дерева, які ви намагаєтеся об’єднати (етапи 2 та 3 відповідно).

Порядок етапів 1, 2 та 3 (звідси порядок трьох аргументів командного рядка <tree-ish>) є важливим, коли ви починаєте 3-стороннє злиття з індексним файлом, який уже заповнений. Ось короткий опис того, як працює алгоритм:

  • Якщо файл існує в ідентичному форматі в усіх трьох деревах, він автоматично згорнеться до стану "об’єднано" командою git read-tree.

  • Файл, який має будь-яку різницю в трьох деревах, залишатиметься окремими записами в індексі. "Порцелянова політика" визначатиме, як видалити етапи, відмінні від 0, та вставити об’єднану версію.

  • Індексний файл зберігає та відновлює всю цю інформацію, тому ви можете об’єднувати елементи поступово, але доки в ньому є записи на етапах 1/2/3 (тобто "необ’єднані записи"), ви не можете записати результат. Отже, тепер алгоритм об’єднання виявляється дуже простим:

    • Ви проходите індекс по порядку та ігноруєте всі записи етапу 0, оскільки вони вже були оброблені.

    • Якщо ви знайдете "stage1", але не знайдете відповідних "stage2" або "stage3", ви знатимете, що його було видалено з обох дерев (він існував лише в початковому дереві), і ви видалите цей запис.

    • Якщо ви знайдете відповідне дерево "stage2" та "stage3", ви видалите одне з них, а інше перетворите на запис "stage0". Видаліть будь-який відповідний запис "stage1", якщо він також існує…​ всі звичайні тривіальні правила…​

Зазвичай для виконання цього останнього кроку використовується git merge-index з наданим git merge-one-file. Скрипт оновлює файли в робочому дереві під час об’єднання кожного шляху та в кінці успішного об’єднання.

Коли ви запускаєте 3-стороннє злиття з індексним файлом, який уже заповнений, вважається, що він відображає стан файлів у вашому робочому дереві, і ви навіть можете мати файли зі змінами, не записаними в індексному файлі. Крім того, вважається, що цей стан "походить" з дерева етапу 2. 3-стороннє злиття відмовляється виконуватися, якщо воно знаходить запис у вихідному індексному файлі, який не відповідає етапу 2.

Це зроблено для того, щоб запобігти втраті змін у вашій роботі та змішуванню випадкових змін у непов’язаному коміті злиття. Для ілюстрації, припустимо, що ви починаєте з того, що було закомічено останнім до вашого репозиторію:

$ JC=`git rev-parse --verify "HEAD^0"`
$ git checkout-index -f -u -a $JC

Ви робите випадкові редагування, не запускаючи git update-index. А потім помічаєте, що верхівка вашого "висхідного" дерева просунулася з моменту вилучення від нього:

$ 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]. Користувачам рекомендується використовувати команду sparse-checkout замість цих команд плавучості для потреб, пов’язаних зі sparse-checkout/skip-worktree. Однак, наведена нижче інформація може бути корисною для користувачів, які намагаються зрозуміти стиль шаблону, що використовується в неконусному режимі команди sparse-checkout.

«Різдке отримання» дозволяє розріджено заповнювати робочий каталог. Він використовує біт skip-worktree (див. git-update-index[1]), щоб повідомити Git, чи варто переглядати файл у робочому каталозі.

Команда «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

Ще одна складна річ — це повне перезаповнення робочого каталогу, коли вам більше не потрібне розріджене отримання. Ви не можете просто вимкнути "розріджене отримання", оскільки біти skip-worktree все ще знаходяться в індексі, а ваш робочий каталог все ще розріджено заповнений. Вам слід перезаповнити робочий каталог вмістом файлу $GIT_DIR/info/sparse-checkout наступним чином:

/*

Тоді ви можете вимкнути розріджене оформлення. Підтримка розрідженого оформлення в git read-tree та подібних командах вимкнена за замовчуванням. Вам потрібно ввімкнути core.sparseCheckout, щоб мати підтримку розрідженого оформлення.

GIT

Частина набору git[1]