Починаючи з мерзотником 1,9 / 2,0 Q1 2014 року, ви не повинні будете відзначати свій попередній філія походження , перш ніж перебазування його на переписаною вгору по течії гілки, як описано в Аристотель Pagaltzis «s відповідь :
Див здійснювати 07d406b і здійснювати d96855f :
Після роботи над topicгілкою, створеною за допомогою git checkout -b topic origin/master, історія віддаленого відстеження гілки, origin/masterможливо, була перемотана і перебудована, що призвело до історії такої форми:
o---B1
/
---o---o---B2--o---o---o---B (origin/master)
\
B3
\
Derived (topic)
де origin/masterвикористовується , щоб вказати на фіксацій B3, B2, B1і тепер він вказує на B, і ваша topicгілка була розпочата на вершині його назад , коли origin/masterбув B3.
Цей режим використовує рефлог origin/masterдля пошуку B3в якості точки розгалуження, щоб topicможна було перебазувати поверх оновленогоorigin/master за допомогою:
$ fork_point=$(git merge-base --fork-point origin/master topic)
$ git rebase --onto origin/master $fork_point topic
Ось чому git merge-baseкоманда має нову опцію:
--fork-point::
Знайдіть точку, в якій гілка (або будь-яка історія, до якої веде <commit>) відгалужується від іншої гілки (або будь-якого посилання) <ref>.
Це не просто шукає спільного предка двох комітів<ref><commit><ref> , але також бере до уваги переробку даних, щоб побачити, чи історія, що веде до розщеплення з попереднього втілення гілки .
Команда " git pull --rebase" обчислює точку розгалуження гілки, що перебазується, за допомогою записів перезапису baseгілки (зазвичай гілки віддаленого відстеження), на якій базувалася робота гілки, щоб справитись із випадком, коли "база" гілка була перемотана і відновлена.
Наприклад, якщо історія виглядала так: де:
- поточний наконечник "
base" гілки знаходиться в B, але раніше завантаження зауважив, що його наконечник був B3і тоді B2і потім, B1
перш ніж дійти до поточного коміту,
- гілка, що перебазується поверх останньої "бази", базується на коміті
B3,
він намагається знайти B3, перейшовши через вихід « git rev-list --reflog base» (тобто B, B1, B2, B3) до тих пір , поки не знайде фіксації , що є предком поточного наконечника « Derived (topic)».
Внутрішньо, ми get_merge_bases_many()можемо обчислити це одним рухом.
Ми хотіли б базу злиття між Derivedі фіктивним комітом злиття, який вийшов би шляхом об'єднання всіх історичних підказок " base (origin/master)".
Коли такий коміт існує, ми повинні отримати єдиний результат, який точно відповідає одному із записів перезапису " base".
Git 2.1 (Q3 2014) додасть, зробить цю функцію більш надійною до цього: див. Коміт 1e0dacd , Джон Кепінг ( johnkeeping)
правильно обробляти сценарій, де ми маємо таку топологію:
C --- D --- E <- dev
/
B <- master@{1}
/
o --- B' --- C* --- D* <- master
де:
B'є виправленою версією, Bяка не є ідентичною виправленням B;
C*і D*ідентичні патчам Cі, Dвідповідно, і конфліктують у текстовому відношенні, якщо застосовуються в неправильному порядку;
Eзалежить від тексту D.
Правильний результат в git rebase master devтому , що Bідентифікується як вилочні точка devі master, таким чином , що C, D, Eє коммітов які повинні бути перетвореними на master; але Cі Dє ідентичними патчам з C*і D*і тому можна скинути, так що кінцевий результат:
o --- B' --- C* --- D* --- E <- dev
Якщо точка розгалуження не ідентифікована, тоді вибір Bна гілці, що містить, B'призводить до конфлікту, а якщо ідентичні фіксації комітів невірно визначені, тоді вибір Cна гілці, що містить D(або еквівалентно D*), призводить до конфлікту.
Режим " --fork-point" " git rebase" регресував, коли команда була переписана на C ще в епоху 2.20, що було виправлено за допомогою Git 2.27 (Q2 2020).
Див. Коміт f08132f (09 грудня 2019 р.) Хуніо С Хамано ( gitster) .
(Об’єднано Junio C Hamano - gitster- у комітеті fb4175b , 27 березня 2020 р.)
rebase: --fork-pointвиправлення регресії
Підписав: Алекс Торок
[jc: оновив виправлення та використовував тести Алекса]
Підписав: Хуніо С Хамано
" git rebase --fork-point master" раніше працював нормально, як "" він внутрішньо називав " git merge-base --fork-point", що знав, як обробляти коротке refname і вводити його до повного refname перед викликом базової get_fork_point()функції.
Це більше не відповідає дійсності після того, як команда була переписана на C, оскільки її внутрішній виклик, зроблений безпосередньо на get_fork_point(), не зменшує короткий опис.
Перемістіть аргумент "dwim refname до повної імені ref", що використовується в "git merge-base", до базової get_fork_point()функції, щоб інший виклик функції у реалізації "git rebase" поводився так само, щоб виправити ця регресія.