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

НАЗВА

git-merge-base - Знайдіть якомога більше спільних предків для злиття

СИНОПСИС

git merge-base [-a | --all] <commit> <commit>…​
git merge-base [-a | --all] --octopus <commit>…​
git merge-base --is-ancestor <commit> <commit>
git merge-base --independent <commit>…​
git merge-base --fork-point <ref> [<commit>]

ОПИС

«git merge-base» знаходить найкращого спільного предка (або спільних предків) між двома комітами для використання у тристоронньому злитті. Один спільний предок є «кращим» за іншого спільного предка, якщо останній є предком першого. Спільний предок, який не має жодного кращого спільного предка, є «найкращим спільним предком», тобто «базою злиття». Зверніть увагу, що для пари комітів може бути більше однієї бази злиття.

РЕЖИМИ РОБОТИ

У найпоширенішому окремому випадку, зазначення лише двох комітів у командному рядку означає обчислення бази злиття між двома заданими комітами.

У більш загальному випадку, серед двох комітів, з яких обчислюється база злиття, один визначається першим аргументом коміта в командному рядку; інший коміт є (можливо, гіпотетичним) комітом, який є злиттям усіх решти комітів у командному рядку.

Як наслідок, «база злиття» не обов’язково міститься в кожному з аргументів комітів, якщо вказано більше двох комітів. Це відрізняється від git-show-branch[1], коли використовується з опцією --merge-base.

--octopus

Обчисліть найкращих спільних предків усіх наданих комітів, готуючись до n-стороннього злиття. Це імітує поведінку git show-branch --merge-base.

--independent

Замість виведення баз злиття, виведіть мінімальну підмножину наданих комітів з тими ж предками. Іншими словами, серед наданих комітів перелічіть ті, до яких неможливо дістатися з жодного іншого. Це імітує поведінку git show-branch --independent.

--is-ancestor

Перевірити, чи перший <commit> є предком другого <commit>, та завершити роботу зі статусом 0, якщо це правда, або зі статусом 1, якщо ні. Помилки сигналізуються ненульовим статусом, який не дорівнює 1.

--fork-point

Знайти точку, в якій гілка (або будь-яка історія, що веде до <commit>) відгалужується від іншої гілки (або будь-якого посилання) <ref>. Це не лише шукає спільного предка двох комітів, але й враховує рефлог <ref>, щоб побачити, чи історія, що веде до <commit>, відгалужується від попередньої версії гілки <ref> (див. обговорення цього режиму нижче).

ОПЦІЇ

-a
--all

Вивести всі бази злиття для комітів, а не лише одну.

ОБГОВОРЕННЯ

Враховуючи два коміти A та B, git merge-base A B виведе коміт, який доступний як з A, так і з B через батьківське відношення.

Наприклад, з такою топологією:

	 o---o---o---B
	/
---o---1---o---o---o---A

База злиття між A та B дорівнює 1.

Враховуючи три коміти A, B та C, git merge-base A B C обчислить базу злиття між A та гіпотетичним комітом M, який є злиттям між B та C. Наприклад, з такою топологією:

       o---o---o---o---C
      /
     /   o---o---o---B
    /   /
---2---1---o---o---o---A

Результат git merge-base A B C дорівнює 1. Це тому, що еквівалентна топологія зі злиттям M між B та C така:

       o---o---o---o---o
      /                 \
     /   o---o---o---o---M
    /   /
---2---1---o---o---o---A

а результатом git merge-base A M є 1. Commit 2 також є спільним предком між A та M, але 1 є кращим спільним предком, оскільки 2 є предком 1. Отже, 2 не є базою злиття.

Результатом виконання git merge-base --octopus A B C буде 2, оскільки 2 є найкращим спільним предком усіх комітів.

Коли історія включає перехресні злиття, може бути більше одного «найкращого» спільного предка для двох комітів. Наприклад, з такою топологією:

---1---o---A
    \ /
     X
    / \
---2---o---o---B

Як 1, так і 2 є базами злиття A та B. Жодна з них не краща за іншу (обидві є «найкращими» базами злиття). Якщо опція --all не вказана, не вказано, яка з них найкраща виводиться.

Поширеною ідіомою для перевірки "швидкого перемотування" між двома комітами A та B є (або принаймні раніше використовувалася) обчислення бази злиття між A та B та перевірка, чи вона така ж, як A, і в цьому випадку A є предком B. Ви часто побачите цю ідіому у старіших скриптах.

A=$(git rev-parse --verify A)
if test "$A" = "$(git merge-base A B)"
then
	... A is an ancestor of B ...
fi

У сучасному git це можна сказати більш прямо:

if git merge-base --is-ancestor A B
then
	... A is an ancestor of B ...
fi

замість цього.

Обговорення режиму розгалуження

Після роботи над гілкою topic, створеною за допомогою git switch -c topic origin/master, історія гілки віддаленого відстеження origin/master могла бути перемотана та перебудована, що призвело до історії такої форми:

		 o---B2
		/
---o---o---B1--o---o---o---B (origin/master)
	\
	 B0
	  \
	   D0---D1---D (topic)

де origin/master раніше вказував на коміти B0, B1, B2, а тепер вказує на B, і ваша гілка topic була запущена поверх неї, коли origin/master була в B0, і ви створили три коміти, D0, D1 та D, поверх неї. Уявіть, що тепер ви хочете перебазувати роботу, яку ви виконали над темою, поверх оновленого origin/master.

У такому випадку, git merge-base origin/master topic поверне батьківський елемент B0 на зображенні вище, але B0^..D не є діапазоном комітів, які ви хочете відтворити поверх B (він включає B0, що не те, що ви написали; це коміт, який інша сторона відкинула, коли перемістила свою кінчику з B0 до B1).

Команда git merge-base --fork-point origin/master topic розроблена для допомоги в такому випадку. Вона враховує не лише B, але й B0, B1 та B2 (тобто старі підказки гілок віддаленого відстеження, про які знає reflog вашого репозиторію), щоб побачити, на якому коміті була зібрана ваша тематична гілка, та знаходить B0, що дозволяє вам відтворити лише коміти у вашій темі, виключаючи коміти, які інша сторона пізніше відкинула.

Отже

$ fork_point=$(git merge-base --fork-point origin/master topic)

знайде B0, і

$ git rebase --onto origin/master $fork_point topic

відтворить D0, D1 та D поверх B, щоб створити нову історію цієї фігури:

		 o---B2
		/
---o---o---B1--o---o---o---B (origin/master)
	\                   \
	 B0                  D0'--D1'--D' (topic - updated)
	  \
	   D0---D1---D (topic - old)

Застереження полягає в тому, що старіші записи reflog у вашому репозиторії можуть бути застарілі за допомогою git gc. Якщо B0 більше не відображається в reflog гілки віддаленого відстеження origin/master, режим --fork-point очевидно не може його знайти та завершує роботу, уникаючи видачі випадкового та непотрібного результату (наприклад, батьківського елемента B0, як це дає та сама команда без опції --fork-point).

Також, гілка віддаленого відстеження, з якою ви використовуєте режим --fork-point, має бути тією, з якої ваша тема відгалужується від її кінчика. Якщо ви відгалужувалися від коміту, старішого за кінчик, цей режим не знайде точку відгалуження (уявіть, що у наведеному вище прикладі історії B0 не існує, origin/master починався з B1, перемістився до B2, а потім до B, і ви відгалужували свою тему в origin/master^, коли origin/master був B1; форма історії була б такою ж, як і вище, без B0, а батьківська гілка B1 - це те, що git merge-base origin/master topic правильно знаходить, але режим --fork-point не знайде цього, оскільки це не один з комітів, які раніше були на кінчику origin/master).

GIT

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