українська мова ▾ Topics ▾ Latest version ▾ git-read-tree last updated in 2.52.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>

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

--index-output=<file>

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

--recurse-submodules
--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 з трьома деревами, "stage" починається з 1.

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

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

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

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

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

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

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

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

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

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

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

  • файл, який має хоч би якусь відмінність у трьох деревах, залишиться в індексі як окремий запис. Визначення того, як видалити етапи, що не дорівнюють 0, та вставити об’єднану версію, залежить від політики «porcelain».

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

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

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

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

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

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