Починаючи з мерзотником 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" поводився так само, щоб виправити ця регресія.